powershellpowershell-5.0powershell-5.1

Include Enum's from another file


In my Powershell "project" I would like to have all the common Enum's in a single file and then reference that file from the various other scripts.

I've tried dot-sourcing the file, and I tried converting the Enum file to a psm1 (Import-Module), but nothing I've tried so far has worked.

For example, the Enum file datatypes.ps1 looks something like this:

Enum DataType { String, Integer, Boolean }

And I tried to include it like this:

. ".\datatypes.ps1"

class MyClass {
    [DataType]$Type = [DataType]::String
}

When I run the above I get the error message:

Unable to find type [DataType].

I've used dot-sourcing to include variables and functions before, those have always worked. But now the Enum's are refusing to work :(

Should dot-sourcing work? Should the module approach work? or must Enum's be located in the same file/script?

EDIT:

I think I might have found the problem, it seems that the script is being completely parsed before the include is being included, is that possibly the issue?


Solution

  • I believe Import-Module does not work, because it loads items in to a different context. You can use the dot sourcing or the using module statement. If you are using the latter, then you need to provide a fully path to the file or place it in one of the $env:PSModulePath paths.

    If you want to import enums or classes in to a module I find the approach below works best, i.e. dot sourcing the full filenames in the module psm1 file.

    Assuming a basic project layout like:

    - MyModule
        |- Classes
            |- MyClasses.ps1
        |- Enums
            |- MyEnums.ps1
        |- MyModule.psm1
        |- MyModule.psd1
    

    MyModule.psm1

    if (Test-Path -Path "$PSScriptRoot\Classes") {
        $Enums = Get-ChildItem (Join-Path $PSScriptRoot Enums) -Filter *.ps1 -ErrorAction SilentlyContinue
        $Classes = Get-ChildItem (Join-Path $PSScriptRoot Classes) -Filter *.ps1 -ErrorAction SilentlyContinue
    
        # Order imports so that Enums are before Classes
        foreach ($Class in @($Enums;$Classes)) {
            Try {
                . $Class.FullName
                Write-Verbose -Message "Imported $($Class.BaseName)"
            }
            Catch {
                Write-Error -Message "Could not load Class [$($Class.Name)] : $($_.Message)"
            }
        }
    }
    
    # Import functions here if you have them, or do anything else.