我一直在爲這個問題奮鬥了近一個星期。我需要一個作爲服務運行來打開文件的vb6應用程序。我不需要對文件做任何事情,我只需要打開它。我嘗試使用ShellExecute和ShellExecuteEx以及使用CreateProcess嘗試從命令行啓動文件。當這些實現都沒有工作時,我嘗試啓動另一個應用程序(使用CreateProcess),只打開文件然後關閉自己。VB6 - 如何從作爲服務運行的應用程序打開文件
這些解決方案在應用程序正常運行時都可以工作,但當它作爲服務運行時,這些解決方案都不工作。應用程序能夠在作爲服務運行時直接或間接地打開文件,這非常重要,只需要能夠觸發它即可。
據我所知,Windows已經鎖定了自Windows Vista以來服務與桌面交互的能力,但我確定必須有一種方法來從服務中觸發文件打開命令。我開發的應用程序能夠通過CreateProcess的命令行運行pg_dump.exe(postgres數據庫的備份可執行文件),以便在作爲服務運行時備份數據庫文件。這就是爲什麼我從服務啓動一個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這是成功的運行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))
下面是一個類似的實現它試圖運行的exe二次將試圖在問題打開文件:
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) – user2437443
定義「打開一個文件「,因爲我認爲你的意思與真正含義完全不同。我的猜測是,你正在嘗試運行一些其他程序,如讀取文件並將其顯示在另一個會話(可能是會話1)中的某個用戶桌面上,而你不能這樣做。否則,如果您真的認爲* open *,那麼您遇到了文件安全問題。 – Bob77