我使用 PS 2. 0, VS 2010, C# 调用 Powershell 脚本( PS1 文件) 使用 C# 。
我有这个单位测试 工作很好:
output = UsingPowerShell(@". est1.ps1, "");
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));
脚本内容 :
=================== test1.ps1 ==========================
$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable
=================== End test1.ps1 ==========================
但这次单位测试失败。 我收到错误信息:
" "Cannot 援引此函数,因为当前主机主机不执行此函数"
output = UsingPowerShell(@". est2.ps1", "");
Assert.IsTrue(output.Contains("test2.ps1"));
脚本内容
=================== test2.ps1 ==========================
$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentPath = $MyInvocation.MyCommand.Path
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")
$scriptDir = Split-Path -parent $MyInvocation.MyCommand.Path
#Write-Host $currentExecutingPath
Write-Host $currentScriptName
Write-Host `r`nRuta: $scriptDir
=================== End test2.ps1 ==========================
使用 PowerShell 方法 :
public static string UsingPowerShell(string scriptPS, string parametros)
{
if (string.IsNullOrWhiteSpace(parametros)) return UsingPowerShell(scriptPS, new List<string> { });
return UsingPowerShell(scriptPS, parametros.Split( ));
}
public static string UsingPowerShell(string scriptPS, IList<string> parametros)
{
var builder = new StringBuilder();
string answer = null;
RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
InitialSessionState iss = InitialSessionState.CreateDefault();
using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
{
runspace.Open();
//runspace.ApartmentState = System.Threading.ApartmentState.STA;
//runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
// create a pipeline and feed it the script text
using (Pipeline pipeline = runspace.CreatePipeline())
{
Command command = new Command(scriptPS,true,true);
foreach (var param in parametros)
{
command.Parameters.Add(null, param);
}
pipeline.Commands.Add(command);
//pipeline.Commands.AddScript(cmdArg);
//runspace.SessionStateProxy.SetVariable("MyResponse", response);
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
Collection<PSObject> psresults = pipeline.Invoke();
//PSObject newResponse = (PSObject)runspace.SessionStateProxy.GetVariable("MyResponse");
//if you want to get a value from a variable in you script like so:
//Object resultcollection = runspace.SessionStateProxy.GetVariable("results");
// convert the script result into a single string
var sb = new StringBuilder();
foreach (PSObject obj in psresults)
{
sb.AppendLine(obj.ToString());
}
answer = sb.ToString();
Console.WriteLine(answer);
//Console.WriteLine(psresults.ToArray()[0].ToString());
// check for errors (non-terminating)
if (pipeline.Error.Count > 0)
{
//iterate over Error PipeLine until end
while (!pipeline.Error.EndOfPipeline)
{
//read one PSObject off the pipeline
var value = pipeline.Error.Read() as PSObject;
if (value != null)
{
//get the ErrorRecord
var r = value.BaseObject as ErrorRecord;
if (r != null)
{
//build whatever kind of message your want
builder.AppendLine(r.InvocationInfo.MyCommand.Name + " : " + r.Exception.Message);
builder.AppendLine(r.InvocationInfo.PositionMessage);
builder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo));
builder.AppendLine(string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId));
}
}
}
//return builder.ToString();
}
pipeline.Dispose();
}
runspace.Close();
}
return answer;
}
有什么建议吗?
更新:
How Windows PowerShell Works
http://msdn.microsoft.com/en-us/library/ms714658(VS.85).aspx
Windows PowerShell 在一个主机应用程序(默认为 powershell.exe) 中运行,该应用程序向用户披露命令行,并使用主机接口与命令行引用的命令进行沟通。主机应用程序可以是控制台应用程序、 Windows 应用程序或网络应用程序。在大多数情况下,主机应用程序使用其主要功能与 Windows Powershell 内部主机接口进行互动;然而,主机应用程序可以通过实施 PSHost 类和一个或多个相关用户界面类别来选择性地支持自己的自定义主机。这些类别允许应用程序与 Windows PowerShell 命令直接沟通。