如何在Powershell模块中创建一个可供该模块中其他函数访问的变量?

时间:2017-03-23 04:52:07

标签: powershell

我有一个powershell模块,它定义了一些根据公司标准编写日志事件的基本函数,以及另一个创建日志文件应该进入的文件夹的单个函数,并重新启动日志记录应用程序服务。

每个写入不同严重程度的日志事件的函数都需要使用$LogFileLocation变量(在创建文件夹的函数中设置,重新启动服务并且通常让系统准备好开始记录)但是{{1变量仅在进行设置的函数内可用。

如何将其用于其他功能,包括导入模块的脚本中的任何脚本函数?我尝试过$LogFileLocation而不仅仅是Global:$LogFileLocation,但这似乎并没有使它成为一个全局变量。

2 个答案:

答案 0 :(得分:2)

将变量及其赋值($LogFile = 'C:\path\to\file.log')放在.psm1文件的顶部,它将成为模块级变量,从而使其可用于所有模块中的功能。

答案 1 :(得分:1)

在您的模块中定义此功能:

Function Set-MyModuleLogPath {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [ValidateScript({Test-Path $_ -PathType Leaf})] #include this if you want to ensure the path exists before using (or add logic to create the path below)
        [String]$Path
    )
    process {
        (New-Variable -Name 'LogFileLocation' -Value (Resolve-Path $Path).Path -Option 'Constant' -Scope 1 -PassThru).Value
        #For more info on Scope see: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_scopes
    }
}

这使用New-Variable命令将路径值分配给变量,将该变量设置为常量(假设一旦设置,您不希望其他函数在运行时更改此路径;因为这可能导致使用范围广泛的变量来获得不可预测的结果。

Scope参数采用1的参数,这意味着此变量的范围限定为函数定义的容器;在你的情况下是模块脚本。即在模块中定义此函数然后在运行时调用与在模块代码中编写$LogFileLocation = 'c:\path\to\file.log'具有相同的效果;只有你现在有办法避免在模块中对该路径进行硬编码。

路径上的ValidateScript选项具有逻辑Test-Path $_ -PathType Leaf。即我们希望确保所引用的路径有效/已存在;它是一个文件,而不是一个目录。当然,您可能只想验证目录是否存在,然后在运行时创建新文件;或者可以创建在运行时尚未存在的任何内容......您可以根据需要调整此逻辑。

如果某人传入相对路径(即Resolve-Path},则使用'.\default.log';就像工作目录在脚本运行时更改一样,此引用的文件也会更改。它设置为绝对路径,然后锁定此位置。

我建议不要在模块的其他位置引用变量名称(即$Script:LogFileLocation$LogFileLocation),而是建议添加一个Get方法以允许逻辑检查此变量是否已设置,然后用它。当然,这可能是一个不值得的额外开销(即,如果性能比稳健性更重要)......取决于您的要求。

Function Get-MyModuleLogPath {
    [CmdletBinding(DefaultParameterSetName='ErrorIfNotSet')]
    param (
        [Parameter(ParameterSetName='DefaultIfNotSet', Mandatory=$true)]
        [switch]$DefaultIfNotSet
        ,
        [Parameter(ParameterSetName='DefaultIfNotSet')]
        [string]$DefaultPath = '.\default.log'
    )
    process {
        try {
            $path = (Get-Variable -Name 'LogFileLocation' -Scope 1 -ValueOnly -ErrorAction Stop).Value
        } catch {
            if ($DefaultIfNotSet) {
                $path = Set-MyModuleLogPath $path #once we've used the default we want it to become locked as the constant; so this log path won't change at runtime
            } else {
                throw "Please run 'Set-ModuleLogPath' to define a log path before calling 'Get-ModuleLogPath', or use the '-DefaultIfNotSet' switch to allow the default path to be used"
            }
        }
        $path
    }
}