私はこの問題にほぼ1週間苦労しています。ファイルを開くサービスとして実行されている vb6 アプリケーションが必要です。ファイルに対して何もする必要はありません。開くだけで済みます。ShellExecute と ShellExecuteEx を使用するだけでなく、CreateProcess を使用してコマンドラインからファイルを起動しようとしました。これらの実装のいずれも機能しなかった場合、代わりに別のアプリケーションを (CreateProcess を使用して) 起動して、ファイルを開き、それ自体を閉じるという唯一のタスクを試みました。
これらのソリューションはすべて、アプリケーションが正常に実行されている場合は機能しますが、サービスとして実行されている場合は機能しません。アプリケーションがサービスとして実行されている間、直接的または間接的にファイルを開くことができることは非常に重要です。それをトリガーできる必要があるだけです。
Windows Vista 以降、サービスがデスクトップと対話する機能を Windows がロックダウンしていることは理解していますが、サービスからファイルを開くコマンドをトリガーする方法が必要であると確信しています。私が開発したアプリは、CreateProcess を使用してコマンド ラインから pg_dump.exe (postgres データベースのバックアップ実行可能ファイル) を実行し、サービスとして実行しながらデータベース ファイルをバックアップすることができます。そのため、サービスからexeを起動してファイルを間接的に開くとうまくいくかもしれません。ただし、何らかの理由で、アプリケーションは pg_dump.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
サービスからexeを実行し、データベースバックアップファイルを作成するのに成功した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))
問題のファイルを開こうとするセカンダリ 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を修正する方法を誰かが知っていれば、助けていただければ幸いです! サービスからファイルを開く別の方法を知っている人がいれば、それもありがたいです。