Как вызвать конкретную функцию в скрипте PowerShell из командной строки? - PullRequest
0 голосов
/ 25 марта 2019

Я хочу вызвать определенную функцию в моем скрипте powershell из командной строки. Но это возвращает мне ошибку, как это: Ключ не может быть нулевым.

Parameter name: key
$Get = $ini_file.($a_section).($b_node)

Key cannot be null.
Parameter name: key
$Output = $ini_file.($a_section).($b_node) | Out-File $Store\Val ...

Вот мой код:

Param(
    [Parameter(Mandatory=$true)]
    [string]$FilePath,
    $ini, $a_section, $b_node, $c_store,
    $a, $b, $c
)

function Get-File {
    $input_file = $FilePath
    $ini_file = @{}

    Get-Content $input_file | ForEach-Object {
        $_.Trim()
    } | Where-Object {
        $_ -notmatch '^(;|$)'
    } | ForEach-Object {
        if ($_ -match '^\[.*\]$') {
            $section = $_ -replace '\[|\]'
            $ini_file[$section] = @{}
        } else {
            $key, $value = $_ -split '\s*=\s*', 2
            $ini_file[$section][$key] = $value
        }
    }

    $Get = $ini_file.($a_section).($b_node)
    $Store = $c_store
    $Output = $ini_file.($a_section).($b_node) | Out-File $Store\Value.cmd
}

function Write-File {
    Import-Module PsIni
    $ff = Get-IniContent $FilePath
    $ff["$a"]["$b"] = "$c"  
    $ff | Out-IniFile -FilePath $FilePath -Force
}

# Calling the function with the global parameter $FilePath
Write-File $FilePath $a $b $c 
Get-File $FilePath $ini $a_section $b_node $c_store

Способ вызова каждой функции из командной строки:

Функция вызова Get-File:

powershell.ps1 Get-File -FilePath C:\User\file.ini -a_section Information -b_node Name -c_store C:\User\

Если я выполню эту команду, я все равно смогу получить value файла INI, но он вернет вышеуказанную ошибку. Если я УДАЛЮ эту часть Write-File $FilePath $a $b $c Она не вернет никакой ошибки.

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

Мой INI-файл


    [Information]
    Name=Joyce
    Age=12
    

ОБНОВЛЕННЫЙ КОД:

Function Read-File
{
    Param(
    [parameter(mandatory=$true)]$FilePath,
    [parameter(mandatory=$true)] $ini,
    [parameter(mandatory=$true)] $a_section,
    [parameter(mandatory=$true)] $b_node,
    [parameter(mandatory=$true)] $c_store
    )
    $input_file = $FilePath
    $ini_file = @{}

    Get-Content $input_file | ForEach-Object {
    $_.Trim()
    } | Where-Object {
    $_ -notmatch '^(;|$)'
    } | ForEach-Object {
    if ($_ -match '^\[.*\]$') {
        $section = $_ -replace '\[|\]'
        $ini_file[$section] = @{}
    } else {
        $key, $value = $_ -split '\s*=\s*', 2
        $ini_file[$section][$key] = $value
    }
    }

     $Get = $ini_file.($a_section).($b_node)
     $Store = $c_store
     $Output = $ini_file.($a_section).($b_node) | Out-File $Store\Value.cmd
}

#---------------------------------------------------------------#
Function Write-File
{
    Param(
    [parameter(mandatory=$true)]$FilePath,
    [parameter(mandatory=$true)] $a,
    [parameter(mandatory=$true)] $b,
    [parameter(mandatory=$true)] $c
    )
    Import-Module PsIni
    $ff = Get-IniContent $FilePath
    $ff["$a"]["$b"] = "$c"  
    $ff | Out-IniFile -FilePath $FilePath -Force

}

$cmd, $params = $args
& $cmd @params

1 Ответ

1 голос
/ 25 марта 2019

То, как вы пытаетесь вызвать функцию, не работает, потому что вы передаете аргументы скрипту, но никогда ничего с ними не делаете.Если вы хотите, чтобы функция вызывалась автоматически при запуске сценария, вызовите функцию из сценария.

function Write-IniFile {
    Param(
        ...
    )
    ...
}
Write-IniFile -FilePath C:\Users\file.ini -a Name -b Joyce -c 1309

и запустите сценарий следующим образом:

PS.ps1

В противном случае точка-Исходный код сценария перед вызовом функции:

. PS.ps1
Write-IniFile -FilePath C:\Users\file.ini -a Name -b Joyce -c 1309

Если вы хотите иметь возможность запустить сценарий с параметрами и передать их в функцию, используйте первый подход, но в функции выполните сплат $args:

function Write-IniFile {
    Param(
        ...
    )
    ...
}
Write-IniFile @args

и вызовите скрипт следующим образом:

PS.ps1 -FilePath C:\Users\file.ini -a Name -b Joyce -c 1309

Редактировать:

Если у вас есть скрипт с несколькими функциямии хотите иметь возможность вызывать любого из них, запустив скрипт, который вы могли бы split'n'splat параметры скрипта:

PS.ps1:

function Foo {
    Param(
        [Parameter(Mandatory=$true)]
        $x
    )
    ...
}

function Bar {
    Param(
        [Parameter(Mandatory=$true)]
        $y,
        [Parameter(Mandatory=$true)]
        $z
    )
    ...
}

$cmd, $params = $args
& $cmd @params

Вызов:

PS.ps1 Foo -x 'some'          # invoke Foo() with the given arguments
PS.ps1 Bar -y 'or' -z 'other' # invoke Bar() with the given arguments

Оператор

$cmd, $params = $args

назначает первый аргумент переменной $cmd, а остальные аргументы - переменной $params.Следующий оператор

& $cmd @params

вызывает $cmd через оператор вызова (&) и splats параметры в $params.

...