PowerShell Pass Named parameters to ArgumentList

前端 未结 7 1827
没有蜡笔的小新
没有蜡笔的小新 2021-02-20 08:14

I have a PowerShell script that accepts 3 named parameters. Please let me know how to pass the same from command line. I tried below code but same is not working. It assigns the

相关标签:
7条回答
  • 2021-02-20 08:49

    If you're willing to skip Invoke-Command altogether...

    Your script could look like this:

    ([string]$args).split('-') | %{ 
        if ($_.Split(' ')[0].ToUpper() -eq "P1") { $P1 = $_.Split(' ')[1] } 
        elseif ($_.Split(' ')[0].ToUpper() -eq "P2") { $P2 = $_.Split(' ')[1] }
        elseif ($_.Split(' ')[0].ToUpper() -eq "P3") { $P3 = $_.Split(' ')[1] } 
    }
    
    Write-Output "P1 Value :" $P1
    Write-Output "P2 Value :" $P2
    Write-Output "P3 Value :" $P3
    

    And you would call it like this:

    D:\test.ps1 -P1 1 -P2 2 -P3 3

    0 讨论(0)
  • 2021-02-20 08:50

    Here's a simple solution:

    [PowerShell]::Create().AddCommand('D:\test.ps1').AddParameters(@{ P1 = 1; P2 = 2; P3 = 3 }).Invoke()
    

    Here's output:

    PS C:\Windows\system32> [PowerShell]::Create().AddCommand('D:\test.ps1').AddParameters(@{ P1 = 1; P2 = 2; P3 = 3 }).Invoke()
    P1 Value :
    1
    P2 Value:
    2
    P3 Value :
    3
    
    0 讨论(0)
  • 2021-02-20 08:51

    Use a hashtable :

    icm -ComputerName test -ScriptBlock{$args} -ArgumentList @{"p1"=1;"p2"=2;"p3"=3} 
    
    0 讨论(0)
  • 2021-02-20 08:52

    Use a hashtable, indeed!

    #TestPs1.ps1
    Param (
        [string]$P3,
        [string]$P2,
        [string]$P1
    )
    Write-Output "P1 Value :" $P1
    Write-Output "P2 Value:" $P2
    Write-Output "P3 Value :" $P3
    
    $params = @{
        P3 = 3
        P2 = 2
    }
    #(just to prove it doesn't matter which order you put them in)
    $params["P1"] = 1;
    #Trhough the use of the "Splat" operator, we can add parameters directly onto the module
    & ".\TestPs1.ps1" @params
    

    outputs:

    P1 Value :
    1
    P2 Value:
    2
    P3 Value :
    3
    
    0 讨论(0)
  • 2021-02-20 08:52

    If you are trying to use the -FilePath with named parameters (-P1 1 -P2 2), then I found this will work. Use a script block to run the file, instead of the using -FilePath.

    Invoke-Command -ComputerName server -ScriptBlock {& "D:\test.ps1" -P1 1 -P2 2 -P3 3}
    
    0 讨论(0)
  • 2021-02-20 09:05

    The code by mjolinor works great, but it took me several minutes to understand it.

    The code makes a simple thing - generates a content of script block with built-in parameters:

    &{
        Param (
            [string]$P3,
            [string]$P2,
            [string]$P1
        )
        Write-Output "P1 Value:" $P1
        Write-Output "P2 Value:" $P2
        Write-Output "P3 Value:" $P3
    } -P1 1 -P2 2 -P3 3
    

    Then this script block is passed to Invoke-Command.

    To simplify the code:

    ".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)"
    
    $scriptContent = Get-Content $ScriptPath -Raw
    $formattedParams = &{ $args } @params
    # The `.{}` statement could be replaced with `&{}` here, because we don't need to persist variables after script call.
    $scriptBlockContent = ".{ $scriptContent } $formattedParams"
    $sb = [scriptblock]::create($scriptBlockContent)
    

    Let's make a basic C# implementation:

    void Run()
    {
        var parameters = new Dictionary<string, string>
        {
            ["P1"] = "1",
            ["P2"] = "2",
            ["P3"] = "3"
        };
    
        var scriptResult = InvokeScript("Test.ps1", "server", parameters)
        Console.WriteLine(scriptResult);
    }
    
    string InvokeScript(string filePath, string computerName, Dictionary<string, string> parameters)
    {
        var innerScriptContent = File.ReadAllText(filePath);
        var formattedParams = string.Join(" ", parameters.Select(p => $"-{p.Key} {p.Value}"));
        var scriptContent = "$sb = { &{ " + innerScriptContent + " } " + formattedParams + " }\n" +
            $"Invoke-Command -ComputerName {computerName} -ScriptBlock $sb";
    
        var tempFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".ps1");
        File.WriteAllText(tempFile, scriptContent);
    
        var psi = new ProcessStartInfo
            {
                FileName = "powershell",
                Arguments = $@"-ExecutionPolicy Bypass -File ""{tempFile}""",
                RedirectStandardOutput = true,
                UseShellExecute = false
            };
    
        var process = Process.Start(psi);
        var responseText = process.StandardOutput.ReadToEnd();
    
        File.Delete(tempFile);
    
        return responseText;
    }
    

    The code generates a temporary script and executes it.

    Example script:

    $sb = {
        &{
            Param (
                [string]$P3,
                [string]$P2,
                [string]$P1
            )
            Write-Output "P1 Value:" $P1
            Write-Output "P2 Value:" $P2
            Write-Output "P3 Value:" $P3
         } -P1 1 -P2 2 -P3 3
    }
    Invoke-Command -ComputerName server -ScriptBlock $sb
    
    0 讨论(0)
提交回复
热议问题