Я уже почти неделю боюсь этой проблемы. Мне нужно приложение vb6, которое запускается как служба для открытия файла. Мне не нужно ничего делать с файлом, мне просто нужно его открыть. Я попытался использовать ShellExecute и ShellExecuteEx, а также использовать CreateProcess, чтобы попытаться запустить файл из командной строки. Когда ни одна из этих реализаций не работала, я попытался вместо этого запустить другое приложение (используя CreateProcess) с единственной задачей открыть файл и затем закрыть его.VB6 - Как открыть файл из приложения, выполняемого как служба?
Эти решения все работают, когда приложение запускается нормально, но не когда оно запускается как служба. Крайне важно, чтобы приложение могло открывать файл во время работы в качестве службы, прямо или косвенно, просто должно быть способно вызвать его.
Я понимаю, что Windows заблокировала способность служб взаимодействовать с рабочим столом с Windows Vista, но я уверен, что должен быть способ запуска команды открытия файла из службы. Приложение, которое я разработал, может запустить pg_dump.exe (исполняемый файл резервной копии для баз данных postgres) из командной строки с помощью CreateProcess для резервного копирования файлов базы данных во время работы в качестве службы. Вот почему я, хотя запуск exe из службы для косвенного открытия файла, может работать. Однако по какой-то причине приложение запускает pg_dump.exe отлично, но не запускает исполняемый файл, который я создал. Мне интересно, будет ли exe, созданный мной, иметь какое-то присутствие на рабочем столе, и поэтому служба не хочет его запускать. Я изменил свойства основной формы во вторичном exe, чтобы форма не была видимой и не отображалась на панели задач, но что-то говорит мне, что этого недостаточно.
Вот мой CreateProcess код (я не пишу большую часть этого поэтому, пожалуйста, простите мое невежество):
Private Declare Function WaitForSingleObject Lib "KERNEL32" (ByVal _
hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "KERNEL32" _
(ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "KERNEL32" _
(ByVal hProcess As Long, lpExitCode As Long) As Long
'create a new win process.
Private Declare Function CreateProcessA Lib "KERNEL32" (ByVal _
lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
lpStartupInfo As STARTUPINFO, lpProcessInformation As _
PROCESS_INFORMATION) As Long
'used by CreateProcess
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadID As Long
End Type
Const NORMAL_PRIORITY_CLASS = &H20&
Const INFINITE = -1&
Public Function ExecSynchronousCmd(cmdline As String) As Long
' - Used to force a shelled command to run synchronously (code will
' suspend where this function is called until shelled process
' returns a return value)
' - There is no time out - it will wait forever!!
' - Function returns exit value for shelled process
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim ret As Long
'Initialize the STARTUPINFO structure:
start.cb = Len(start)
'Start the shelled application:
ret = CreateProcessA(vbNullString, cmdline$, 0&, 0&, 1&, _
NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
'Wait for the shelled application to finish:
ret = WaitForSingleObject(proc.hProcess, INFINITE)
Call GetExitCodeProcess(proc.hProcess, ret&)
Call CloseHandle(proc.hThread)
Call CloseHandle(proc.hProcess)
ExecSynchronousCmd = ret
End Function
Вот реализация для запуска pg_dump.exe, которая успешна при запуске ехе С обслуживания и создания резервных копий баз данных файлов:
i = ExecSynchronousCmd(Chr$(34) & "C:\Program Files (x86)\PostgreSQL\9.3\bin\pg_dump.exe" & Chr$(34) & _
" -Ft " & _
" -f " & Chr$(34) & tempName & Chr$(34) & _
" -U " & s1 & _
" -h " & s3 & _
" -p " & s4 & _
" " & sDB(0, x))
Вот такая же реализация, которая пытается запустить вторичный ехе, который попытается открыть файл в вопрос:
i = ExecSynchronousCmd(Chr$(34) & "C:\Program Files (x86)\GranDocsNP\GDNPOpener.exe" & Chr$(34))
Приведенный выше код не работает, когда приложение запускается как служба. Почему pg_dump.exe успешно работает, но мой собственный GDNPOpener.exe не работает?
Как я уже говорил выше, я также попытался использовать ShellExecute и ShellExecuteEx, чтобы открыть файл непосредственно из службы, которая не сработала. (Я использую ShellExecuteEx во вторичном exe (GDNPOpener.exe), чтобы открыть файл)
Если кто-нибудь знает, как исправить мой exe, чтобы мой сервис запустил его, я был бы очень благодарен за помощь! Если кто-нибудь знает какие-либо альтернативные способы открыть файл из службы, это тоже будет оценено, спасибо!
Если я правильно понимаю, 'GNDPOpener.exe' - это ваш собственный код, как и сервис. Почему они являются отдельными приложениями? Почему бы вам просто не поместить код из «GNDPOpener.exe» непосредственно в службу? –
Поскольку служба не хочет открывать файл напрямую. Поэтому я решил, что если я заставлю службу запустить другое приложение, возможно, это приложение сможет открыть файл, поскольку он НЕ работает как служба и не будет подвергаться тем же ограничениям. Тем не менее, не только служба не может открыть файл, но также не может запустить вторичное приложение (что странно, потому что, как я сказал в моем первоначальном вопросе, он, похоже, способен запустить pg_dump.exe fine) – user2437443
Определить " откройте файл ", потому что я думаю, вы имеете в виду нечто совершенно иное, чем это действительно означает. Я предполагаю, что вы пытаетесь запустить какую-либо другую программу, которая делает что-то вроде чтения файла и отображает его на каком-то рабочем столе пользователя в другом сеансе (возможно, в сеансе 1), и этого вы не можете сделать. В противном случае, если вы действительно имеете в виду * open *, у вас проблема с файловой безопасностью. – Bob77