Click here to Skip to main content
15,886,724 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
Hi,

Follow Win32_printer class, is able to view printer status and delete printer as well.
Try to use similar way to set workoffline property. The value can be set, but the printer can't change its status as offline.
C#
ManagementScope managementScope = new ManagementScope(ManagementPath.DefaultPath);
            managementScope.Connect();
            SelectQuery selectQuery = new SelectQuery();
            selectQuery.QueryString = "Select * from win32_Printer where Name = '" + "Printer Name" + "'";
            ManagementObjectSearcher MOS = new ManagementObjectSearcher(managementScope, selectQuery);
            ManagementObjectCollection MOC = MOS.Get();
            foreach (ManagementObject mo in MOC)
            {
                //mo.Delete();  //in case of printer delete

                // Printer WorkOffline property as False by default
                MessageBox.Show(mo.ToString() + "\n Offline:" + mo["WorkOffline"].ToString());
                mo.SetPropertyValue("WorkOffline",true);

                //  Printer WorkOffline property was set True successfully 
                MessageBox.Show(mo.ToString() + "\n Offline: " + mo["WorkOffline"].ToString());                
            }
// WorkOffline property can't make current printer to set Offline status.

Any good idea to set printer offline by c#?
Posted
Updated 13-Apr-22 7:18am
v3
Comments
Maciej Los 16-Jul-14 2:00am    
Not a question at all!
Tom6012 16-Jul-14 3:06am    
Any idea to set printer as offline by C#?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

namespace PrinterInfo
{
    class Program
    {
        static void Main(string[] args)
        {
            string printerName = "Brother%";
            string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '{0}'", printerName);

            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
            using (ManagementObjectCollection coll = searcher.Get())
            {
                try
                {
                    foreach (ManagementObject printer in coll)
                    {
						foreach (PropertyData property in printer.Properties)
						{
							Console.WriteLine(string.Format("{0}: {1}", property.Name, property.Value));
						}
						printer.SetPropertyValue("DriverName", printer["DriverName"]);
						printer.SetPropertyValue("PortName", printer["PortName"]);
						printer.SetPropertyValue("DeviceID", printer["DeviceID"]);

                        bool SetPrinterOffline = (bool)printer["WorkOffline"];

                        if (SetPrinterOffline == true)
                            SetPrinterOffline = false;
						else
							SetPrinterOffline = true;

						printer.SetPropertyValue("WorkOffline", SetPrinterOffline);
                        printer.Put();
                        //Console.WriteLine(string.Format("{0}: {1}", printer["Name"], printer["WorkOffline"]));
						Console.WriteLine(string.Format("{0} WorkOffline: {1}", printer["Name"], printer["WorkOffline"]));                        
						//Console.ReadKey();
                        
                    }
                }
                catch (ManagementException ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
}
 
Share this answer
 
Use the SetPrinter[^] API call with the parameter command set to PRINTER_CONTROL_SET_STATUS and the parameter pPrinter set to PRINTER_STATUS_OFFLINE
 
Share this answer
 
Comments
Tom6012 17-Jul-14 6:54am    
It looks not support Win7/8.
Duncan Edwards Jones 17-Jul-14 7:20am    
It does support Win7 - that's what I use.
See http://msdn.microsoft.com/en-us/library/windows/desktop/dd145082(v=vs.85).aspx

Make sure in pPrinter you are passing the new status value, not a pointer to the new status value...
Tom6012 21-Jul-14 23:17pm    
Hi Duncan,

Yes, Win7 work well!
But Win 8 have system error 6 found in disable printer rountine.
As checking SetPrinter return False, and Marshal.GetLastWin32Error() return 6.

Portion of disable printer routine.
static unsafe void CSDisablePrinter(int hPrinter)
{
if (!SetPrinter(hPrinter, 0,
(byte*)PRINTER_STATUS_OFFLINE, PRINTER_CONTROL_SET_STATUS))
{
throw new ApplicationException("Cannot disable printer " + Marshal.GetLastWin32Error());
}

List all of code as below

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices; // DllImport

// rference page http://support.microsoft.com/kb/315720/zh-tw

namespace PrintAPI
{
public partial class Form1 : Form
{

unsafe struct PRINTER_DEFAULTS
{
public void* pDatatype; // LPTSTR
public void* pDevMode; // LPDEVMODE
public uint DesiredAccess; // ACCESS_MASK
};

[DllImport("kernel32", SetLastError = true)]
static extern int GetLastError();

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

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

[DllImport("WinSpool.drv", SetLastError = true)]
static extern unsafe bool SetPrinter(int hPrinter, uint Level, void* pPrinter, uint Command);

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;

// 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("Cannot open printer '" + printerName + "' " + Marshal.GetLastWin32Error());
}
return hPrinter;
}

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

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

// Resume printer.
static unsafe void CSResumePrinter(int hPrinter)
{
if (!SetPrinter(hPrinter, 0, null, PRINTER_CONTROL_RESUME))
{
throw new ApplicationException("Cannot resume printer " + 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("Cannot disable printer " + Marshal.GetLastWin32Error());
}
}

// Enable printer.
static unsafe void CSEnablePrinter(int hPrinter)
{
if (!SetPr
Copy into C++ console program, but get a lot of error.

C++
// PrinterAPItest.cpp : 
//

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

// MySetPrinter
// 
// Demonstrates how to use the SetPrinter API.  This particular function changes the orienation
// for the printer specified in pPrinterName to the orientation specified in dmOrientation.
// 
// Valid values for dmOrientation are:
// DMORIENT_PORTRAIT (1)
// or
// DMORIENT_LANDSCAPE (2)

BOOL MySetPrinter(LPTSTR pPrinterName, short dmOrientation)
{
	HANDLE hPrinter = NULL;
	DWORD dwNeeded = 0;
	PRINTER_INFO_2 *pi2 = NULL;
	DEVMODE *pDevMode = NULL;
	PRINTER_DEFAULTS pd;
	BOOL bFlag;
	LONG lFlag;

	// Open printer handle (on Windows NT, you need full-access because you
	// will eventually use SetPrinter)...
	ZeroMemory(&pd, sizeof(pd));
	pd.DesiredAccess = PRINTER_ALL_ACCESS;
	bFlag = OpenPrinter(pPrinterName, &hPrinter, &pd);
	if (!bFlag || (hPrinter == NULL))
		return FALSE;

	// The first GetPrinter tells you how big the buffer should be in 
	// order to hold all of PRINTER_INFO_2. Note that this should fail with 
	// ERROR_INSUFFICIENT_BUFFER.  If GetPrinter fails for any other reason 
	// or dwNeeded isn't set for some reason, then there is a problem...
	SetLastError(0);
	bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
         if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || 
         (dwNeeded == 0))
	{
		ClosePrinter(hPrinter);
		return FALSE;
	}

	// Allocate enough space for PRINTER_INFO_2...
	pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
	if (pi2 == NULL)
	{
		ClosePrinter(hPrinter);
		return FALSE;
	}

	// The second GetPrinter fills in all the current settings, so all you
	// need to do is modify what you're interested in...
	bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
	if (!bFlag)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		return FALSE;
	}

	// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
	// DocumentProperties...
	if (pi2->pDevMode == NULL)
	{
		dwNeeded = DocumentProperties(NULL, hPrinter,
						pPrinterName,
						NULL, NULL, 0);
		if (dwNeeded <= 0)
		{
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			return FALSE;
		}

		pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded);
		if (pDevMode == NULL)
		{
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			return FALSE;
		}

		lFlag = DocumentProperties(NULL, hPrinter,
						pPrinterName,
						pDevMode, NULL,
						DM_OUT_BUFFER);
		if (lFlag != IDOK || pDevMode == NULL)
		{
			GlobalFree(pDevMode);
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			return FALSE;
		}

		pi2->pDevMode = pDevMode;
	}

	// Driver is reporting that it doesn't support this change...
	if (!(pi2->pDevMode->dmFields & DM_ORIENTATION))
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
			GlobalFree(pDevMode);
		return FALSE;
	}

	// Specify exactly what we are attempting to change...
	pi2->pDevMode->dmFields = DM_ORIENTATION;
	pi2->pDevMode->dmOrientation = dmOrientation;

	// Do not attempt to set security descriptor...
	pi2->pSecurityDescriptor = NULL;

	// Make sure the driver-dependent part of devmode is updated...
	lFlag = DocumentProperties(NULL, hPrinter,
		  pPrinterName,
		  pi2->pDevMode, pi2->pDevMode,
		  DM_IN_BUFFER | DM_OUT_BUFFER);
	if (lFlag != IDOK)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
			GlobalFree(pDevMode);
		return FALSE;
	}

	// Update printer information...
	bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
	if (!bFlag)
	// The driver doesn't support, or it is unable to make the change...
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
			GlobalFree(pDevMode);
		return FALSE;
	}

	// Tell other apps that there was a change...
	SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L,
			  (LPARAM)(LPCSTR)pPrinterName,
			  SMTO_NORMAL, 1000, NULL);

	// Clean up...
	if (pi2)
		GlobalFree(pi2);
	if (hPrinter)
		ClosePrinter(hPrinter);
	if (pDevMode)
		GlobalFree(pDevMode);

	return TRUE;
}
 
Share this answer
 
Refer below link for c# offline printer code
http://support.microsoft.com/kb/315720/en-us[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900