Function to Set Default Printer | CodeGuru

Function to Set Default Printer

Environment: Windows NT4 SP3; Developed with Visual C++ 6 SP3 SetPrinter is a simple DLL COM that enables you to programmatically set the default printer: The problem that I faced is that if you attempt to specify the default printer from an application, that printer is not actually realized as the default printer by Windows […]

Written By
CodeGuru Staff
CodeGuru Staff
Jul 19, 2000
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Environment: Windows NT4 SP3; Developed with Visual C++ 6 SP3


SetPrinter is a simple DLL COM that enables you to programmatically set the default printer:


  • The problem that I faced is that if you
    attempt to specify the default printer from an application,
    that printer is not actually realized as the default printer by
    Windows immediately.


You can resolve this problem by doing the following:



  • First, install the driver printer on your machine;
  • If You work on Windows 2000, you must use ‘SetDefaultPrinter’ followed by the printer’s name.
  • If You work on Windows 98 or Windows NT 4 you must first call the OpenPrinter function
    in order to retrieve the printer handle. Then you need to call the
    GetPrinter function twice in order to obtain the printer informations.
    You then need to call the WriteProfileString function (Windows NT)
  • Finally, you must notify all windows of this new Windows setting as follows:

    lResult = SendMessageTimeout(HWND_BROADCAST,
                                 WM_SETTINGCHANGE,
                                 0L, 0L,
                                 SMTO_NORMAL,
                                 1000,
                                 NULL);
    	


Or instead of going through all of that, you can use my COM component and its DPSetDefaultPrinter method.
Here is the code for that method so that you can see all that needs to take place to perform a seemingly very
simple task.

STDMETHODIMP CCustomPrinter::DPSetDefaultPrinter(BSTR pPrinterName, int *Result)
{
USES_CONVERSION;
  BOOL bFlag;
  OSVERSIONINFO osv;
  DWORD dwNeeded = 0;
  HANDLE hPrinter = NULL;
  PRINTER_INFO_2 *ppi2 = NULL;
  LPTSTR pBuffer = NULL;
  LONG lResult;
  // What version of Windows are you running?
  osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osv);
  if (!pPrinterName)
	*Result = 0;
	return S_FALSE;
  // If Windows 95 or 98, use SetPrinter…
  if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  {
    // Open this printer so you can get information about it…
    bFlag = OpenPrinter((char*)OLE2CA(pPrinterName), &hPrinter, NULL);
    if (!bFlag || !hPrinter)
		*Result = 0;
		return S_FALSE;
    // The first GetPrinter() tells you how big our buffer should
    // be in order to hold ALL of PRINTER_INFO_2. Note that this will
    // usually return FALSE. This only means that the buffer (the 3rd
    // parameter) was not filled in. You don’t want it filled in here…
    GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
    if (dwNeeded == 0)
    {
      ClosePrinter(hPrinter);
      *Result = 0;
	  return S_FALSE;
    }
    // Allocate enough space for PRINTER_INFO_2…
    ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
    if (!ppi2)
    {
      ClosePrinter(hPrinter);
      *Result = 0;
	  return S_FALSE;
    }
    // The second GetPrinter() will fill in all the current information
    // so that all you need to do is modify what you’re interested in…
    bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
    if (!bFlag)
    {
      ClosePrinter(hPrinter);
      GlobalFree(ppi2);
      *Result = 0;
	  return S_FALSE;
    }
    // Set default printer attribute for this printer…
    ppi2->Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
    bFlag = SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0);
    if (!bFlag)
    {
      ClosePrinter(hPrinter);
      GlobalFree(ppi2);
      *Result = 0;
	  return S_FALSE;
    }
    // Tell all open applications that this change occurred. 
    // Allow each application 1 second to handle this message.
    lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L,
      (LPARAM)(LPCTSTR)”windows”, SMTO_NORMAL, 1000, NULL);
  }
  // If Windows NT, use the SetDefaultPrinter API for Windows 2000,
  // or WriteProfileString for version 4.0 and earlier…
  else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
#if(WINVER >= 0x0500)
    if (osv.dwMajorVersion >= 5) // Windows 2000 or later…
    {
      bFlag = SetDefaultPrinter(pPrinterName);
      if (!bFlag)
        *Result = 0;
		return S_FALSE;
    }
    else // NT4.0 or earlier…
#endif
    {
      // Open this printer so you can get information about it…
      bFlag = OpenPrinter((char*)OLE2CA(pPrinterName), &hPrinter, NULL);
      if (!bFlag || !hPrinter)
        *Result = 0;
		return S_FALSE;
      // The first GetPrinter() tells you how big our buffer should
      // be in order to hold ALL of PRINTER_INFO_2. Note that this will
      // usually return FALSE. This only means that the buffer (the 3rd
      // parameter) was not filled in. You don’t want it filled in here…
      GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
      if (dwNeeded == 0)
      {
        ClosePrinter(hPrinter);
        *Result = 0;
		return S_FALSE;
      }
      // Allocate enough space for PRINTER_INFO_2…
      ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
      if (!ppi2)
      {
        ClosePrinter(hPrinter);
        *Result = 0;
		return S_FALSE;
      }
      // The second GetPrinter() fills in all the current
      // information…
      bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
      if ((!bFlag) || (!ppi2->pDriverName) || (!ppi2->pPortName))
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
        *Result = 0;
		return S_FALSE;
      }
      // Allocate buffer big enough for concatenated string.
      // String will be in form “printername,drivername,portname”…
      pBuffer = (LPTSTR)GlobalAlloc(GPTR,
        lstrlen((char*)OLE2CA(pPrinterName)) +
        lstrlen(ppi2->pDriverName) +
        lstrlen(ppi2->pPortName) + 3);
      if (!pBuffer)
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
		*Result = 0;
		return S_FALSE;
      }
      // Build string in form “printername,drivername,portname”…
      lstrcpy(pBuffer, (char*)OLE2CA(pPrinterName));  lstrcat(pBuffer, “,”);
      lstrcat(pBuffer, ppi2->pDriverName);  lstrcat(pBuffer, “,”);
      lstrcat(pBuffer, ppi2->pPortName);
      // Set the default printer in Win.ini and registry…
      bFlag = WriteProfileString(“windows”, “device”, pBuffer);
      if (!bFlag)
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
        GlobalFree(pBuffer);
        *Result = 0;
		return S_FALSE;
      }
    }
    // Tell all open applications that this change occurred. 
    // Allow each app 1 second to handle this message.
    lResult = SendMessageTimeout(HWND_BROADCAST,
				 WM_SETTINGCHANGE,
				 0L, 0L,
				 SMTO_NORMAL,
				 1000,
				 NULL);
  }
  // Cleanup…
  if (hPrinter)
    ClosePrinter(hPrinter);
  if (ppi2)
    GlobalFree(ppi2);
  if (pBuffer)
    GlobalFree(pBuffer);
*Result = 1;
return S_OK;
}

Installation


  • On each machine where you want to use the SetPrinter component, you must register the DLL as follows:
    regsvr32 <path>SetPrinter.dll;


Downloads


Download SetPrinter project code – 40 Kb
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.