How do I determine a printer's port?

I've been trying to acertain the port of a the default printer using Printers.Printer.GetPrinter() and the resulting port is not accurate, causing all sorts of issues when I try to use it.

My code is:

Procedure GetDefaultPrinterProperties;
var
  hMode   : THandle;
  pName   : PChar;
  pDriver : PChar;
  pPort   : PChar;
  sName   : string;
  sDriver : string;
  sPort   : string;
  pMode : PDevMode;
begin
  if Printer.Printers.Count = 0 then
    exit;

  pName := StrAlloc(255);
  pDriver := StrAlloc(255);
  pPort := StrAlloc(255);
  Printers.Printer.GetPrinter(pName, pDriver, pPort, hMode);
  pMode := GlobalLock(hMode);

  sPort := String(pPort);
  if Length(sPort) = 0 then
    begin
      GetProfileString('Devices', pName, '', pPort, MAX_PATH);
      sPort := String(pPort);
      i := Pos(',',sPort);
      sPort := Copy(sPort, i + 1, Length(sPort));
      i := Pos('winspool,',sPort);
      if i > 0 then
        sPort := Copy(sPort, i+9, Length(sPort));
    end;

  GlobalUnlock(hMode);
  StrDispose(pName);
  StrDispose(pDriver);
  StrDispose(pPort);
end;

I do get the pName, but the pPort and pDriver is always blank.  If I try to use GetProfileString('Devices', pName, '', pPort, MAX_PATH), it give me the wrong port.

I've been searching the web for days....

Thanks for your assistance,

Jacob
LVL 6
Jacob78Asked:
Who is Participating?
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
Try this way using winspool

uses Winspool;

Function GetDefaultPrinterInfo: String;
var
  Buffer, PrinterInfo: PAnsiChar;
  I, Count, Flags, NumInfo: Cardinal;
  Level: Byte;
  DefaultPrinter: array [0..79] of Char;
  st, shared, value: String;
begin
  Result := '';
  try
    getprofilestring('windows', 'device', '', DefaultPrinter, SizeOf(DefaultPrinter) - 1);
    I := 0;
    while DefaultPrinter[I] <> ',' do
    begin
      st := st+DefaultPrinter[I];
      inc(I);
    end;
    Flags := PRINTER_ENUM_CONNECTIONS or PRINTER_ENUM_LOCAL;
    Level := 2;
    Count := 0;
    EnumPrinters(Flags, nil, Level, nil, 0, Count, NumInfo);
    if Count = 0 then
      Exit;
    GetMem(Buffer, Count);
    try
      if not EnumPrinters(Flags, nil, Level, PByte(Buffer), Count, Count, NumInfo) then
        Exit;
      PrinterInfo := Buffer;
      for I := 0 to NumInfo - 1 do
      begin
        value := '';
        shared := '';
        with PPrinterInfo2(PrinterInfo)^ do
        begin
          if pPrinterName <> nil then
            If Format('%s', [pPrinterName])= st then
            begin
              if pdriverName <> nil then
                value := Format('Driver: %s - ', [pdriverName]);
              if pPrinterName <> nil then
                value := Format('%sPrinter: %s - ', [value, pPrinterName]);
              if pServerName <> nil then
                shared := Format('%s\%s', [pServerName, pShareName])
              else if pPortName <> nil then
                shared := Format('%s', [pPortName]);
              if shared <>'' then
                value := Format('%sPort: %s', [value, shared]);
              Result := value;
              break;
            end;
          inc(PrinterInfo, SizeOf(TPrinterInfo2));
        end;
      end;
    finally
      FreeMem(Buffer, Count);
    end;
  except
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(GetDefaultPrinterInfo);
end;

Open in new window

0
 
Jacob78Author Commented:
Thanks,

The code seems to work perfectly...  

A couple of questions:

1)  How could I extrapolate this code to obtain the PaperSize and PaperSource?
2)  Rather than use the code:

   getprofilestring('windows', 'device', '', DefaultPrinter, SizeOf(DefaultPrinter) - 1);
    I := 0;
    while DefaultPrinter[I] <> ',' do
    begin
      st := st+DefaultPrinter[I];
      inc(I);
    end;

Is there a downside to using the Printer.Printers[Printer.PrinterIndex] to get the Device Name of the Default printer...    This way I can get use the code to obtain information from the Default printer on load and then for any subsequent selected printer..?

Thanks again
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
Even if you use  Printer.GetPrinter(pName... you have to extract the right name from pName to use it with Winspool like GetProfileString, so it is redundant

Anyway you could combine Printer.GetPrinter and winspool.DeviceCapabilities






0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.