2

Problem with Powershell object in C#9

I am trying to retrieve physical disks in C# using a system.management.powershell object. When I try using the cmdlet “Get-Process” the powershell object retrieves all processes correctly.

  using (PowerShell PowerShellInstance = PowerShell.Create())
    {
        // this works
        //PowerShellInstance.AddCommand("Get-Process");
        PowerShellInstance.AddScript("Get-PhysicalDisk");
        //PowerShellInstance.AddCommand("Out-String -Width 240 -Stream");
        Collection<PSObject> outlist = PowerShellInstance.Invoke();
    }

When I try using the cmdlet “Get-PhysicalDevice” no data is returned, and no errors are thrown.


I have also tried using a Runspace and a pipeline to execute get-process, and all processes are returned correctly.

Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
Pipeline p = rs.CreatePipeline();
p.Commands.Add("get-process");
// p.Commands.Add("get-physicaldisk");
Collection<PSObject> results = p.Invoke();
rs.Close();

When I try get-physicaldisk with a runspace the program throws a command not found exception. I am transferring a server monitor from VB to C#. The Runspace (get-physicaldisk) works correctly in VB using .net framework 4.1.7.

I am using System Management 5.0, ..Automation 7.1.4, and Powershell SDK 7.1.4.

0

2 Answers 2

4

Daniel's helpful answer provides an effective solution for the case at hand.

This answer explains how the PowerShell SDK reports errors and how to inspect them:

  • The .AddScript() PowerShell SDK method is for passing one more PowerShell statements for execution; that is, you can pass a snippet of PowerShell source code, as you would find in a .ps1 script file.

  • By contrast, the .AddCommand() method accepts the name or executable path of a single PowerShell command - without arguments; the latter must be added with separate calls, namely via a single .AddParameters() call, or via argument-individual .AddParameter() and .AddArgument() calls.

Choosing one method over the other has implications with respect to error handling, specifically with respect to statement-terminating errors, such as when calling a nonexistent command or, as it turned out to be the case for you, a command whose module failed to import:

  • .AddScript()-added code does not throw a .NET exception when .Invoke() is called and a statement-terminating error occurs - instead, an empty collection is returned, the .HadErrors property returns true, and the error(s) that occurred can be examined via the .Streams.Error collection.

  • .AddCommand()-added code may throw a .NET exception, e.g. of type System.Management.Automation.CommandNotFoundException.

By contrast:

  • Script-terminating errors (those created with a throw statement or via $ErrorActionPreference = 'Stop' / -ErrorAction Stop) always create a .NET exception for the caller.

    • throw, as a PowerShell statement, can only be executed via .AddScript(), but setting $ErrorActionPreference / using -ErrorAction is also possible in connection with .AddCommand().
  • Non-terminating errors (e.g., Get-ChildItem nosuchfile) never create a .NET exception for the caller.

See also:

Sign up to request clarification or add additional context in comments.

Comments

2

Set your execution policy to RemoteSigned so that the Storage module can be imported

using (var runspace = RunspaceFactory.CreateRunspace())
{
    runspace.InitialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned;
    runspace.Open();
    using (PowerShell PowerShellInstance = PowerShell.Create(runspace))
    {
        PowerShellInstance.AddScript("Get-PhysicalDisk");
        Collection<PSObject> outlist = PowerShellInstance.Invoke();
    }
}

3 Comments

Nicely done; I was trying to explain in general terms how to diagnose the problem, but the specific cause of a module failing to import hadn't occurred to me.
Btw, do you know what inside that module necessitates enabling scripts to run (as an aside: Microsoft.PowerShell.ExecutionPolicy.RemoteSigned should suffice and is probably preferable)? In a pristine PowerShell session, it works for me even with policy Restricted, but in conjunction with loading unrelated format data in my $PROFILE file I do see the symptom.
@mklement0, Unfortunately I do not. I just happened to notice the error that the module wasn't loading. I have tested with RemoteSigned and it also works for me so I have updated my answer. I have not been able to get it to work with Restricted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.