How to use API Winspool.EnumprinterData in Delphi?

女生的网名这么多〃 提交于 2020-06-28 05:01:46

问题


Does anyone have experience with using the Winspool.EnumprinterData API in Delphi?

I found a demo for C++: https://s-kita.hatenablog.com/entry/20120227/1330353801

I tried to covert it to Delphi as below:

procedure TForm1.GetPrinterData;
var
 hPrinter  : THandle;
 pInfo:  PPrinterInfo2;
 bytesNeeded: DWORD;
 dwRet : DWORD;
 dwIndex: DWORD;
 pValueName: PWideChar;
 pTagName: PWideChar;
 cbValueName: DWORD;
 pcbValueName : DWORD;
 pType: DWORD;
 pData: PByte;
 cbData: DWORD;
 pcbData: PDWORD;
 i : Integer;
 printername : String;
 dwValueNameSize : DWORD;
 dwDataSize : DWORD;
 begin
   hprinter := GetCurrentPrinterHandle;
   dwRet := EnumPrinterDataw(hprinter,i,nil,0, pcbValueName,pType,nil,0,pcbData);
 end;

Question 1: EnumPrinterDataW result is not the same, even if I chose the same printer, and it often raises an Access Violation error.

Question 2: the API has many pointer type variables, the next step should allocate memory to some variable, but I do not know how to do thqt. For example pData: PByte; Pdata = Allocmem(pcbData^); <==== this is difficult to me, Pdata is TByte, how to allocmem(pcbData^) is TPwidechar how to do this?

This has taken me 2 days to deal with, and it is still a mess !!!!


回答1:


There are some mistakes in your code:

  • you are not checking if GetCurrentPrinterHandle() returns a valid printer handle.

  • you are not initializing your i variable. You need to pass a 0-based index to EnumPrinterData(), but the value of i is indeterminate.

  • you are not initializing your pcbData variable. EnumPrinterData() expects a pointer to a DWORD variable that will receive the size of the data written to the pData buffer (or the needed size of the pData buffer if pData is nil). But your pcbData is not pointing to a valid DWORD.

Try something more like this:

procedure TForm1.GetPrinterData;
var
  hPrinter: THandle;
  dwIndex,
  dwRet,
  dwType,
  dwMaxValueNameSize,
  dwMaxDataSize,
  dwValueNameSize,
  dwDataSize: DWORD;
  pValueName,
  lpData: array of Byte;
  sValueName: UnicodeString; // or WideString in D2007 and earlier
begin
  hPrinter := GetCurrentPrinterHandle;
  if hPrinter = 0 then
    Exit; // or raise an exception

  try
    dwIndex := 0;

    dwRet = EnumPrinterData(hPrinter, dwIndex, nil, 0, dwMaxValueNameSize, dwType, nil, 0, @dwMaxDataSize);
    if dwRet = ERROR_NO_MORE_ITEMS then
      Exit
    else if dwRet <> ERROR_SUCCESS then
      RaiseLastOSError(dwRet);

    SetLength(pValueName, dwMaxValueNameSize);
    SetLength(pData, dwMaxDataSize);

    repeat
      dwValueNameSize := 0;
      dwDataSize := 0;

      dwRet = EnumPrinterData(hPrinter, dwIndex, PWideChar(pValueName), dwMaxValueNameSize, dwValueNameSize, dwType, PByte(pData), dwMaxDataSize, @dwDataSize);
      if dwRet = ERROR_NO_MORE_ITEMS then
        Exit
      else if dwRet <> ERROR_SUCCESS then
        RaiseLasstOSError(dwRet);

      SetLength(sValueName, PWideChar(pValueName), (dwValueNameSize div SizeOf(WideChar)) - 1); // -1 for null terminator

      // use dwType, sValueName, and pData up to dwDataSize bytes, as needed...

      Inc(dwIndex);
    until False;
  finally
    // only if GetCurrentPrinterHandle returns a handle that needs to be closed now...
    ClosePrinter(hPrinter);
  end;
end;



回答2:


Thanks for your great great help! But have more questions, need your help. (sorry, I'm not good at English)

Q1. in your answer : SetLength(sValueName, PWideChar(pValueName), (dwValueNameSize div SizeOf(WideChar)) - 1); // -1 for null terminator

I dont understnt this SetLength format.....and complier raise an Error :
[DCC Error] Unit1.pas(111): E2008 Incompatible types

Q2. how to get value : sValueName ----> ValueName : array of Byte, how to get string value form an array of Byte

sorry for my poor ability. I really do not get pointer type Data, need more study



来源:https://stackoverflow.com/questions/62286424/how-to-use-api-winspool-enumprinterdata-in-delphi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!