【发布时间】:2015-01-10 21:29:16
【问题描述】:
我已经为这个问题苦苦挣扎了将近一个星期。我需要一个作为服务运行的 vb6 应用程序来打开文件。我不需要对文件做任何事情,我只需要打开它。我尝试使用 ShellExecute 和 ShellExecuteEx 以及使用 CreateProcess 尝试从命令行启动文件。当这些实现都不起作用时,我尝试启动另一个应用程序(使用 CreateProcess),其唯一任务是打开文件然后关闭自身。
这些解决方案在应用程序正常运行时都可以工作,但在作为服务运行时则不行。应用程序能够在作为服务运行时直接或间接打开文件非常重要,它只需要能够触发它即可。
我了解自 Windows Vista 以来 Windows 已锁定服务与桌面交互的能力,但我确信必须有一种方法可以从服务触发文件打开命令。我开发的应用程序能够使用 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 直接从服务打开文件,但没有成功。 (我在辅助 exe (GDNPOpener.exe) 中使用 ShellExecuteEx 打开文件)
如果有人知道如何修复我的 exe 以便我的服务能够运行它,我将非常感谢您的帮助!如果有人知道从服务中打开文件的任何其他方法,那也将不胜感激,谢谢!
【问题讨论】:
-
如果我理解正确,
GNDPOpener.exe是您自己的代码,服务也是如此。为什么它们是单独的应用程序?为什么不直接把GNDPOpener.exe的代码放到服务里面呢? -
因为服务不想直接打开文件。所以我想如果我让服务启动另一个应用程序,也许该应用程序将能够打开文件,因为它不是作为服务运行并且不会受到相同的限制。但是,该服务不仅无法打开文件,而且也无法启动辅助应用程序(这很奇怪,因为正如我在原始问题中所说,它似乎能够很好地启动 pg_dump.exe)
-
定义“打开文件”,因为我认为你的意思与真正的意思完全不同。我的猜测是您正在尝试运行一些其他程序,该程序执行诸如读取文件并将其显示在另一个会话(可能是会话 1)中的某个用户桌面上的操作,而您不能这样做。否则,如果您真的是 open,那么您就有文件安全问题了。
-
当一个服务不能做普通应用程序可以做的事情时,这是因为它是在服务上下文中运行的,而不是因为服务可执行文件或服务进程本身有什么特别之处。启动另一个应用程序将无济于事,因为该应用程序也会在服务上下文中运行。所以你的
GNDPOpener.exe没有意义,它不能做任何服务不能做的事情。 (不过我不知道为什么它不会运行。我从未尝试在服务上下文中运行 VB6 应用程序。) -
至于您的根本问题,您可能需要与相关软件的供应商(Hotdocs?)进行讨论。一般来说,一个软件越复杂,它在服务环境中成功运行的可能性就越小,除非它是专门设计的。
标签: vb6 windows-services shellexecute createprocess shellexecuteex