PowerShell 项目,在哪里放置全局设置?

PowerShell project, where to put global settings?

我们正在使用 PowerShell 构建一个更大的项目(scripts/functions 的集合,帮助我们设置一些 SharePoint environments/tenants)。

许多功能应该重用存储在一个集中位置的设置。

我找不到 "best practice" 如何最好地创建和构造这样的设置 file/location。

我的想法是将全局设置存储在一个单独的文件(模块文件)中,例如 Settings.psm1 内容如下:

# Set vars
$global:scriptEnvironment = "SP2016HOSTINGDEV"
$global:logFileName = "z_Migration_to_SP2016.log"
$global:languageMapping = @{
    "en-US" = 1;
    "de-DE" = 2;
}
$global:oldWsps = @(
    [WspFile]@{ Filename = "comapany.solution.wsp"; IsDeployable = $true; IsGloballyDeployable = $false; FullTrustBinDeployment = $false },
    [WspFile]@{ Filename = "company.solution2.server.wsp"; IsDeployable = $true; IsGloballyDeployable = $false; FullTrustBinDeployment = $false }
)
...

在另一个 modules/scripts 中,我总是可以像这样包含这些设置:

# Set vars
$scriptDirectory = Split-Path -parent $PSCommandPath

# Module import
Import-Module (Join-Path $scriptDirectory Settings.psm1) -Force -ErrorAction Stop
Import-Module (Join-Path $scriptDirectory Functions.psm1) -Force -ErrorAction Stop

# Functions
...

所以这将使我能够在其他脚本文件中的函数中使用这样的全局设置:

Function WriteLog
{
    param
    (
        [System.String]$LogString = "",
        [System.String]$LogLevel = ""
    )
    WriteLogToPath -LogFileName $global:logFileName -LogString $LogString -LogLevel $LogLevel
}

这是一个好方法吗?或者我不应该为此使用模块文件,如果不是,我应该使用哪种文件?

我可能会将您所有的 scripts/functions 收集到一个模块中,并使用注册表来存储全局设置。加载模块时从注册表中读取值,并为模块中的每个设置设置具有默认值的变量,以便您可以将缺失值写入注册表。

像这样:

$modulename = Split-Path $PSScriptRoot -Leaf

$default_foo = 'something'
$default_bar = 'or other'
...

function Get-RegistrySetting($name) {
    $path = "HKCU:\Software${script:modulename}"

    if (-not (Test-Path -LiteralPath $path)) {
        New-Item -Path $path -Force | Out-Null
    }

    try {
        Get-ItemProperty $path -Name $name -ErrorAction Stop |
            Select-Object -Expand $name
    } catch {
        $val = Get-Variable -Scope script -Name "default_${name}" -ValueOnly -ErrorAction Stop
        Set-ItemProperty $path -Name $name -Value $val
        $val
    }
}

$global:foo = Get-RegistrySetting 'foo'
$global:bar = Get-RegistrySetting 'bar'
...

对于仅在模块内部使用的变量,您可能希望使用 script 范围而不是 global 范围。

我个人会避免使用注册表。不过我同意使用模块。我的方法是使用一个清单模块(即使用一个 .psd1 文件,它本质上是一个包含关于模块的元数据的键值哈希表),并使用 RootModule 键指定一个 'root' 模块。

模块范围现在由这个 RootModule 设置,您可以在其中定义变量。

您可以将您的函数分离到 'nested' 个模块(另一个清单文件密钥),这些模块由 PowerShell 自动加载到根模块范围内,因此应该可以访问这些变量。

您甚至可以使用该清单文件中的键来控制导出哪些变量和函数。

检查 Get-Configuration Powershell 模块。概念很简单,模块添加了环境变量,其中(在 JSON 中)保存了类型和源的定义。

(dir env:PSGetConfiguration).Value
{
    "Mode":  "Xml",
    "XmlPath":  "C:\Managers\PSGetConfiguration.xml"
}

配置文件非常简单,只包含键和值项

cat $(Get-ConfigurationSource).XmlPath
<Configuration>
  <conf key="ExampleKey" value="ExampleValue" />
  <conf key="key" value="Value123" />
  <conf key="remove" value="remove" />
</Configuration>

模块公开两个主要函数Get-Configuration和Set-Configuration

Set-Configuration -Key k1 -Value v1
Get-Configuration -Key k1
v1

在启动模块时保存 XML 在模块目录中,可以通过手动更改环境变量或使用命令 Set-XmlConfigurationSource

来更改它

SQL 配置

默认模块使用XML来存储数据,但第二种选择是将数据存储在SQL中。设置配置非常简单:

Set-SqlConfigurationSource -SqlServerInstance ".\sql2017" -SqlServerDatabase "ConfigDatabase" -SqlServerSchema "config" -SqlServerTable "Configuration"

之后我们的配置将存储在 SQL table.

代码也可在 github 中找到。