Проект PowerShell, где поставить глобальные настройки?

Мы создаем более крупный проект с помощью PowerShell (набор скриптов / функций, который помогает нам настраивать некоторые среды / арендаторы SharePoint).

Многие функции должны повторно использовать настройки, которые хранятся в одном центральном месте.

Я не смог найти "наилучшую практику" того, как такой файл / местоположение настроек лучше всего создавать и структурировать.

Моя идея состоит в том, чтобы хранить глобальные настройки в отдельном файле (файле модуля), например 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 }
)
...

А в других модулях / сценариях я всегда мог включить эти настройки следующим образом:

# 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
}

Это хороший подход? Или я не должен использовать файлы модулей для этого, и если нет, то какие файлы я должен использовать вместо этого?

3 ответа

Я, вероятно, собрал бы все ваши скрипты / функции в модуле и использовал бы реестр для хранения глобальных настроек. Прочитайте значения из реестра, когда модуль загружен, и имейте переменные со значениями по умолчанию для каждого параметра в вашем модуле, чтобы вы могли записать пропущенные значения в реестр.

Что-то вроде этого:

$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.

Область действия модуля теперь задается этим RootModule, и вы можете определить свои переменные там.

Вы можете разделить свои функции на "вложенные" модули (другой ключ файла манифеста), и они автоматически загружаются 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 Powershel

При запуске модуль сохраняет XML в каталоге модуля, его можно изменить, изменив вручную переменную среды или используя команду Set-XmlConfigurationSource

Конфигурация SQL

По умолчанию модуль использует XML для хранения данных, но второй вариант - хранить данные в SQL. Настройка конфигурации довольно проста:

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

После этого наш конфиг будет храниться в таблице SQL.

Конфигурация в SQL

Код также доступен в github.

Другие вопросы по тегам