-1

In Windows 7, the following Excel VBA 7.1 snippet successfully launches the On-Screen Keyboard (OSK.EXE) but the value of the dwProcessID member retrieved from the 'proc' (process information) parameter (passed ByRef) does not match that, or any other PID, displayed by task manager.

Type PROCESS_INFORMATION
     hProcess As Long
     hThread As Long
     dwProcessID As Long ' Integer doesn't work either
     dwThreadID As Long 
End Type

Declare Function CreateProcessA Lib "kernel32" (ByVal _
    lpApplicationName As Long, 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 Long, _
    ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As _
    PROCESS_INFORMATION) As Long

Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO

start.cb = Len(start)

If CreateProcessA(0, "OSK.EXE", 0, 0, 1, NORMAL_PRIORITY_CLASS, 0, 0, start, 
proc) <> 0 Then
   WaitForInputIdle proc.hProcess, INFINITE
   MsgBox CStr(proc.dwProcessID), vbInformation, "Process ID" ' Wrong for 
OSK, but correct for Notepad and Calc
   CloseHandle (proc.hProcess)
   CloseHandle (proc.hThread)
End If

For OSK, it seems that the proc.hProcess value is incorrect. I checked the process ID value of proc.dwProcessID against the PID listed for OSK in Task Manager, and they don't match. Indeed, proc.dwProcessID isn't listed for any process (even in Process Explorer), so it seems that the PROCESS_INFORMATION Type is not receiving correct outputs.

Everything works fine for NOTEPAD and CALC though. Equivilent code compiled in VB.NET behaves properly with OSK, so what's different about VBA that causes CreateProcessA to work incorrectly with OSK?

Thanks in advance, John.

JAH72
  • 7
  • 1

2 Answers2

1

It could be that the executable you are launching (OSK.EXE) execute another process or does some job and exit very quickly so when you look in process explorer you cannot find anything. If the code inside the "if" is not executed I would try to get the error with GetLastError call.

Frediano Ziglio
  • 310
  • 1
  • 6
  • Thanks for your suggestions. The code inside the 'if' statement is executed and OSK remains running as required, but CreateProcess yields a handle for OSK that is different to that shown in Task Manager. No errors are flagged. The same code behaves properly if compiled in VB.NET, so the issue seems to relate to something that's different in the way VBA runs. – JAH72 Dec 07 '18 at 13:52
1

I think you are encountering issues like https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/64-bit-visual-basic-for-applications-overview. Long is not a good replacement for pointers, in this case should be

Type PROCESS_INFORMATION hProcess As LongPtr hThread As LongPtr dwProcessID As Long dwThreadID As Long End Type

Declare Function CreateProcessA Lib "kernel32" (ByVal _ lpApplicationName As LongPtr, ByVal lpCommandLine As String, ByVal _ lpProcessAttributes As LongPtr, ByVal lpThreadAttributes As LongPtr, _ ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ ByVal lpEnvironment As LongPtr, ByVal lpCurrentDirectory As LongPtr, _ ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As _ PROCESS_INFORMATION) As Long

See also https://www.jkp-ads.com/articles/apideclarations.asp

Frediano Ziglio
  • 310
  • 1
  • 6