We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

ShellExecute and Wait for response

Chizl
Chizl asked
on
Medium Priority
693 Views
Last Modified: 2012-05-04
The steps that I am taking are the following:

1. Execute something using the Shell command under vbHide, which returns a program's task id.

2. Wish to monitor the task id and not continue until that task id has completed.

I want to us the appropriate API calls in a while loop.

Keep in mind I know the command line to MAP a drive.

I'm sure this is easily done with a shell command, but what the main purpose of this is to MAP and Network drive (we know what the computer name to network is) blind to the user, then UNMAP it when we are done with the task which we have started.  

If there is a better or easier way without shell command I'm up for options.

Sorry I can offer more points I have been too generous in the past and only have 101 total points left.  Don't know why but it also said I have 151 Point available, isn't that backwards?

Thanx,
Chizl
Comment
Watch Question

Commented:
Chizl,
See if this works for you.
Regards
Dalin


'Declaration
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              

Private Declare Function WaitForSingleObject Lib _
"kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds _
As Long) As Long

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              

Declare Function CloseHandle Lib "kernel32" (ByVal hObject _
As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&
             

'Prodedure

'This is the code that can be called to execute an external program.  
'Simply copy this code into the code of your project.  To run an external
'program, call ExecCmd(program) from anywhere in your code.

Public Sub ExecCmd(cmdline$)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO

' Initialize the STARTUPINFO structure:
start.cb = Len(start)

' Start the shelled application:
ret& = CreateProcessA(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              

Author

Commented:
It works perfect except one thing.  It is visible to the user.  We are running a dos command line from Shell or ShellExecute, but this would work great if there is a way of keeping the dos window from popping up.

Author

Commented:
Also I see that running like this If I keep the DOS window then I can't kill it within my app.  I don't want this because if I wanted to use the window then I could use FindWindow to get when the dos app is dead and then close it.   If I can get this invisible, vbHide, then I could most defantly use it.  Thanx for the good and close example of what I need.

Author

Commented:
I have been playing with the:

start.wShowWindow = 0 up to start.wShowWindow = 10 and thought this might have something to do with hidding the DOS Window.  All I see so far is everyone of them do the exact same thing, NOTHING!  Any clues?
Dr. Kamal MehdiIT Director / IT Project Manager
CERTIFIED EXPERT

Commented:
After starting the process, get the window handle and hide it using the SW_HIDE.

Public Const SW_HIDE = 0
Declare Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long

Hope that helps.

Author

Commented:
Sorry!

The problem there is that the, "CreateProcessA" doesn't pass back a handle.  I could use the FindWindow to get the handle, but that is where I don't want to go.  I don't want any windows, even for a few seconds.  Even if the window was there shortly before I Hide it, it would still be in memory at a finished status making the process never to end.

Thanx for the help though!

Commented:
Chizl,

   Is this the function you want (I put code in a form module) :

-----
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
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
Const PROCESS_QUERY_INFORMATION = &H400
Const INFINITE = &HFFFF

Public Sub ShellAndWait(ByVal sTask As String)

    Dim lTaskID As Long
    Dim hTask As Long
    Dim lRtn As Long
   
    lTaskID = Shell(sTask, vbHide)
    If lTaskID <> 0 Then
        ' Use task id to obtain the process handle
        hTask = OpenProcess(PROCESS_QUERY_INFORMATION, False, lTaskID)
        ' Wait till the task finish
        lRtn = WaitForSingleObject(hTask, INFINITE)
        ' Close the process handle
        CloseHandle hTask
    End If
   
End Sub
-----

Hope it helps.

Commented:
Why not changing the appropriate values in the registry, this way you will not have to create another process, and it will be completly transparent

Author

Commented:
Well the hidding is what I want which I could already do that.  You are hidding the window, but the process is still open in memory and isn't closing when its finished.  So this makes the project lock up and I now have to alt-ctrl-del to get it out of memory.   A little of everything here is what I want, but making it all work correctly isn't easy.

>>Why not changing the appropriate values in the
>>registry, this way you will not have to create
>>another process, and it will be completly
>>transparent.

????? What do you mean?

CERTIFIED EXPERT
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
CERTIFIED EXPERT

Commented:
Note these two lines, these are what hides the window:

  Start.dwFlags = STARTF_USESHOWWINDOW

  Start.wShowWindow = SW_HIDE

Author

Commented:
Perfect!  Thanx much!
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.