Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение информации _PRINTER_INFO_5 о принтере / 19 сообщений из 19, страница 1 из 1
23.08.2017, 11:23:07
    #39509187
Dagmanor
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Здравствуйте.
Понадобилось разделить принтеры в системе по принципу локальный/сетевой. пробую делать так:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
var
  i: Integer;
  p: P_PRINTER_INFO_5;
  ABytesNeeded: DWord;
  PH:THandle;
begin
  ListBox1.Items.Clear;
  ListBox2.Items.Clear;
  for i := 0 to Printer.Printers.Count - 1 do
  begin

    ph:=0;
    OpenPrinter(PWideChar(Printer.Printers[I]),PH,nil);
    if PH<>0 then
    begin
      GetPrinter(PH, 5, nil, 0, @ABytesNeeded);
      GetMem(p,ABytesNeeded);
      GetPrinter(PH, 5, p, ABytesNeeded, @ABytesNeeded);
      if getlasterror <> 0 then
        raiselastoserror;

      if ((p^.Attributes and PRINTER_ATTRIBUTE_LOCAL) <> 0) then
      begin
          //если он локальный
        ListBox1.Items.add(p^.pPrinterName+' | '+ p^.pPortName);
      end
      else
        ListBox2.Items.add(p^.pPrinterName+' | '+ p^.pPortName);

      FreeMem(p);
    end;
    ClosePrinter(ph);
  end;
end;


( P_PRINTER_INFO_5 = ^_PRINTER_INFO_5; )


Но постоянно получаю ошибку:
"System Error. Code: 122.
Область данных, переданная по системному вызову, слишком мала."

Подскажите, пожалуйста, что делаю не так?
...
Рейтинг: 0 / 0
23.08.2017, 11:46:58
    #39509200
Mr.Pavel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Попробуйте вместо GetMem\FreeMem использовать GlobalAllocPtr\GlobalFreePtr
...
Рейтинг: 0 / 0
23.08.2017, 11:58:19
    #39509207
Dagmanor
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
решил проблему выделением заведомо достаточного количества памяти:

Код: pascal
1.
2.
      GetMem(p,10240);
      GetPrinter(PH, 5, p, 10240, @ABytesNeeded);



Спасибо большое за ответы.
...
Рейтинг: 0 / 0
23.08.2017, 12:03:20
    #39509213
Mr.Pavel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
там проблема скорее всего в memory alignment
...
Рейтинг: 0 / 0
23.08.2017, 12:30:20
    #39509234
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Dagmanor,

А зачем так сложно?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var 
  ...
  p: _PRINTER_INFO_5;
  ABytesNeeded: DWord;
  ...
begin
  ...
      GetPrinter(PH, 5, @p, SizeOf(p), @ABytesNeeded);
      if getlasterror <> 0 then
  ...
end;


Не вариант?
...
Рейтинг: 0 / 0
23.08.2017, 12:33:23
    #39509237
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
alekcvp,
Хотя, блин, там строки же...
...
Рейтинг: 0 / 0
23.08.2017, 12:33:38
    #39509238
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Dagmanor
Код: pascal
1.
      GetPrinter(PH, 5, nil, 0, @ABytesNeeded);



приведи декларацию функции GetPrinter
Их может быть несколько, тогда надо будет проверить, какая конкретно используется

меня смущает последний параметр весьма


Dagmanor
Код: pascal
1.
PWideChar(Printer.Printers[I]



Здесь надёжнее PChar


Dagmanor
Код: pascal
1.
2.
      if getlasterror <> 0 then
        raiselastoserror;



Правильнее
Код: sql
1.
 CheckWin32Error( GetPrinter(PH, 5, p, ABytesNeeded, @ABytesNeeded) );
...
Рейтинг: 0 / 0
23.08.2017, 12:35:46
    #39509240
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
alekcvp,

там все проще, издержки копипаста

он ДВА РАЗА вызывает функцию GetPrinter и НИ ОДНОГО РАЗА не проверяет е результат

ПЕРВАЯ вызов функции выставляет ошибку ( SetLastError ), но он её сразу не проверяет

а вот после ВТОРОГО вызова он ее проверяет и выбрасывает исключение

но это была ошибка ПЕРВОГО вызова, а не ВТОРОГО
...
Рейтинг: 0 / 0
23.08.2017, 12:39:31
    #39509244
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
DagmanorПонадобилось разделить принтеры в системе по принципу локальный/сетевой

в принципе ещё можно WMI использовать, но будет медленно и через брандммауэр

хато единообразно для любого жеоеза и декларативно, псевдо-SQL
...
Рейтинг: 0 / 0
23.08.2017, 12:44:29
    #39509250
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
alekcvp
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var 
  ...
  p: _PRINTER_INFO_5;
  ABytesNeeded: DWord;
  ...
begin
  ...
      GetPrinter(PH, 5, @p, SizeOf(p), @ABytesNeeded);
      if getlasterror <> 0 then
  ...
end;


Не вариант?

опасно

в другой версии Windows структуру _PRINTER_INFO_5 вдруг как расширят, размер увеличат - и скомпилированная 5 лет назад программа начнёт выдавать ошибку
...
Рейтинг: 0 / 0
23.08.2017, 13:17:47
    #39509278
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Ariochопасно

в другой версии Windows структуру _PRINTER_INFO_5 вдруг как расширят, размер увеличат - и скомпилированная 5 лет назад программа начнёт выдавать ошибку
Нет, проблема в том что структура содержит строки, а такие структуры, AFAIR, винда возвращает прикрепляя данные в её "хвост". Т.е. SizeOf(p) вернёт нам размер структуры без учета памяти под строки . Поэтому необходимо сначала получать размер и после выделять память, т.к. в этот размер входит не только размер структуры но и размер всех строк.
...
Рейтинг: 0 / 0
23.08.2017, 13:28:06
    #39509286
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Ariochв другой версии Windows структуру _PRINTER_INFO_5 вдруг как расширят, размер увеличат - и скомпилированная 5 лет назад программа начнёт выдавать ошибку

Это фантастика.
...
Рейтинг: 0 / 0
23.08.2017, 13:45:47
    #39509315
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
schi,

в Windows очень много структур, в которых первое поле - это "размер структуры"

это типовой сценарий

именно потому что за десятилетия жизни Windows эти структуры развивались и их размер увеличивался, и поле "размер вот этой самой структуры" тем самым обеспечивает и версионность самой структуры и совместиость старых програм с новыми структурами в новых Windows
...
Рейтинг: 0 / 0
23.08.2017, 14:21:03
    #39509353
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Ariochэто типовой сценарий

В данном конкретном случае проще сделать _PRINTER_INFO_11, чем ломать совместимость.
...
Рейтинг: 0 / 0
23.08.2017, 14:40:36
    #39509376
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Ariochschi,

в Windows очень много структур, в которых первое поле - это "размер структуры"

это типовой сценарий

именно потому что за десятилетия жизни Windows эти структуры развивались и их размер увеличивался, и поле "размер вот этой самой структуры" тем самым обеспечивает и версионность самой структуры и совместиость старых програм с новыми структурами в новых Windows

Код: pascal
1.
2.
3.
4.
5.
6.
7.
  _PRINTER_INFO_5W = record
    pPrinterName: PWideChar;
    pPortName: PWideChar;
    Attributes: DWORD;
    DeviceNotSelectedTimeout: DWORD;
    TransmissionRetryTimeout: DWORD;
  end;



Ты тут где-то видишь размер структуры в первом поле ?
...
Рейтинг: 0 / 0
23.08.2017, 16:05:07
    #39509432
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
schi,

конкретно тут - нет.

кстати record без указания выравнивания, без спецификатора packed....

изменится компилятор - и может поехать структура.

или например переход с Win32 API и Delphi ANSI->UTF16
или Win32 -> Win64

в общем, если есть возможность у Windows динамически запросить "сколько тебе памяти надо" - то это и нужно делать, а не хардкодить sizeof или вообще магические константы
...
Рейтинг: 0 / 0
23.08.2017, 16:10:46
    #39509436
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
AriochDelphi ANSI->UTF16Для этой структуры размер не изменится
...
Рейтинг: 0 / 0
23.08.2017, 16:26:16
    #39509441
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
_Vasilisk_Для этой структуры

вот вот, для ЭТОЙ

чем проверять каждую структуру с риском забыть или ошибиться, лучше использовать один общий принцип

-----------

ну а вообще, это оффтопик зверский.

Повторяю, исходная ошибка исходного автора в том, что он:

1) не проверяет результаты работы функций (возвращаемое значение)

2) ошибку от первой функции переводит в исключение не сразу, а только после вызова второй функции, чем запутал и себя и нас :-)
...
Рейтинг: 0 / 0
23.08.2017, 16:54:04
    #39509453
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение информации _PRINTER_INFO_5 о принтере
Ariochschi,

конкретно тут - нет.

кстати record без указания выравнивания, без спецификатора packed....

изменится компилятор - и может поехать структура.


Никуда она не поедет :)
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение информации _PRINTER_INFO_5 о принтере / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]