Microsoft KB Archive/315720

= How to enable and disable a printer by using the SetPrinter function in Visual C# =

Article ID: 315720

Article Last Modified on 12/11/2006

-

APPLIES TO


 * Microsoft Visual C# .NET 2002 Standard Edition
 * Microsoft Visual C# 2005 Express Edition

-



This article was previously published under Q315720



This article refers to the following Microsoft .NET Framework Class Library namespace:
 * System.Runtime.InteropServices

IN THIS TASK
SUMMARY
 * Requirements
 * Create an Application to Control the Printer
 * Build the Application
 * Verification
 * Troubleshooting

REFERENCES



SUMMARY
This step-by-step article shows you how to programmatically enable and disable printing functionality on a printer installed on a computer that supports the Win32 application programming interface (API) in Visual C#.

back to the top

Requirements
You need the following hardware and software to perform the procedures in this article:
 * A Microsoft Windows NT, Microsoft Windows 2000, Microsoft Windows Server 2003, or Microsoft Windows XP-based computer
 * Microsoft Visual Studio .NET or Microsoft Visual Studio 2005

You need the following skills to perform the procedures in this article:
 * C# programming experience
 * Basic knowledge of the Windows API

back to the top

Create an Application to Control the Printer
To create an application to control the printer, follow these steps:  Start Visual Studio .NET or Visual Studio 2005, and then create a new Visual C# console application project named PrinterControl.  Edit Class1.cs in Visual Studio .NET or Program.cs in Visual Studio 2005. After the using System; statement, add the following statement: using System.Runtime.InteropServices;   At the start of the body of class Class1 in Visual Studio .NET or class Program in Visual Studio 2005, add the following structure declaration: unsafe struct PRINTER_DEFAULTS {    public void * pDatatype;     // LPTSTR public void * pDevMode;     // LPDEVMODE public uint  DesiredAccess; // ACCESS_MASK };                     After the structure declaration, add the following declarations for Windows API functions: [DllImport(&quot;kernel32&quot;, SetLastError=true)] static extern int GetLastError;

[DllImport(&quot;WinSpool.drv&quot;, SetLastError=true)] static extern unsafe bool OpenPrinter (string pPrinterName, int * phPrinter, void * pDefault);

[DllImport(&quot;WinSpool.drv&quot;, SetLastError=true)] static extern bool ClosePrinter(int hPrinter);

[DllImport(&quot;WinSpool.drv&quot;,SetLastError=true)] static extern unsafe bool SetPrinter (int hPrinter, uint Level, void * pPrinter, uint Command);   After the function declaration, add the following constants for use in the Windows API functions: const uint PRINTER_ACCESS_ADMINISTER = 0x00000004; const uint PRINTER_STATUS_OFFLINE = 0x00000080; const uint PRINTER_CONTROL_PAUSE = 1; const uint PRINTER_CONTROL_RESUME = 2; const uint PRINTER_CONTROL_PURGE = 3; const uint PRINTER_CONTROL_SET_STATUS = 4;   You can call the Windows API functions directly in your code. However, it is more convenient to place them in wrapper functions that handle the unsafe code and provide error handling through exceptions. Add the following wrapper functions in Class1: // Open a printer for administration operations. static unsafe int CSOpenPrinter(string printerName) {   bool bResult; int hPrinter; PRINTER_DEFAULTS pd;

pd.pDatatype    = null; pd.pDevMode     = null; pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER; bResult = OpenPrinter(printerName, &hPrinter, &pd); if (!bResult) {       throw new ApplicationException(&quot;Cannot open printer '&quot; +                                         printerName + &quot;' &quot; +                                         Marshal.GetLastWin32Error); }   return hPrinter; }

// Close the printer. static void CSClosePrinter(int hPrinter) {   if (!ClosePrinter(hPrinter)) {       throw new ApplicationException(&quot;Cannot close printer &quot; +                                        Marshal.GetLastWin32Error); } }

// Pause printer. static unsafe void CSPausePrinter(int hPrinter) {   if (!SetPrinter(hPrinter, 0, null, PRINTER_CONTROL_PAUSE)) {       throw new ApplicationException(&quot;Cannot pause printer &quot; +                                         Marshal.GetLastWin32Error); } }

// Resume printer. static unsafe void CSResumePrinter(int hPrinter) {   if (!SetPrinter(hPrinter, 0, null, PRINTER_CONTROL_RESUME)) {       throw new ApplicationException(&quot;Cannot resume printer &quot; +                                         Marshal.GetLastWin32Error); } }

// Disable printer (offline). static unsafe void CSDisablePrinter(int hPrinter) {   if (!SetPrinter(hPrinter, 0, (byte*)PRINTER_STATUS_OFFLINE, PRINTER_CONTROL_SET_STATUS)) {       throw new ApplicationException(&quot;Cannot disable printer &quot; +                                         Marshal.GetLastWin32Error); } }

// Enable printer. static unsafe void CSEnablePrinter(int hPrinter) {   if (!SetPrinter(hPrinter, 0, (byte*)0, PRINTER_CONTROL_SET_STATUS)) {       throw new ApplicationException(&quot;Cannot enable printer &quot; +                                         Marshal.GetLastWin32Error); } }                     Add the following code in the Main function to call the wrapper functions to demonstrate the printer control operations (you will need to specify your printer name in the CSOpenPrinter function call): [STAThread] static void Main(string[] args) {   int hPrinter; try { // Edit the following line to match your printer name. hPrinter = CSOpenPrinter(&quot;YourPrinterName&quot;);

CSDisablePrinter(hPrinter); Console.WriteLine(&quot;The printer is disabled&quot;); Console.ReadLine;

CSEnablePrinter(hPrinter); Console.WriteLine(&quot;The printer is enabled&quot;); Console.ReadLine;

CSPausePrinter(hPrinter); Console.WriteLine(&quot;The printer is paused&quot;); Console.ReadLine; CSResumePrinter(hPrinter); Console.WriteLine(&quot;The printer is resumed&quot;); Console.ReadLine; CSClosePrinter(hPrinter); }   catch (ApplicationException e)    { Console.WriteLine(&quot;Exception: {0}&quot;, e.Message); } }                   </li></ol>

back to the top

Build the Application
Before you build the application, you must enable unsafe code compilation for your project.

To do this, follow these steps:
 * 1) In Solution Explorer, right-click PrinterControl, and then click Properties on the shortcut menu.
 * 2) In the PrinterControl Property Pages dialog box, click Configuration Properties, and then set Allow unsafe code blocks to True.

Note In Visual Studio 2005, click Build in the PrintControl Property Pages dialog box, and then click to select the Allow unsafe code check box.
 * 1) Click OK.
 * 2) Build the application.

back to the top

Verification
<ol> Before you run the application, open the Printers window to display the name and status of each printer on your computer.

To do this in Windows XP, click Start, and then click Printers and Faxes.

In Windows Server 2003, Windows 2000, Windows NT, Microsoft Windows Millennium Edition, and Microsoft Windows 98, click Start, point to Settings, and then then click Printers.</li> Run your application in Visual Studio .NET or in Visual Studio 2005.</li> The application displays the following message:

The printer is disabled

Verify the printer is disabled by looking in the Printers folder. Press Enter in the application window, to continue the application.

Press ENTER.</li> The application displays the following message:

The printer is enabled

Verify that the printer is enabled by looking in the Printers folder. Press Enter in the application window, to continue the application.

Press ENTER.</li> The application displays the following message:

The printer is paused

Verify that the printer is paused by looking in the Printers folder. Press Enter in the application window, to continue the application.

Press ENTER.</li> The application displays the following message:

The printer is resumed

Verify that the printer is resumed by looking in the Printers folder. Press Enter in the application window, to continue the application.

Press ENTER. The application terminates.</li></ol>

back to the top

Troubleshooting
The SetPrinter function requires appropriate permissions on Windows XP, Windows 2000, Windows Server 2003, and Windows NT-based systems. If you do not have administrative rights on the specified printer, the SetPrinter function call fails.

back to the top

<div class="references_section">