コマンドライン引数を使用して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 2009

気にしないで。文字列を正しく分割する方法を知っていると役立つことがあります。;-)おかげで、あなたの解決策は私の問題を解決するのに役立ちました!
Mephisztoe 2009

@Tronex-キーをスクリプトのパラメーターとして定義する必要があります。PowerShellには、パスを操作するための優れた組み込みツールがいくつかあります。それについて別の質問をするかもしれません。@ Kosi2801には、パラメーターを追加するための正しい答えがあります。
Steven Murawski、

私の返信を入力すると、あなたの回答と重複しました。解決されてよかったです。
Steven Murawski、

1
scriptInvoker変数は使用されていません。
ナイアヘル2014年

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で発生しました
Muhammad 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をチェックして、エラーの有無を確認できます。コレクションをチェックするのは本当に便利でした。ユーザーは、PowerShellスクリプトが返すオブジェクトのタイプです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.