【发布时间】:2014-03-28 02:49:23
【问题描述】:
我正在尝试从 C# 调用 Add-AppxPackage cmdlet。我在 running PowerShell from C# code 上找到了 MSDN 文章。我已经引用了 System.Management.Automation 程序集并尝试了以下代码 sn-ps,所有这些在尝试调用 powerShell.Invoke() 时都会导致相同的异常:
System.Management.Automation.CommandNotFoundException 未处理
“Add-AppxPackage”一词未被识别为 cmdlet 的名称, 函数、脚本文件或可运行的程序。检查拼写 名称,或者如果包含路径,请验证路径是否正确并 再试一次。
片段 1:
var powerShell = PowerShell.Create();
powerShell.AddCommand(string.Format("Add-AppxPackage '{0}'", appxFilePath));
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
我明白为什么这不起作用,因为我不应该在 AddCommand() 函数中提供参数。
片段 2:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddParameter("Path", appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
片段 3:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddArgument(appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
我的 C# 项目以 .Net 4.5 为目标,如果我执行 powerShell.AddCommand("Get-Host") 它可以工作并且它返回的版本是 4.0。 Add-AppxPackage 是在 PowerShell v3.0 中添加的,所以该命令肯定存在,如果我在 Windows PowerShell 命令提示符下手动运行该命令,它就可以正常工作。
有什么想法我在这里做错了吗?任何建议表示赞赏。
-- 更新--
我找到了this post和this one,发现有一个AddScript()函数,所以我试了一下:
片段 4:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format("Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
foreach (PSObject result in results)
{
Console.WriteLine(result);
}
而且它不会抛出异常,但它也不会安装metro应用程序,并且从powerShell.Invoke()返回的“结果”是空的,所以我仍然不知所措......
-- 更新 2--
所以我决定尝试创建一个新的 PowerShell 进程来运行我的命令,所以我尝试了这个:
Process.Start(new ProcessStartInfo("PowerShell", string.Format("-Command Add-AppxPackage '{0}'; $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyUp')", appxFilePath)));
但它仍然会引发 Add-AppxPackage 不是可识别的 cmdlet 的相同错误。
回答
如果您关注 robert.westerlund 的回答的长评论线程,您会看到由于某种原因从 Visual Studio 运行/启动时,PowerShell 不包括直接从 PowerShell 命令提示符运行时执行的所有 PSModulePaths ,所以很多模块都不存在。解决方案是使用以下方法找到我需要的模块的绝对路径(在我的例子中是 appx 模块):
(Get-Module appx -ListAvailable).Path
然后在尝试调用其中一个 cmdlet 之前导入该模块。所以这是对我有用的 C# 代码:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format(@"Import-Module 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Appx\Appx.psd1'; Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
更新答案
您可以从this other post I opened 看到,问题出在 Visual Studio 扩展(在我的情况下为 StudioShell)中的一个错误,导致并非所有 PSModulePath 都被加载。卸载该扩展后,所有模块都已正确加载,我不再需要手动导入模块。
【问题讨论】:
标签: c# powershell invoke