명령 줄 인수를 사용하여 C #에서 PowerShell 스크립트 실행


101

C # 내에서 PowerShell 스크립트를 실행해야합니다. 스크립트에는 명령 줄 인수가 필요합니다.

이것이 내가 지금까지 한 일입니다.

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();

RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.Add(scriptFile);

// Execute PowerShell script
results = pipeline.Invoke();

scriptFile은 "C : \ Program Files \ MyProgram \ Whatever.ps1"과 같은 것을 포함합니다.

스크립트는 "-key Value"와 같은 명령 줄 인수를 사용하는 반면 Value는 공백도 포함 할 수있는 경로와 유사 할 수 있습니다.

이게 작동하지 않습니다. 누구든지 C # 내에서 PowerShell 스크립트에 명령 줄 인수를 전달하고 공백에 문제가 없는지 확인하는 방법을 알고 있습니까?


1
향후 사용자를 위해 명확하게하기 위해 허용 된 답변은 사용 매개 변수 없이도 공백 문제가있는 사람들의 문제를 해결합니다. : 사용 하여 탈출 문제 Command myCommand = new Command(scriptfile);pipeline.Commands.Add(myCommand);해결하십시오.
scharette

답변:


111

별도의 명령으로 스크립트 파일을 만들어보십시오.

Command myCommand = new Command(scriptfile);

그런 다음 매개 변수를 추가 할 수 있습니다.

CommandParameter testParam = new CommandParameter("key","value");
myCommand.Parameters.Add(testParam);

그리고 마지막으로

pipeline.Commands.Add(myCommand);

다음은 완전하고 편집 된 코드입니다.

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();

RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

Pipeline pipeline = runspace.CreatePipeline();

//Here's how you add a new script with arguments
Command myCommand = new Command(scriptfile);
CommandParameter testParam = new CommandParameter("key","value");
myCommand.Parameters.Add(testParam);

pipeline.Commands.Add(myCommand);

// Execute PowerShell script
results = pipeline.Invoke();

값이 c : \ program files \ myprogram과 같은 경우 키가 c : \ program으로 설정된다는 문제가 여전히있는 것 같습니다. :(
Mephisztoe

신경 쓰지 마. 문자열을 올바르게 분할하는 방법을 알고있을 때 도움이되는 경우가 있습니다. ;-) 다시 한 번 감사드립니다. 귀하의 솔루션은 제 문제를 해결하는 데 도움이되었습니다!
Mephisztoe

@Tronex-키를 스크립트의 매개 변수로 정의해야합니다. PowerShell에는 경로 작업을위한 몇 가지 훌륭한 기본 제공 도구가 있습니다. 그것에 대해 다른 질문을 할 수도 있습니다. @ Kosi2801은 매개 변수 추가에 대한 정답을 가지고 있습니다.
Steven Murawski

내 답장을 입력하는 것이 귀하의 답장과 겹쳤습니다. 문제가 해결되어 기쁩니다!
Steven Murawski

1
scriptInvoker 변수가 사용되지 않습니다.
niaher

33

다른 해결책이 있습니다. 누군가가 정책을 변경할 수 있기 때문에 PowerShell 스크립트 실행이 성공하는지 테스트하고 싶습니다. 인수로 실행할 스크립트의 경로를 지정합니다.

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"powershell.exe";
startInfo.Arguments = @"& 'c:\Scripts\test.ps1'";
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();

string output = process.StandardOutput.ReadToEnd();
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));

string errors = process.StandardError.ReadToEnd();
Assert.IsTrue(string.IsNullOrEmpty(errors));

스크립트 내용은 다음과 같습니다.

$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable

1
안녕하세요. 설명한대로 powershell을 시작하고 모든 명령 프로세스 (이 경우)를 실행해도 종료되지 않는 이유를 알고 있습니까?
Eugeniu Torica

어떤 라이브러리 당신이 사용하는
SoftwareSavant

11

Commands.AddScript 메서드에 매개 변수를 전달하는 데 문제가 있습니다.

C:\Foo1.PS1 Hello World Hunger
C:\Foo2.PS1 Hello World

scriptFile = "C:\Foo1.PS1"

parameters = "parm1 parm2 parm3" ... variable length of params

나는 null값으로 이름과 매개 변수를 컬렉션 에 전달 하여 이것을 해결 했습니다.CommandParameters

내 기능은 다음과 같습니다.

private static void RunPowershellScript(string scriptFile, string scriptParameters)
{
    RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
    runspace.Open();
    RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
    Pipeline pipeline = runspace.CreatePipeline();
    Command scriptCommand = new Command(scriptFile);
    Collection<CommandParameter> commandParameters = new Collection<CommandParameter>();
    foreach (string scriptParameter in scriptParameters.Split(' '))
    {
        CommandParameter commandParm = new CommandParameter(null, scriptParameter);
        commandParameters.Add(commandParm);
        scriptCommand.Parameters.Add(commandParm);
    }
    pipeline.Commands.Add(scriptCommand);
    Collection<PSObject> psObjects;
    psObjects = pipeline.Invoke();
}

방금 추가 :using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))...using (Pipeline pipeline = runspace.CreatePipeline())
Red

나는 여러 매개 변수를 전달하고 때이 오류가 발생합니다 형식 'System.Management.Automation.ParseException'의 처리되지 않은 예외가 System.Management.Automation.dll에서 발생
무하마드 Noman

5

AddScript 메서드와 함께 파이프 라인을 사용할 수도 있습니다.

string cmdArg = ".\script.ps1 -foo bar"            
Collection<PSObject> psresults;
using (Pipeline pipeline = _runspace.CreatePipeline())
            {
                pipeline.Commands.AddScript(cmdArg);
                pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
                psresults = pipeline.Invoke();
            }
return psresults;

문자열과 전달하는 매개 변수를받습니다.


4

내 것이 조금 더 작고 간단합니다.

/// <summary>
/// Runs a PowerShell script taking it's path and parameters.
/// </summary>
/// <param name="scriptFullPath">The full file path for the .ps1 file.</param>
/// <param name="parameters">The parameters for the script, can be null.</param>
/// <returns>The output from the PowerShell execution.</returns>
public static ICollection<PSObject> RunScript(string scriptFullPath, ICollection<CommandParameter> parameters = null)
{
    var runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    var pipeline = runspace.CreatePipeline();
    var cmd = new Command(scriptFullPath);
    if (parameters != null)
    {
        foreach (var p in parameters)
        {
            cmd.Parameters.Add(p);
        }
    }
    pipeline.Commands.Add(cmd);
    var results = pipeline.Invoke();
    pipeline.Dispose();
    runspace.Dispose();
    return results;
}

3

다음은 스크립트에 매개 변수를 추가하는 방법입니다.

pipeline.Commands.AddScript(Script);

이것은 HashMap을 매개 변수로 사용하여 스크립트에서 변수의 이름이고 값은 변수의 값입니다.

pipeline.Commands.AddScript(script));
FillVariables(pipeline, scriptParameter);
Collection<PSObject> results = pipeline.Invoke();

그리고 채우기 변수 방법은 다음과 같습니다.

private static void FillVariables(Pipeline pipeline, Hashtable scriptParameters)
{
  // Add additional variables to PowerShell
  if (scriptParameters != null)
  {
    foreach (DictionaryEntry entry in scriptParameters)
    {
      CommandParameter Param = new CommandParameter(entry.Key as String, entry.Value);
      pipeline.Commands[0].Parameters.Add(Param);
    }
  }
}

이렇게하면 스크립트에 여러 매개 변수를 쉽게 추가 할 수 있습니다. 또한 스크립트의 변수에서 값을 얻으려면 다음과 같이 표시됩니다.

Object resultcollection = runspace.SessionStateProxy.GetVariable("results");

// 결과는 v의 이름입니다.

Kosi2801이 스크립트 변수 목록이 자신의 변수로 채워지지 않는다고 제안하는 방식으로 수행하면 어떤 이유로 든 내가 보여준 방식대로 수행해야합니다.


3

저에게있어 C #에서 PowerShell 스크립트를 실행하는 가장 유연한 방법은 PowerShell.Create().AddScript()

코드 스 니펫은

string scriptDirectory = Path.GetDirectoryName(
    ConfigurationManager.AppSettings["PathToTechOpsTooling"]);

var script =    
    "Set-Location " + scriptDirectory + Environment.NewLine +
    "Import-Module .\\script.psd1" + Environment.NewLine +
    "$data = Import-Csv -Path " + tempCsvFile + " -Encoding UTF8" + 
        Environment.NewLine +
    "New-Registration -server " + dbServer + " -DBName " + dbName + 
       " -Username \"" + user.Username + "\" + -Users $userData";

_powershell = PowerShell.Create().AddScript(script);
_powershell.Invoke<User>();
foreach (var errorRecord in _powershell.Streams.Error)
    Console.WriteLine(errorRecord);

Streams.Error를 확인하여 오류가 있는지 확인할 수 있습니다. 컬렉션을 확인하는 것이 정말 편리했습니다. User는 PowerShell 스크립트가 반환하는 개체 유형입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.