【问题标题】:How do I make a variable in a Powershell module accessible to other functions in that module?如何使 Powershell 模块中的变量可供该模块中的其他函数访问?
【发布时间】:2017-03-23 04:52:07
【问题描述】:

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

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

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

【问题讨论】:

  • 现有答案可能是正确的方法,但仅供参考,全局范围的正确方法是 $global:logfilelocation

标签: powershell


【解决方案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';好像工作目录随着脚本运行而改变,this 引用的文件也会改变。通过将其解析为绝对路径设置此位置时的路径然后被锁定。

与其在模块中的其他地方(即$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)
        } catch {
            if ($DefaultIfNotSet) {
                $path = Set-MyModuleLogPath $DefaultPath #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
    }
}

【讨论】:

  • $path = (Get-Variable -Name 'LogFileLocation' -Scope 1 -ValueOnly -ErrorAction Stop).Value $path 将为空。我删除了 -ValueOnly 参数并且它起作用了
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 2011-09-09
    • 2011-12-27
    相关资源
    最近更新 更多