Art C

Art C

  • 1.5k
  • 203
  • 125

Use Powershell Add- and Get-Printer in C# WPF program

Oct 22 2024 10:00 PM

Hello! I'm new here, so please be gentle. I'm working on a small program to map network printers for an enterprise I work for. My ability to access the printers is limited to standard user permissions and I can make no changes to the network whatsoever.

I got this working fairly easily using PowerShell's Get-Printer and Add-Printer cmdlets, but when I attempted to use the same commands in C# I discovered that those two cmdlets do not seem to be included in the System.Management.Automation library. The PowerShell code I am attempting to adapt is below:

Function mapPrinter () {
    try {
        $title = "Printer Mapping Status"
        $message = "Printer successfully mapped! Please allow some time for printer to appear as an option."

        if ($PrinterListBox.SelectedItems.Count -gt 0) {
            foreach ($printer in $PrinterListBox.SelectedItems) {
                $printerPath = "\\" + $printer.SERVER + "\" + $printer.PRINTER
                Add-Printer -ConnectionName $printerPath -ErrorAction Stop
            }

            displayMessage -msg $message -ttl $title

            $PrinterMapButton.IsEnabled = $false
        }
    }
    catch {
        $message = ""
        $title = "Printer Mapping Error"
        displayMessage -msg $message -ttl $title
    }
}

I attempted to import the PrintManagement module into the runspace of the PowerShell instance, but every attempt I made failed. The latest attempt is below:

       private void mapPrinter(object sender, RoutedEventArgs e)
        {
            if (PrinterListBox.SelectedItems.Count > 0)
            {
                foreach (PrinterObject printer in PrinterListBox.SelectedItems)
                {
                    InitialSessionState iss = InitialSessionState.CreateDefault();
                    iss.ImportPSModule("PrintManagement");
                    using (Runspace runSpace = RunspaceFactory.CreateRunspace(iss)) 
                    {
                        runSpace.Open();

                        using (var pipeline = runSpace.CreatePipeline())
                        {
                            string printerPath = "\\\\" + printer.Server + "\\" + printer.Printer;
                            var parameters = new Dictionary<string, object>
                            {
                                {"ComputerName", printer.Server},
                                {"ConnectionName", printerPath},
                                {"ErrorAction", "Stop"}
                            };

                            Command cmd = new Command("Add-Printer");
                            cmd.Parameters.Add("ComputerName", printer.Server);
                            cmd.Parameters.Add("ConnectionName", printerPath);
                            cmd.Parameters.Add("ErrorAction", "Stop");

                            pipeline.Commands.Add(cmd);
                            pipeline.Invoke();
                        }
                    }
                }
            }
        }

I have also attempted to use CimSession for this purpose. In that case, I managed to get the mapping functionality working, but when attempting to do connection validation it has thus far failed. I can't assume the paths fed to the program are valid, so I need to be able to test them prior to presenting them to users as an option. The "easiest" way to do this is the Add- and Get-Printer cmdlets, but they have thus far proven to be very far from easy.

My question / request is this: how the devil do you get Add- and Get-Printer working in C#?


Answers (1)