我正在尝试从Add-AppxPackage
调用C# cmdlet。我在从PowerShell代码运行C#上找到了MSDN的文章。我引用了System.Management.Automation程序集并尝试了以下代码片段,所有这些代码段在尝试调用powerShell.Invoke()时都会产生相同的异常:
System.Management.Automation.CommandNotFoundException未被处理 术语“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”),它可以工作,它返回的版本是4.0。AppxPackage是在PowerShell的v3.0中添加的,所以这个命令肯定存在,如果我从PowerShell命令提示符手动运行这个命令,它就会正常工作。
知道我在这里做错了什么吗?如有任何建议,敬请见谅。
-更新
我找到了这个职位和这一个,并意识到有一个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);
}
它不会抛出异常,但它也不会安装地铁应用程序,从powerShell.Invoke()返回的“结果”是空的,所以我仍然不知道.
-更新2
因此,我决定尝试创建一个新的PowerShell进程来运行我的命令,所以我尝试了如下:
Process.Start(new ProcessStartInfo("PowerShell", string.Format("-Command Add-AppxPackage '{0}'; $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyUp')", appxFilePath)));
但是它仍然抛出与AppxPackage不是公认的cmdlet相同的错误。
回答
如果您遵循robert.westerlund上的长注释线程,您将看到,由于某种原因,在从Visual运行/启动时,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();
更新答复
从我开的另一封信中可以看出,问题是Visual扩展中的一个bug (在我的例子中是StudioShell)导致的并不是所有的PSModulePaths都被加载。卸载该扩展后,所有模块都已正确加载,我不再需要手动导入模块。
发布于 2014-03-19 00:13:43
在PowerShell中,终止错误(它停止执行)和非终止错误(这些错误只是写入错误流)之间有区别。
如果要在自己的函数中创建非终止错误,只需使用Write-Error
cmdlet即可。如果要创建终止错误,请使用Throw
关键字。如果运行Get-Help Write-Error
、Get-Help about_Throw
和Get-Help about_Try_Catch_Finally
,您可以更多地了解这些概念。
使用不存在包的Add-AppxPackage
是一个非终止性错误,因此将写入错误流,但不会引发执行停止异常。下面的代码尝试添加一个不存在的包,然后将错误写入控制台。
var powerShell = PowerShell.Create();
powerShell.AddScript("Add-AppxPackage NonExistingPackageName");
// Terminating errors will be thrown as exceptions when calling the Invoke method.
// If we want to handle terminating errors, we should place the Invoke call inside a try-catch block.
var results = powerShell.Invoke();
// To check if a non terminating error has occurred, test the HadErrors property
if (powerShell.HadErrors)
{
// The documentation for the Error property states that "The command invoked by the PowerShell
// object writes information to this stream whenever a nonterminating error occurs."
foreach (var error in powerShell.Streams.Error)
{
Console.WriteLine("Error: " + error);
}
}
else
{
foreach(var package in results)
{
Console.WriteLine(package);
}
}
https://stackoverflow.com/questions/22488780
复制相似问题