1

I am trying to fetch the printers associated with my computer inside an ASP.NET Core 5 app using the System.Management.Automation and Microsoft.PowerShell.SDK nuget packages.

PowerShell ps = PowerShell.Create();
ps.AddScript("Get-Printer");
ps.Invoke();

However, when I try this, I get the following error

The 'Get-Printer' command was found in the module 'PrintManagement', but the module could not be loaded. For more information, run 'Import-Module PrintManagement'

I tried Import-Module PrintManagement, but nothing is being imported and I get no messages. I also tried setting the execution policy to unrestricted, but it still didn't work.

I tried the code in a .NET 5 application console and it worked perfectly fine so I guess the issue narrows down to ASP.NET Core 5.

Any help would be greatly appreciated!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

2 Answers2

0

I have checked the issue, and a good link about the Powershell.cs. And It missing something related SecureString. Then I change the code like below.

And It works fine, you could custom the output format in the controller. Here is my test result and code.

    public IActionResult cmd()
    {
        var script = "Powershell Get-Printer";
        string errors;
        IEnumerable<PSObject> output;
        var success = PowershellTools.RunPowerShellScript(script, out output, out errors);
        List<string> response = new List<string>();
        foreach (var item in output)
        {
            response.Add(item.ToString());
        }

        return Ok(response);
    }

enter image description here

PowershellTools.cs

using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Security;

namespace Tools
{
    public static class PowershellTools
    {
        public static bool RunPowerShellScript(string script, out IEnumerable<PSObject> output, out string errors)
        {
            return RunPowerShellScriptInternal(script, out output, out errors, null);
        }

        public static bool RunPowerShellScriptRemote(string script, string computer, string username, string password, out IEnumerable<PSObject> output, out string errors)
        {
            output = Enumerable.Empty<PSObject>();
            var secured = new SecureString();

            foreach (char letter in password)
            {
                secured.AppendChar(letter);
            }
            secured.MakeReadOnly();

            var credentials = new PSCredential(username, secured);
            var connectionInfo = new WSManConnectionInfo(false, computer, 5985, "/wsman", "http://schemas.microsoft.com/powershell/Microsoft.PowerShell", credentials);
            var runspace = RunspaceFactory.CreateRunspace(connectionInfo);

            try
            {
                runspace.Open();
            }
            catch (Exception e)
            {
                errors = e.Message;
                return false;
            }

            return RunPowerShellScriptInternal(script, out output, out errors, runspace);
        }

        public static bool RunPowerShellScriptInternal(string script, out IEnumerable<PSObject> output, out string errors, Runspace runspace)
        {
            output = Enumerable.Empty<PSObject>();

            using (var ps = PowerShell.Create())
            {
                ps.Runspace = runspace;
                ps.AddScript(script);

                try
                {
                    output = ps.Invoke();
                }
                catch (Exception e)
                {
                    Trace.TraceError("Error occurred in PowerShell script: " + e);
                    errors = e.Message;
                    return false;
                }

                if (ps.Streams.Error.Count > 0)
                {
                    errors = String.Join(Environment.NewLine, ps.Streams.Error.Select(e => e.ToString()));
                    return false;
                }

                errors = String.Empty;
                return true;
            }
        }
    }
}
Jason Pan
  • 15,263
  • 1
  • 14
  • 29
  • Thank you for your answer, this code still output the same error on my end. – Picassopolo Feb 15 '23 at 18:19
  • After going over your answer again, I found out that you used "Powershell Get-Printer" as as script instead of just "Get-Printer" like I was, this fixed the problem thank you very much! – Picassopolo Feb 15 '23 at 21:07
0

I managed to make it work by putting the PrintManagement module folder directly in \bin\Debug\net5.0\runtimes\win\lib\net5.0\Modules in my project files.