如何获取C#PowerShell调用以使用自定义函数



我在C#中有一个简单的函数来调用PowerShell命令并返回输出,它运行良好。但是,我希望能够为添加到PowerShell的自定义函数返回值。这是我的C#代码:

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddScript("MyCustomCommand");
ICollection<PSObject> results = ps.Invoke();

当我在本地运行PowerShell时,我在C:WindowsSystem32WindowsPowerShellv1.0Microsoft.PowerShell_profile.ps1位置设置了配置文件,所以当我打开PowerShell并输入MyCustomCommand时,它会返回一个字符串:

Function MyCustomCommand {
[CmdletBinding()]
param()
return "someoutput"
}

然而,当我从C#调用相同的MyCustomCommand时,却找不到它。如何永久添加此配置文件,使C#在调用命令时也能返回相同的输出,就像我在桌面上打开PowerShell实例时一样?

更新我使用了@start automatics推荐的模块解决方案,但由于执行策略的原因,我无法运行,所以我修改了它:

ps.Runspace = runspace;
ps.AddCommand("Set-ExecutionPolicy").AddArgument("Unrestricted");
ps.AddCommand("Import-Module").AddArgument("MyNewModuleName");
ps.Commands.AddScript("MyCustomCommand");

出了什么问题

它无法在C#中运行您的命令,因为您的命令尚未加载。

好的,那么你是如何加载的

您已经在使用[Runspace]。这很好。[Runspace]是您将函数加载到其中所需要的。有两种方法可以做到这一点:

  1. 使用[InitialSessionState]

这是推荐的路线。CCD_ 6用于填充PowerShell[Runspace]的初始状态。在这里,您可以加载模块、声明命令、添加变量等。最简单的处理方法是首先将它们放在模块中。


InitialSessionState iss = InitialSessionState.CreateDefault2();
// Note: .CreateDefault2 is the recommended default of a session state
// Note: .CreateDefault reflects the default session state in v2-v4 timeframes
iss.ImportPSModule(new[] { "NameOfModule" });
iss.ImportPSModulesFromPath("PathToModule");
Runspace runspace = RunspaceFactory.CreateRunspace(iss);

您也可以使用SessionStateFunctionEntry 手工声明单个函数

InitialSessionState iss = InitialSessionState.CreateDefault2();
iss.Commands.Add(new SessionStateFunctionEntry("MyFunction","MyDefinition"));

使用任何一种技术,都应该用您需要的命令填充您的运行空间。

useLocalScope设置为$false的.AddCommand/.AddScript

另一种方法是运行一个命令来更改[Runspace]。默认情况下,当将.AddCommand或.AddScript添加到[PowerShell]对象时,它将使用";本地";范围这意味着您所做的任何更改(添加的命令、导入的模块、设置的变量等(都将是";"局部作用域";,并且下次在[Runspace]中运行时将不可用。

若要使其按您希望的方式工作,请在useLocalScope(第二个参数(设置为false的情况下使用.AddScript/.AddCommand。

以下是PowerShell概念的快速验证:

[PowerShell]::Create().AddScript('$x = 1',$false).AddStatement().AddScript('$x').Invoke()

希望这能帮助

最新更新