我需要在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脚本并确保空格没问题?
答案 0 :(得分:104)
尝试将scriptfile创建为单独的命令:
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();
答案 1 :(得分:28)
我有另一个解决方案。我只想测试执行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
答案 2 :(得分:8)
我是否有机会更清楚地了解Commands.AddScript方法的传递参数?
C:\ Foo1.PS1 Hello World Hunger C:\ Foo2.PS1 Hello World
scriptFile =“C:\ Foo1.PS1”
parameters =“parm1 parm2 parm3”......可变长度的参数
解决了这个问题......将null作为名称,将param作为值传递给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();
}
答案 3 :(得分: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 :(得分: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建议脚本变量列表不会填充自己的变量。
答案 5 :(得分:2)
对我来说,从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脚本返回的对象类型。
答案 6 :(得分:2)
我的更小更简单:
/// <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;
}