Powershell - переменные проблемы - PullRequest
0 голосов
/ 29 марта 2020

Я написал скрипт, который будет извлекать данные из файла .properties ( в основном файл конфигурации ). Некоторые данные из файла свойств содержат данные среды ( т.е.% UserProfile% ), поэтому я запускаю их через функцию ( Resolve – EnvVariable ), которая заменит переменную среды на реальная стоимость. Замена работает отлично, но каким-то образом данные, кажется, изменены. Когда я пытаюсь использовать значения, которые были пропущены через функцию, они больше не работают (см. Результаты ниже).

Это содержимое файла c: \ work \ test. свойства

types="*.txt"
in="%UserProfile%\Downloads"

Это мой скрипт PowerShell

Clear-Host
#Read the properties file and replace the parameters when specified
if (Test-Path C:\work\test.properties) {
    $propertiesFile = Get-Content C:\work\test.properties
    Write-Host "Parameters will be substituded from properties file" -ForegroundColor Yellow
    foreach ($line in $propertiesFile) {
        Write-Host ("from Properties file $line")
        $propSwitch = $line.Split("=")[0]
        $propValue = Resolve–EnvVariable($line.Split("=")[1])
        switch ($propSwitch) {
            "types" { $types = $propValue }
            "in" { $in = $propValue }
        }
    }
}
write-host ("After running through function `n in=" + $in + "<-   types=" + $types + "<-")

# This function resolves environment variables
Function Resolve–EnvVariable {
    [cmdletbinding()]
    Param(
        [Parameter(Position = 0, ValueFromPipeline = $True, Mandatory = $True,
            HelpMessage = "Enter string with env variable i.e. %APPDATA%")]
        [ValidateNotNullOrEmpty()]
        [string]$String
    )

    Begin {
        Write-Verbose "Starting $($myinvocation.mycommand)"
    } #Begin

    Process {  
        #if string contains a % then process it
        if ($string -match "%\S+%") {
            Write-Verbose "Resolving environmental variables in $String"
            #split string into an array of values
            $values = $string.split("%") | Where-Object { $_ }
            foreach ($text in $values) {
                #find the corresponding value in ENV:
                Write-Verbose "Looking for $text"
                [string]$replace = (Get-Item env:$text -erroraction "SilentlyContinue").Value
                if ($replace) {
                    #if found append it to the new string
                    Write-Verbose "Found $replace"
                    $newstring += $replace
                }
                else {
                    #otherwise append the original text
                    $newstring += $text
                }

            } #foreach value

            Write-Verbose "Writing revised string to the pipeline"
            #write the string back to the pipeline
            Write-Output $NewString
        } #if
        else {
            #skip the string and write it back to the pipeline
            Write-Output $String
        }
    } #Process

    End {
        Write-Verbose "Ending $($myinvocation.mycommand)"
    } #End
} #end Resolve-EnvVariable


# Hardcoded values work
$test1 = Get-ChildItem -Path "C:\Users\Paul\Downloads" -Recurse -Include "*.txt" 

# Values pulled and updated through function do not work
$test2 = Get-ChildItem -Path $in -Recurse -Include $types 

# If I manually assign the values, it works
$in = "C:\Users\Paul\Downloads" 
$types = "*.txt"
$test3 = Get-ChildItem -Path $in -Recurse -Include $types 

foreach ($test in $test1) { write-host "test1 $test" }
foreach ($test in $test2) { write-host "test2 $test" }
foreach ($test in $test3) { write-host "test3 $test" }

Результаты

Parameters will be substituded from properties file
from Properties file types="*.txt"
from Properties file in="%UserProfile%\Downloads"
After running through function 
 in="C:\Users\Paul\Downloads"<-   types="*.txt"<-
test1 C:\Users\Paul\Downloads\Test\testPaul.txt
test1 C:\Users\Paul\Downloads\Test2\File1.txt
test3 C:\Users\Paul\Downloads\Test\testPaul.txt
test3 C:\Users\Paul\Downloads\Test2\File1.txt

1 Ответ

3 голосов
/ 29 марта 2020

Два варианта:

1. Используйте Environment.ExpandEnvironmentVariables()

Если вы переключились на неквалифицированные строковые значения и экранировали \, это было бы так же просто, как передать файл в ConvertFrom-StringData, после чего вы могли бы расширить значения переменных с помощью Environment.ExpandEnvironmentVariables():

Файл свойств:

types=*.txt
in=%UserProfile%\\Downloads

Сценарий:

# Convert file to hashtable
$properties = Get-Content file.properties -Raw |ConvertFrom-StringData

# Copy value to new hashtable, but expand env vars first
$expanded = @{}
foreach($entry in $properties.GetEnumerator()){
    $expanded[$entry.Key] = [Environment]::ExpandEnvironmentVariables($entry.Value)
}

Должен дать вам нужные значения:

PS C:\> $expanded

Name                           Value
----                           -----
in                             C:\Users\username\Downloads
types                          *.txt

2. Используйте для своих свойств сценарий PowerShell и поставьте его точками

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

Файл свойств:

$types = "*.txt"
$in = Join-Path $env:USERPROFILE Downloads

Сценарий:

# dot source the variables
. (Join-Path $PSScriptRoot properties.ps1)

# do the actual work
Get-ChildItem $in -Include $types
...