2015-01-06 16 views
4

У меня есть сценарий PowerShell, который принимает 3 именованных параметра. Пожалуйста, дайте мне знать, как передать это из командной строки. Я пробовал код ниже, но он не работает. Он присваивает всего значение только P3. Мое требование заключается в том, что P1 должен содержать 1, P2 РЕКОМЕНДУЕМЫМ 2 и P3 должны быть назначены 3.PowerShell Pass Именованные параметры ArgumentList

Invoke-Command -ComputerName server -FilePath "D:\test.ps1" -ArgumentList {-P1 1 -P2 2 -P3 3} 

Ihe ниже код файла сценария.

Param (
    [string]$P3, 
    [string]$P2, 
    [string]$P1 
) 
Write-Output "P1 Value :" $P1 
Write-Output "P2 Value:" $P2 
Write-Output "P3 Value :" $P3 
+0

возможно дубликат [? Как передать именованные параметры Invoke-Command] (http://stackoverflow.com/questions/4225748/how-do-i-pass- named-parameters-with-invoke-command) –

ответ

9

Один из вариантов:

$params = @{ 
P1 = 1 
P2 = 2 
P3 = 3 
} 

$ScriptPath = 'D:\Test.ps1' 

$sb = [scriptblock]::create(".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)") 

Invoke-Command -ComputerName server -ScriptBlock $sb 
+0

Да Я могу добиться результата, используя приведенный выше код. –

+1

Не могли бы вы дать мне знать, как добиться того же, используя код C#, поскольку мое требование - запустить этот сценарий PowerShell с C#. –

+0

Извините, не знаю, C# достаточно, чтобы преобразовать это для вас. – mjolinor

3

Используйте хэш-таблицу:

icm -ComputerName test -ScriptBlock{$args} -ArgumentList @{"p1"=1;"p2"=2;"p3"=3} 
+0

не могли бы вы предоставить более подробную информацию об этом. –

+0

посмотреть этот пост http://stackoverflow.com/a/4226027/381149 –

2

Код по mjolinor отлично работает, но мне потребовалось несколько минут, чтобы понять это.

Код делает простую вещь - генерирует содержимое блока сценария со встроенными параметрами:

&{ 
    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.

Чтобы упростить код:

".{$(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) 

Давайте создадим базовую реализацию C#:

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 = [email protected]"-ExecutionPolicy Bypass -File ""{tempFile}""", 
      RedirectStandardOutput = true, 
      UseShellExecute = false 
     }; 

    var process = Process.Start(psi); 
    var responseText = process.StandardOutput.ReadToEnd(); 

    File.Delete(tempFile); 

    return responseText; 
} 

код создает временный сценарий и выполняет его.

Пример сценария:

$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