1. ホーム
  2. powershell

あるスクリプトからの引数で別のスクリプトを呼び出す

2023-11-08 18:55:40

質問

設定ファイルを読み込むスクリプトがあり、その結果、2 つ目の PowerShell スクリプトの関数に引数として渡したい名前と値のペアのセットが生成されます。

設計時には、この設定ファイルにどのようなパラメーターが配置されるかは分からないので、この 2 番目の PowerShell スクリプトを呼び出す必要がある時点で、私は基本的にこの 2 番目のスクリプトへのパスを持つ 1 つの変数と、パス変数で識別されるスクリプトに渡す引数の配列である 2 番目の変数を持っているだけです。

つまり、2つ目のスクリプトへのパスを含む変数 ( $scriptPath ) のような値を持つかもしれません。

"c:\the\path\to\the\second\script.ps1"

引数を含む変数( $argumentList )は次のようなものになるかもしれません。

-ConfigFilename "doohickey.txt" -RootDirectory "c:\some\kind\of\path" -Max 11

この状態から、$argumentListからすべての引数を指定してscript.ps1を実行するにはどうしたらよいでしょうか。

この2番目のスクリプトからの書き込みホストコマンドが、この最初のスクリプトが起動されたコンソールに見えるようにしたいのですが。

ドットソース、Invoke-Command、Invoke-Expression、および Start-Job を試しましたが、エラーを発生させないアプローチを見つけられませんでした。

たとえば、最も簡単な最初のルートは、次のように呼び出されたStart-Jobを試してみることだと思いました。

Start-Job -FilePath $scriptPath -ArgumentList $argumentList

...しかし、これはこのエラーで失敗します。

System.Management.Automation.ValidationMetadataException:
Attribute cannot be added because it would cause the variable
ConfigFilename with value -ConfigFilename to become invalid.

...この場合、"ConfigFilename" は 2 番目のスクリプトによって定義されたパラメータ リストの最初のパラメータで、私の呼び出しは明らかにその値を "-ConfigFilename" に設定しようとしています。

私は何を見逃しているのでしょうか?

EDITです。

OK、これはいわゆるスクリプトのモックアップで、invokee.ps1という名前のファイルです。

Param(
[parameter(Mandatory=$true)]
[alias("rc")]
[string]
[ValidateScript( {Test-Path $_ -PathType Leaf} )]
$ConfigurationFilename,
[alias("e")]
[switch]
$Evaluate,
[array]
[Parameter(ValueFromRemainingArguments=$true)]
$remaining)

function sayHelloWorld()
{
    Write-Host "Hello, everybody, the config file is <$ConfigurationFilename>."
    if ($ExitOnErrors)
    {
        Write-Host "I should mention that I was told to evaluate things."
    }
    Write-Host "I currently live here: $gScriptDirectory"
    Write-Host "My remaining arguments are: $remaining"
    Set-Content .\hello.world.txt "It worked"
}

$gScriptPath = $MyInvocation.MyCommand.Path
$gScriptDirectory = (Split-Path $gScriptPath -Parent)
sayHelloWorld

...そして、これは呼び出しスクリプトのモックアップで、invoker.ps1という名前のファイルになっています。

function pokeTheInvokee()
{
    $scriptPath = (Join-Path -Path "." -ChildPath "invokee.ps1")
    $scriptPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($scriptPath)
    
    $configPath = (Join-Path -Path "." -ChildPath "invoker.ps1")
    $configPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($configPath)
    
    $argumentList = @()
    $argumentList += ("-ConfigurationFilename", "`"$configPath`"")
    $argumentList += , "-Evaluate"

    Write-Host "Attempting to invoke-expression with: `"$scriptPath`" $argumentList"
    Invoke-Expression "`"$scriptPath`" $argumentList"
    Invoke-Expression ".\invokee.ps1 -ConfigurationFilename `".\invoker.ps1`" -Evaluate
    Write-Host "Invokee invoked."
}

pokeTheInvokee

invoker.ps1を実行すると、現在、Invoke-Expressionの最初の呼び出しで、このようなエラーが発生します。

Invoke-Expression : You must provide a value expression on
the right-hand side of the '-' operator.

2回目の呼び出しはうまくいきますが、1つの重要な違いは、最初のバージョンではパスにスペースがある引数を使用していますが、2回目ではそうなっていないことです。 これらのパスにスペースがあることを誤って処理したのでしょうか?

どのように解決するのですか?

あはは。 これは、スクリプトへのパスにスペースがあるという単純な問題であることが判明しました。

Invoke-Expression の行を変更する。

Invoke-Expression "& `"$scriptPath`" $argumentList"

...で十分でしたので、キックオフしました。 ネオリスクさん、ご協力ありがとうございました。