Finding Printer Ports

I am using EnumPrinters to find the printer port of an installed printer.  It is giving me LPT1: as the port.  When I attempt to print using this port, an error is given.  The port in the registry syas that it is Ne02:.  Is there function out there where you can give it LPT1: and it will give you Ne02:?  I would read it from the registry but it is only found under HKEY_CURRENT_USER which make this method unreliable.
paulcaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

nietodCommented:
In what way are you using this?  i.e. how are you printing directly to the port?
0
paulcaAuthor Commented:
The EnumPrinters fills in a list box on a web page with the value of each option equal to name_driver_port.

I have a C++ program that will parse the printer name, driver and port and place these into the DEVNAMES structure and then print the document to the appropriate printer.  The EnumPrinters function returns the friendly name of the port which is not what the DEVNAMES structure is looking for.  It is looking for the Nexx: port.  Is there a relationship between the friendly port name and the Nexx: port name that I can use to get the Nexx: port name?  Or is there a way I can get the Nexx: port name more directly?
0
nietodCommented:
I'm sort of in a hurry here.  But a quick run-through indicated you could use EnumPrinters to fill in a PRINTER_INFO_2 structure, this gives you DEVNAMES structure.  You can get the name (and other info from there).  There may be other ways too, but that should work.
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

paulcaAuthor Commented:
PRINTER_INFO_2 will give me the DEVMODE structure not the DEVNAMES structure.
0
nietodCommented:
Sorry, I meant DEVMODE and in the DEVMODE, in dmDeviceName is the name you want for the DEVNAMES.  right?
0
paulcaAuthor Commented:
That will give me the printer name but I need the port name.  Can I get the port name (Nexx:) from the device name somehow?  I shouldn't need the dmDeviceName since I am passing that from the web interface anyway.
0
nietodCommented:
The port name is in the PRINTER_INFO_2 too.  I was thinking this was A way to get the information but proibably not the THE way to do it.  But apparently it is a good way.  I found this article in the MS knowledge base.  It has some sample code that is doing what you are probably trying to do.  The code is MFC, but you get the idea from it.  (You don't use MFC right?)

***********************************

HOWTO: Obtaining the DEVMODE and DEVNAMES Structures
Last reviewed: November 24, 1997
Article ID: Q166129  
The information in this article applies to:
The Microsoft Foundation Classes (MFC) included with: - Microsoft Visual C++, 32-bit Editions, versions 4.0, 4.1, 4.2, 4.2b,

     5.0




SUMMARY
You need the DEVMODE and DEVNAMES structures to specify a printer in an MFC application when you programmatically print to a non-default (network or secondary) printer. They can be manually constructed using information obtained from the GetPrinter() printer API.



MORE INFORMATION
During a normal print operation in an MFC application, the print dialog box is displayed which allows you to select the printer you want to print to. The default printer displayed in the print dialog box is the default printer specified in the system. MFC stores the default printer of the application in the CWinApp::m_hDevMode and CWinApp::m_hDevNames protected data members. Because MFC initializes these variables to NULL, the MFC print architecture defaults to the system's default printer the first time a print operation is performed. The system default printer's DEVMODE and DEVNAMES are then copied to the MFC application's m_hDevMode and m_hDevNames data members.

Occasionally, a programmer may want to print to a printer other than the default printer without having the user specify it through the print dialog box. Two common examples are:

Set the default printer of the application to something other than the system's default printer.

-or-
Printing directly to a non-default printer such as another network printer.

Whether you need to use the non-default printer on a permanent basis or for only one print job, you need the DEVMODE and DEVNAMES structure to create the printer DC. The PRINTER_INFO_2 structure from GetPrinter() contains all the information needed to fill the DEVMODE and DEVNAMES structures. The printer DC can then be created by the programmer explicitly through CPrintDialog::CreatePrinterDC() or CDC::CreateDC() (among others), or implicitly through the MFC framework.
The sample code below shows how to use GetPrinter() to set the default printer of the application. The code implements a CMyApp function that uses the printer name supplied to globally allocate a new DEVMODE and DEVNAMES structures and set them to the data members of CWinApp. You can call this function from CMyApp::InitInstance(), or anywhere before printing. Note that these structures are not freed because the MFC framework handles this automatically.

To print directly to a non-default printer, create the structures in the OnPreparePrinting, set them to pInfo->m_pPD->m_pd's corresponding data members, and call pInfo-m_pPD->CreatePrinterDC(). Do not call DoPreparePrinting().



Sample Code

   class CMyApp : public CWinApp
   {
   public:
       CTestprintApp();
       BOOL SetPrinterDevice(char*);
       ...
   };

   #include <winspool.h>

   BOOL CMyApp::SetPrinterDevice(char* pszDeviceName)
   {
   // Open printer and obtain PRINTER_INFO_2 structure.
   HANDLE hPrinter;
   if (OpenPrinter(pszDeviceName, &hPrinter, NULL) == FALSE)
       return FALSE;
   DWORD dwBytesReturned, dwBytesNeeded;
   GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
   PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR,
       dwBytesNeeded);
   if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded,
       &dwBytesReturned) == 0) {
   GlobalFree(p2);
   ClosePrinter(hPrinter);
   return FALSE;
   }
   ClosePrinter(hPrinter);

   // Allocate a global handle for DEVMODE and copy DEVMODE data.
   HGLOBAL  hDevMode = GlobalAlloc(GHND, sizeof(*p2->pDevMode));
   DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);
   memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode));
   GlobalUnlock(hDevMode);

   // Compute size of DEVNAMES structure you'll need.
   DWORD drvNameLen = strlen(p2->pDriverName);  // driver name
   DWORD ptrNameLen = strlen(p2->pPrinterName); // printer name
   DWORD porNameLen = strlen(p2->pPortName);    // port name
   DWORD devNameSize = sizeof(DEVNAMES) +
       ptrNameLen + porNameLen + drvNameLen + 3;

   // Allocate a global handle big enough to hold DEVNAMES.
   HGLOBAL   hDevNames = GlobalAlloc(GHND, devNameSize);
   DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);

   // Copy the DEVNAMES information from PRINTER_INFO_2 structure.
   pDevNames->wDriverOffset = sizeof(DEVNAMES);
   memcpy((char*)pDevNames + pDevNames->wDriverOffset,
       p2->pDriverName, drvNameLen);

   pDevNames->wDeviceOffset = sizeof(DEVNAMES) +
   drvNameLen + 1;
   memcpy((char*)pDevNames + pDevNames->wDeviceOffset,
       p2->pPrinterName, ptrNameLen);

   pDevNames->wOutputOffset = sizeof(DEVNAMES) +
       drvNameLen + ptrNameLen + 2;
   memcpy((char*)pDevNames + pDevNames->wOutputOffset,
       p2->pPortName, porNameLen);

   pDevNames->wDefault = 0;

   GlobalUnlock(hDevNames);
   GlobalFree(p2);   // free PRINTER_INFO_2

   m_hDevMode = hDevMode;
   m_hDevNames = hDevNames;
   return TRUE;
   }


(c) Microsoft Corporation 1997, All Rights Reserved. Contributions by Adam Kim, Microsoft Corporation
Keywords          : MfcPrinting kbprint
Technology        : kbMfc
Version           : 4.0 4.1 4.2 4.2b 5.0
Platform          : NT WINDOWS
Issue type        : kbhowto



--------------------------------------------------------------------------------



THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
paulcaAuthor Commented:
I have wrote a program similar to the one above but I used EnumPrinters to get the port name.  The port name obtained from PRINTER_INFO_2 gave me an error when I placed this into DEVNAMES and tried to print.  If I hard coded Nexx: port name into the DEVNAMES struct, the print worked.  How can I get the Nexx: port name from PRINTER_INFO_2 or somewhere else?
0
nietodCommented:
What was the port name obtain from PRITNER_INFO_2?
What is "Nexx:"?  I have never heard of it as a port name.  The only ones I know of are COMx and LPTx.

This information all comes from the registry, but I don't know where and I really wouldn't recommend pulling it directly from there anyways (The OS can change its scheme at a moments notice.  (I already has, this used to come from the windows.ini file.)
0
paulcaAuthor Commented:
I have found the problem.  The port name was correct.  I was concatenating some garbage onto the port name when I was parsing out DEVNAMES.  I have it straightened up now. Thanks.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Software

From novice to tech pro — start learning today.