powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Windows [игнор отключен] [закрыт для гостей] / Печать на принтер из под SYSTEM. Как сделать чтоб приложение видело/печатало?
2 сообщений из 2, страница 1 из 1
Печать на принтер из под SYSTEM. Как сделать чтоб приложение видело/печатало?
    #38636108
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не знаю даже в какую тему писать, но вроде здесь люди самые эрудированные, в VB6 это точно без ответа останется.

Попробую по порядку. Например я хочу распечатать некий документ (неважно что jpg,txt,)
Немного теории.
Используется метод printto - неточно, зависит от реестра но наиболее универсально.

Примеры печати из приложения:

1. Запуск ShellExecute ("printto")
Код: vbnet
1.
2.
3.
4.
  ShellExecute 0, "printto", _
   Chr(34) & App.Path & "\test.jpg" & Chr(34), _
   Chr(34) & "PrinterName" & Chr(34), _
   "", SW_SHOWNORMAL



2. Зная стандартное приложение и подглядев ключи "printto" в реестре, можно обезопасить себя от случайного отсутствия ключа в реестре

Т.е. например для jpg,tif, bmp, png и т.п. графики стандартный метод такой:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
'графика
'rundll32.exe C:\WINDOWS\system32\shimgvw.dll,ImageView_PrintTo /pt "%1" "%2"<<< "%3" "%4"
'txt
'%SystemRoot%\system32\notepad.exe /pt "%1" "%2" "%3" "%4"
  ShellExecute 0, "", "rundll32.exe", _
   "shimgvw.dll,ImageView_PrintTo /pt " & _
   Chr(34) & App.Path & "\test.jpg" & Chr(34) & " " & _
   Chr(34) & "PrinterName" & Chr(34), _
   "", SW_HIDE



2A. А если совсем культурно, нашаманив согласно статье СВЕДЕНИЯ: интерфейс программ Windows Rundll и Rundll32 , то прямым вызовом API:
Код: vbnet
1.
2.
3.
4.
Public Declare Function ImageView_PrintTo Lib "shimgvw.dll" Alias "ImageView_PrintToA" _
 (ByVal hwnd As Long, ByVal hinst As Long, ByVal lpszCmdLine As String, ByVal nCmdShow As Long) As Long

  ImageView_PrintTo  0, 0, "/pt " & Chr(34) & App.Path & "\test.jpg" & " " & Chr(34) & "PrinterName" & Chr(34), 0



3. Именно "printto" используется например при добавлении задания в MS Fax
FaxDocument.ConnectedSubmit method
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub Main()
  Dim g_objFaxServer As New FAXCOMEXLib.FaxServer
  g_objFaxServer.Connect ("")
  Dim objFaxDocument As New FAXCOMEXLib.FaxDocument
  'We can create outgoing job from any printable file format, no dialog boxes
  objFaxDocument.Body = App.Path & "\test.jpg"
  objFaxDocument.Recipients.Add "74951234567", "74951234567"
  'Submit the document to the connected fax server
  objFaxDocument.ConnectedSubmit g_objFaxServer
End Sub


Здесь файл произвольного формата (jpg) передается методу ConnectedSubmit, который осуществляет печать jpg через "printto", как я расписал выше на принтер "Fax".
==========================================
Теперь о проблеме.
1. Обнаружил на Win 8.1 x64 при запуске процедуры objFaxDocument.ConnectedSubmit под Local SYSTEM (режим AsService).
Дебаг показал что objFaxDocument.ConnectedSubmit намертво завис без всяких ошибок и код "застрял" (печать файла типа jpg).
2. В то же время я обнаружил, что "печать txt" (printto+notepad) проходит тем же кодом абсолютно нормально. Т.е. txt печатается и факс-задание добавляется (под System!!!)
3. Я начал рыться в ключах реестра, пытаться менять дефолтные приложения для jpg (shimgvw -стандартный просмотрщик, mspaint), сделал тестовое приложение. Ничего не помогает. Под юзером все OK, под SYSTEM -Ж.
Причем Ж и при прямом вызове
shimgvw.dll,ImageView_PrintTo /pt "%1" "%2"
А это тонкий намек на то что Extension-Associations не зависят от аккаунта.
!!! при этом печать txt через блокнот всегда работает.
4. Я даже скачал утилитку Русиновича и научился запускать тест-прогу под System:
psexec -s -i -d cmd.exe
Далее из cmd запускаем любой exe и смотрим чего происходит.
5. Далее я начитался топиков на форумах и там был дан совет кому-то в такой ситуации.
Запустить
psexec -s -i -d notepad.exe (под System)
, потом Печать,
и посмотреть все ли принтеры на месте.
Я проверил, на месте. И печатают. Но с notepad и в автомате проблем нет.
6. И все-таки мне удалось высечь.
Я запустил
psexec -s -i -d myproga.exe (под System)
В myproga.exe у меня GUI и есть команды печати.
Так вот, она вообще не видит ни одного принтера.
Более того, из myproga.exe я вывел картинку через стандартный просмотрщик
rundll32 shimgvw.dll,ImageView_Fullscreen test.pict
И фотовьюер при попытке нажать в нем Print заявил буквально следующее:
Windows Photo Viewer can't print this picture because there is no
printer installed or a service Windows needs is not running.

Исходя из всего сказанного, выводы такие:
1. Часть приложений при запуске из-под System видят принтеры и способны печатать (например блокнот).
2. Другие приложения по какой-то причине не видят принтеры и отсюда проблемы.

Как лечить свое приложение чтоб оно видело принтеры?


Я конечно попытался добавить права для SYSTEM для принтера, но думаю это не то и не помогло.

'---
Я когда-то уже решал подобную похожую проблему. Хитро запущенное приложение не видело базу данных под x64.

Непонятки при доступе к объектам БД при запуске приложения VB6 "из под принтера".
ПРИЧИНАWhen exporting, RMS needs and looks for oledb32.dll, by default this is located in: C:\Program Files (x86)\Common Files\System\Ole DB\. However the location could be different from the default and when RMS searches for the dll it uses the system variable %CommonProgramFiles(x86)% to find this location.

There is a known issue in Windows Vista X64 and Windows 2008 X64 that when the CreateEnvironmentBlock function is called without inheriting environment variables from the current process, the returned environment block is missing the following environment variables: CommonProgramFiles(x86), CommonProgramW6432, ProgramFiles(x86), ProgramW6432.

This causes RMS to fail to find oledb32.dll and the export fails.

Решение
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Public Sub Fix_x64_Environment()
  If Is64bit Then
    Dim buf As String * 256
    Dim varValue As String
    Dim length As Long

    ' Get "CommonProgramFiles(x86)" Environment Variable.
    length = GetEnvironmentVariable("CommonProgramFiles(x86)", buf, Len(buf))
    varValue = Left$(buf, length)
    If Len(varValue) = 0 Then
      ' Set "CommonProgramFiles(x86)" Environment Variable.
      SetEnvironmentVariable "CommonProgramFiles(x86)", GetCommonProgramFilesX86Path
    End If
  End If
End Sub



И у меня ощущение, что под System проги также теряют какую-то Environment Variable и не видят принтеров.
И ее надо "восстанавливать" ручками. Notepad -то видит!!!
Есть идеи?
...
Рейтинг: 0 / 0
Печать на принтер из под SYSTEM. Как сделать чтоб приложение видело/печатало?
    #38636133
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, в принципе нашел решение:

registration required. Printing from windows service on windows 8 fails

решениеAt http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/ we see that this was reported to Microsoft and confirmed as a bug in Windows 8 and Windows Server 2012.

This bug is triggered when trying to print from a 32bit process in non-standard user session (like e.g. a service).

According to Microsoft, this a bug was resolved in Windows 8.1 and Windows Server 2012 R2. However, we could still reproduce it on Windows 8.1.

On the same site, a workaround is given by Microsoft. This workaround solved the problem for us on Windows 8.1. It probably also works on Windows 8 and Windows Server 2012.

The workaround goes as follows:

1.Open Regedit and go to HKEY_CLASSES_ROOT\CLSID{BA7C0D29-81CA-4901-B450-634E20BB8C34}

2.Check the value of the "AppID" Registry Entry. In our case this was {AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}

3.Now go to HKEY_CLASSES_ROOT\AppID{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0} (or the respective value you found on your system)
4.Under this registry key, delete the entries with the name "AccessPermission", "LaunchPermission" and "RunAs"
Since this is a bug in Windows, you cannot fix it in your code. The workaround might have side effects, but we haven't seen any so far in our scenario.
Оно решает задачу видимости принтеров под System и частчно с objFaxDocument.ConnectedSubmit - частично, потому что "printto" под System почему-то не работает (видимо это независимый баг). A shimgvw.dll,ImageView_PrintTo /pt "%1" "%2" хоть и стало работать, но его в лоб в метод не засунешь, подсовывается TIFF сконвертированный из JPG напрямую например (я всегда делаю tiff если printto дает ошибку), ConnectedSubmit его как-то выправляет, по крайне мере этот TIFF перестал стопорить метод.

Но, блин, грохать ключи в реестре... последнее дело. Тем более программно это еще надо думать как. Там ведь с TrustedInstaller надо владельца снимать и назначать Administrators, потом права себе давать, потом удалять параметры. Потом по хорошему TrustedInstaller назад восстанавливать. И еще абсолютно неясно что там удаляется и за что оно отвечает.
Хорошо б на уровне программы как-то фиксить, Notepad же фиксит для себя.

Модератор: Тема перенесена из форума "C++".
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / Windows [игнор отключен] [закрыт для гостей] / Печать на принтер из под SYSTEM. Как сделать чтоб приложение видело/печатало?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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