Managing Printers Programatically using C# and WMI

By | May 12, 2010

This is another part of my series regarding start up scripts. This post is for Printer Management, now why do I have to do that? I was tasked to do this as we have to map each printer in every shop we had when a user logs in. Now this is all managed in a SQL Server database where their subnets (which is unique per shop) are mapped to a printer or many printers, so any configuration changes have to be done in SQL Server rather than manually updating all of the clients, these configuration changes are things such as renaming printers (we have to do this as we still have some legacy apps that rely on Printer1 and Printer2, if you know what I mean), changing the IP Ports, changing default printers and much more.

Now I had created a class library to handle the Printer Management, I have 5 main methods that I normally use


1. AddPrinter – Adds or maps a specific printer to the client machine.

2. DeletePrinter – Removes or unmaps a specific printer to the client machine.

3. RenamePrinter – Renames the printer on the client machine.

4. SetDefaultPrinter – Sets the printer as default on clients machine.

5. GetPrinterInfo – Gets the Printer Information.

6. IsPrinterInstalled – Checks whether the printer is installed.

Now for the the codes:

using System;
using System.Management;

class PrinterSettings
{
    private static ManagementScope oManagementScope = null;
    //Adds the Printer
    public static bool AddPrinter(string sPrinterName)
    {
        try
        {
            oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
            oManagementScope.Connect();

            ManagementClass oPrinterClass = new ManagementClass(new ManagementPath("Win32_Printer"), null);
            ManagementBaseObject oInputParameters = oPrinterClass.GetMethodParameters("AddPrinterConnection");

            oInputParameters.SetPropertyValue("Name", sPrinterName);

            oPrinterClass.InvokeMethod("AddPrinterConnection", oInputParameters, null);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    //Deletes the printer
    public static bool DeletePrinter(string sPrinterName)
    {
        oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\""\\") + "'";

        ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery);
        ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();

        if (oObjectCollection.Count != 0)
        {
            foreach (ManagementObject oItem in oObjectCollection)
            {
                oItem.Delete();
                return true;
            }
        }
        return false;
    }
    //Renames the printer
    public static void RenamePrinter(string sPrinterName, string newName)
    {
        oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\""\\") + "'";

        ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery);
        ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();

        if (oObjectCollection.Count != 0)
        {
            foreach (ManagementObject oItem in oObjectCollection)
            {
                oItem.InvokeMethod("RenamePrinter"new object[] { newName });
                return;
            }
        }

    }
    //Sets the printer as Default
    public static void SetDefaultPrinter(string sPrinterName)
    {
        oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\""\\") + "'";

        ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery);
        ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();

        if (oObjectCollection.Count != 0)
        {
            foreach (ManagementObject oItem in oObjectCollection)
            {
                oItem.InvokeMethod("SetDefaultPrinter"new object[] { sPrinterName });
                return;

            }
        }
    }
    //Gets the printer information
    public static void GetPrinterInfo(string sPrinterName)
    {
        oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\""\\") + "'";

        ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, @oSelectQuery);
        ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();

        foreach (ManagementObject oItem in oObjectCollection)
        {
            Console.WriteLine("Name : " + oItem["Name"].ToString());
            Console.WriteLine("PortName : " + oItem["PortName"].ToString());
            Console.WriteLine("DriverName : " + oItem["DriverName"].ToString());
            Console.WriteLine("DeviceID : " + oItem["DeviceID"].ToString());
            Console.WriteLine("Shared : " + oItem["Shared"].ToString());
            Console.WriteLine("---------------------------------------------------------------");
        }
    }
    //Checks whether a printer is installed
    public bool IsPrinterInstalled(string sPrinterName)
    {
        oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE Name = '" + sPrinterName.Replace("\""\\") + "'";

        ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery);
        ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();

        return oObjectCollection.Count > 0;
    }
}

If you had noticed on my WMI Queries I added @” on each query you need this because it terminates the character , to make it more confusing my Printer Name variable is something similar to  this \\ServerName\PrinterName“, now to make it more confusing I added “Replace(“\”, “\\”)”. Now what the hell am I doing.

The issue is that the character is the escape symbol for both C# and WQL and Using @” tells C# not to escape the  but you need to tell WQL the same thing.  In C# I had used @” to escape the querystring which instructs the compiler to treat ANY special characters in the string as literals which then means you don’t need to escape the symbol for C# but we need an extra as an escape for WQL parser.

To further elaborate.  In my parameter sPrinterName the value as text is \ServerNamePrinterName but since its in C# you will see when you put a watch on it, it will show as \\ServerName\PrinterName” its only when it is passed as the parameter then it is recognized as \ServerNamePrinterName that’s why I have to do the replace so it would be \\ServerName\PrinterName” again (which is a proper format for WQL) and add @ for C# to escape it.


8 thoughts on “Managing Printers Programatically using C# and WMI

  1. Marc Moennikes

    Thanks. Do you have other articles in the series regarding start up scripts?
    I have found another article about network drives in your blog.
    I am thinking about develoing a small application for managing user environment.
    Printer, drives, regkeys, desktop links…

    Thanks

    Reply
    1. rsmacaalay

      I have several of these but I have not posted it on-line. I had a similar project before hence most of what you need I might have just let me know what components you need I might be able to help.

      Reply
      1. Marc Moennikes

        Hello,

        thanks for your reply.
        Well first step will be printer (default printer and additional printers), network drive mapping, registry keys and shortcut/links on desktop and/or startmenue. Maybe after that favorites, copying files or so.
        Configuration stored in database…
        So at the moment the plan. We have also taken a closer look on products at the market, but most of them have a lot of functionality we did not need.

        regards

        Reply
  2. Amit

    How can i print landscape without dilog by WMI or Printdocument .I want to print on network printer?

    Reply

Leave a Reply