为什么从C#调用PowerShell会抛出System.Management.Automation.CommandNotFoundException?

时间:2010-09-15 15:51:19

标签: c# powershell

我正在使用这个c#:

    public bool RunPowershell(string script)
    {
        RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create();

        using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig))
        {
            runspace.Open();

            using (RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace))
            {
                scriptInvoker.Invoke(script);
            }
        }

        return true;
    }

要运行此脚本:

      Add-PSSnapin -name Microsoft.SystemCenter.VirtualMachineManager
      $vmm = Get-VMMServer -ComputerName "VmmComputerName"

在Windows 2003 32位操作系统上运行正常,但在Windows 2008R2 64位上,我收到此错误:

System.Management.Automation.CommandNotFoundException: The term 'Get-VMMServer' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin)
at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
at System.Management.Automation.CommandFactory._CreateCommand(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
at System.Management.Automation.ExecutionContext.CreateCommand(String command)
at System.Management.Automation.CommandNode.CreateCommandProcessor(Int32& index, ExecutionContext context)
at System.Management.Automation.CommandNode.AddToPipeline(PipelineProcessor pipeline, ExecutionContext context)
at System.Management.Automation.PipelineNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
at System.Management.Automation.AssignmentStatementNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList,     ExecutionContext context)

而且,我安装了Microsoft.SystemCenter.VirtualMachineManager。如果我手动将其输入到2008R2机器上的power-shell控制台,该脚本也可以工作。

对于我可能遗失的任何想法,你能帮忙吗?

非常感谢。

2 个答案:

答案 0 :(得分:7)

这是因为powershell管理单元元数据记录在注册表中。在您的情况下,这意味着管理单元信息仅在注册表中的32位软件配置单元中可用。通常,使其可用的技巧是使用64位版本的.NET框架的installutil.exe(在framework64目录中)来注册它,但有时它只是32位的原因。它可能取决于64位环境中不可用的32位COM对象。

所以你有两种方法:

1)使用installutil.exe / i注册管理单元64位(不太可行)

2)仅通过VS项目属性(anycpu - > x86)将.NET exe作为32位目标

3)将您的工作包装成如下脚本:http://www.nivot.org/blog/post/2012/12/18/Ensuring-a-PowerShell-script-will-always-run-in-a-64-bit-shell

-Oisin

答案 1 :(得分:0)

这是一个处理命名参数并满足我的需要的示例。原始照片取自x0n帖子中的链接选项。有关其他详细信息,请参见链接的帖子。我正在从在x86上具有第三方依赖性的C#控制台应用程序执行此脚本。

param([string[]]$listOfVMNames, [string]$userName, [string]$resourceGroupName, [int]$waitForJob)
if ($pshome -like "*syswow64*") {
    & (join-path ($pshome -replace "syswow64", "sysnative") powershell.exe) -file `
        (join-path $psscriptroot $myinvocation.mycommand) -listOfVMNames (,$listOfVMNames) -userName $userName -resourceGroupName $resourceGroupName -waitForJob $waitForJob
    exit
}