首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从PowerShell调用C# cmdlet引发CommandNotFoundException

从PowerShell调用C# cmdlet引发CommandNotFoundException
EN

Stack Overflow用户
提问于 2014-03-18 19:08:24
回答 1查看 6.2K关注 0票数 2

我正在尝试从Add-AppxPackage调用C# cmdlet。我在从PowerShell代码运行C#上找到了MSDN的文章。我引用了System.Management.Automation程序集并尝试了以下代码片段,所有这些代码段在尝试调用powerShell.Invoke()时都会产生相同的异常:

System.Management.Automation.CommandNotFoundException未被处理 术语“AppxPackage”不被识别为cmdlet、函数、脚本文件或可操作程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后再试一次。

片段1:

代码语言:javascript
运行
复制
var powerShell = PowerShell.Create();
powerShell.AddCommand(string.Format("Add-AppxPackage '{0}'", appxFilePath));

foreach (PSObject result in powerShell.Invoke())
{
    Console.WriteLine(result);
}

我理解为什么这不能工作,因为我不应该在AddCommand()函数中提供参数。

片段2:

代码语言:javascript
运行
复制
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddParameter("Path", appxFilePath);

foreach (PSObject result in powerShell.Invoke())
{
    Console.WriteLine(result);
}

片段3:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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进程来运行我的命令,所以我尝试了如下:

代码语言:javascript
运行
复制
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模块):

代码语言:javascript
运行
复制
(Get-Module appx -ListAvailable).Path

然后导入该模块,然后尝试调用其cmdlet之一。这就是对我有用的C#代码:

代码语言:javascript
运行
复制
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都被加载。卸载该扩展后,所有模块都已正确加载,我不再需要手动导入模块。

EN

Stack Overflow用户

回答已采纳

发布于 2014-03-19 00:13:43

在PowerShell中,终止错误(它停止执行)和非终止错误(这些错误只是写入错误流)之间有区别。

如果要在自己的函数中创建非终止错误,只需使用Write-Error cmdlet即可。如果要创建终止错误,请使用Throw关键字。如果运行Get-Help Write-ErrorGet-Help about_ThrowGet-Help about_Try_Catch_Finally,您可以更多地了解这些概念。

使用不存在包的Add-AppxPackage是一个非终止性错误,因此将写入错误流,但不会引发执行停止异常。下面的代码尝试添加一个不存在的包,然后将错误写入控制台。

代码语言:javascript
运行
复制
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);
    }
}
票数 7
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22488780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档