Create process with 16 bit apps

Posted on 1998-04-30
Medium Priority
Last Modified: 2012-08-14
I am using the createprocess API along with WaitforSingle Object the 16 bit app starts but goes nowhere.  If I kill the VB5 app that calls it the 16 bit app finishes.  It seems to be hanging at the Waitforsingleobject API is there something i can do to make this process continue.  This works fine on a NT machine the problem seems to only occur on win95 machines.

      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

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

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private 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, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const INFINITE = -1&

Public Sub ExecCmd(cmdline$)
      Dim Start As STARTUPINFO
      ' Initialize the STARTUPINFO structure:
      Start.cb = Len(Start)
      ' Start the shelled application:
      ret& = CreateProcess(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, Start, Proc)
      ' Wait for the shelled application to finish:
      ret& = WaitForSingleObject(Proc.hProcess, INFINITE)
      ret& = CloseHandle(Proc.hProcess)

End Sub
Question by:sye
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Expert Comment

ID: 1435123
There is a similar question in the locked question area.
If thtat works, you can delete the question and save you some points.

Author Comment

ID: 1435124
This is similar to the othe rquestion I tried it with the same results the 16 bit app starts and waits for the VB5 app to be killed before it will proceed any further or be killed itself.


Accepted Solution

juliocoelho earned 400 total points
ID: 1435125
I have faced the same problem in an application for a client of mine.
The problem occurs when you run a DOS application, because WIN 95 doesn't close the DOS Window automatically like NT does. You can solve it in the following ways:
    1. using a .pif file to run the application, you only need to say in the .pif that the window is going to be closed automatically;
    2. The other way is to use the following:
        2.1. Transform the sub into a function to return if the application was runned with sucess;
        2.2. then use the following:
            // try Win95 way
            if not ExecCmd("command /c dir") then
                // if that fails try Win NT way
                if not ExecCmd("command /c dir") then
                    msgbox "the application didn't run"
                end if
            end if

You only have to substitute the dir command by your application name, the command /c indicates to Win95 to open a Dos session and close it after the command is finished.

I hope that this solve your problem.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 1435126
I tried calling the 16 bit ap with the command /c "app" nothing seemed to happen the called app did not start.  We need it to start allow the user to manipulate some things then close it and have the vb5 app pick up where it stopped.  The 16 bit app starts it just hangs (the logo for the app is not even displayed) then if i close the vb app from the task list the app continues as i want it to.

Expert Comment

ID: 1435127
I see!

You don't want the the caller application to freeze, for that I think it's better for you to use the following function.
If you look into the function you can see that I'm using a loop to see if the DOS Window begins with the caption FINISHED, you put the code you need in there, like a DoEvents so that you application dont frezes

Option Explicit

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId 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
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long

Private Const STILL_ACTIVE = &H103
Private Const SYNCHRONIZE = &H100000

Public Const WAIT_FAILED = -1&        'Error on call
Public Const WAIT_OBJECT_0 = 0        'Normal completion
Public Const WAIT_ABANDONED = &H80&   '
Public Const WAIT_TIMEOUT = &H102&    'Timeout period elapsed
Public Const IGNORE = 0               'Ignore signal
Public Const INFINITE = -1&           'Infinite timeout

Public Const SW_HIDE = 0
Public Const SW_SHOWNORMAL = 1
Public Const SW_SHOW = 5
Public Const SW_MINIMIZE = 6
Public Const SW_SHOWNA = 8
Public Const SW_RESTORE = 9

Private Const WM_CLOSE = &H10
Private Const GW_HWNDNEXT = 2
Private Const GW_OWNER = 4

Public Function ShellAndClose(ByVal JobToDo As String, Optional ExecMode) As Long
   ' Shells a new process and waits for it to complete.
   ' Calling application is responsive while new process
   ' executes. It will react to new events, though execution
   ' of the current thread will not continue.
   ' Will close a DOS box when Win95 doesn't. More overhead
   ' than ShellAndLoop but useful when needed.
   Dim ProcessID As Long
   Dim PID As Long
   Dim hProcess As Long
   Dim hWndJob As Long
   Dim nRet As Long
   Dim TitleTmp As String

   If IsMissing(ExecMode) Then
      ExecMode = vbMinimizedNoFocus
      If ExecMode < vbHide Or ExecMode > vbMinimizedNoFocus Then
         ExecMode = vbMinimizedNoFocus
      End If
   End If

   On Error Resume Next
      ProcessID = Shell(JobToDo, CLng(ExecMode))
      If Err Then
         ShellAndClose = vbObjectError + Err.Number
         Exit Function
      End If
   On Error GoTo 0

   hWndJob = FindWindow(vbNullString, vbNullString)
   Do Until hWndJob = 0
      If GetParent(hWndJob) = 0 Then
         Call GetWindowThreadProcessId(hWndJob, PID)
         If PID = ProcessID Then Exit Do
      End If
      hWndJob = GetWindow(hWndJob, GW_HWNDNEXT)

   hProcess = OpenProcess(fdwAccess, False, ProcessID)
      TitleTmp = Space(256)
      nRet = GetWindowText(hWndJob, TitleTmp, Len(TitleTmp))
      If nRet Then
         TitleTmp = UCase(Left(TitleTmp, nRet))
         If InStr(TitleTmp, "FINISHED") = 1 Then
            Call SendMessage(hWndJob, WM_CLOSE, 0, 0)
         End If
      End If

      GetExitCodeProcess hProcess, nRet
      Sleep 100
   Loop While nRet = STILL_ACTIVE
   Call CloseHandle(hProcess)

   ShellAndClose = nRet
End Function

LVL 13

Expert Comment

ID: 1435128
Bought This Question.

Expert Comment

ID: 1435129
Sorry, but I didn't understand what you said?

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses
Course of the Month10 days, 14 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question