Powershell Invoke method neither throwing exceptio

2019-03-05 12:29发布

问题:

I am trying to build an ASP.Net, c# application to expose few IIS management related activities through web interface for a distributed Admin group.

I am making use of System.Management.Automation V3.0 library to wrap power shell commands. As a first step I wanted to list all Web Applications that are currently up and running on local IIS by invoking Get-WebApplication command. This is where I am facing the issue. Method call is neither throwing any exception nor its returning the result. Does anyone know the root cause of this issue? Please share your experience of building such interface using System.Management.Automation.dll.

 var shell = PowerShell.Create();              
          shell.Commands.AddScript("Get-WebApplication | Out-String");
          try
          {
              var results = shell.Invoke();
              if (results.Count > 0)
              {
                  var builder = new StringBuilder();
                  foreach (var psObject in results)
                  {                          
                      builder.Append(psObject.BaseObject.ToString() + "\r\n");
                  }
              }

          }                  
          catch(Exception ex)
          {
              throw;
          }

PS: Get-Service in place of Get-WebApplication works absolutely fine by returning list of services available on the machine.

回答1:

PowerShell.Create() does not create new PowerShell process. If you does not specify Runspace for it, then it will create new in-process Runspace. Since it run in your process, it will match your process bitness and you can not change that. To create Runspace with different bitness you need to create out of process Runspace. Here is a sample console application, which demonstrate how you can do that:

using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
public static class TestApplication {
    public static void Main() {
        Console.WriteLine(Environment.Is64BitProcess);
        using(PowerShellProcessInstance pspi = new PowerShellProcessInstance()) {
            string psfn = pspi.Process.StartInfo.FileName;
            psfn=psfn.ToLowerInvariant().Replace("\\syswow64\\", "\\sysnative\\");
            pspi.Process.StartInfo.FileName=psfn;
            using(Runspace r = RunspaceFactory.CreateOutOfProcessRunspace(null, pspi)) {
                r.Open();
                using(PowerShell ps = PowerShell.Create()) {
                    ps.Runspace=r;
                    ps.AddScript("[Environment]::Is64BitProcess");
                    foreach(PSObject pso in ps.Invoke()) {
                        Console.WriteLine(pso);
                    }
                }
            }
        }
    }
}

If you compile this application as x32, it still will use x64 out of process Runspace on x64 operation system.