Killing an external app called with ShellExecute

Hi all;

Ok, big points for a quick response...

I opened an SSH tunnel from within VB with the following:

ShellExecute Me.hwnd, "Open", "C:/plink.exe", "-ssh -l sshtunnel -pw 12345 -L 3306: -batch", "c:\", 0

I would not like to be able to kill it when it's dead. Any solutions?
LVL 17
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

instead of shell execute, you want to use a system.diagnostic.process

Here is an example of opening explorer letting it go for 30000 mil, and closing it (use it to refresh cache of an site after a bulk upload of data)

        Dim IE_Process As New System.Diagnostics.Process
        IE_Process = Process.Start("iexplore", "http://localhost/freightfinder/Cache_Renew.aspx")

or if you dont want to actually close the process, but just wait for it to finish (use this to run dts script and wait for them to execute):
        Dim DTS_Process As New System.Diagnostics.Process
        DTS_Process = Process.Start("C:\Program Files\Microsoft SQL Server\80\Tools\Binn\dtsrun.exe", "/E /S127.0.0.1 /NLISTING_Import")
If you use Shell you could use this function:
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Are you using VB6 or .NET?

If VB6, I can show you how to the use the CreateProcess and TerminateProcess API's to accomplish this as well.

Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

SqueebeeAuthor Commented:
I use VB6. I'm not sure I can use shell because of the arguments. Anyway, I am open to VB6 suggestions.
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Create a new project and add a two command buttons and timer to the main form.  Also add a module.

Paste the code below into the areas as they are labeled.  The first button will launch notepad.  At least it does on my system.  You can change the cmd string to whatever it is you want.  The second button will kill the launched application.  The program will also automatically detect if the application has closed within 100 milliseconds and react accordingly.

Run the app and try using the kill button and/or closing the launched app to see what happens.

' Code for the main form....
Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 100
    Command1.Caption = "Start"
    Command2.Caption = "Kill"
    Command2.Enabled = False
End Sub

Private Sub Command1_Click()
    Dim cmd As String
    cmd = "c:\windows\notepad.exe"
    'cmd = "C:/plink.exe -ssh -l sshtunnel -pw 12345 -L 3306: -batch"
    If RunProcess(cmd, SW_NORMAL) Then
        Command1.Enabled = False
        Timer1.Enabled = True
        Command2.Enabled = True
        MsgBox "Unable to start command: " & cmd
    End If
End Sub

Private Sub Command2_Click()
    lngReply = TerminateProcess(lngProcess, 0&)
End Sub

Private Sub Timer1_Timer()
    lngReply = WaitForSingleObject(lngProcess, 0)
    If lngReply <> 258 Then ' 258 means the process is still running
    End If
End Sub

Private Sub resetApp()
    Timer1.Enabled = False
    lngReply = CloseHandle(lngProcess)
    lngReply = CloseHandle(lngThread)
    Command1.Enabled = True
    Command2.Enabled = False
End Sub

' Code for the module...
Option Explicit

Public Enum enSW
    SW_HIDE = 0
    SW_NORMAL = 1
End Enum

Global lngProcess As Long
Global lngThread As Long
Global lngProcessID As Long
Global lngThreadID As Long
Global lngReply As Long

        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 Byte
        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

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

Public Declare Function GetExitCodeProcess Lib "kernel32" _
      (ByVal hProcess As Long, lpExitCode As Long) As Long

Public Declare Function CreateProcess Lib "kernel32" Alias _
    "CreateProcessA" (ByVal lpApplicationName As String, ByVal _
    lpCommandLine As String, lpProcessAttributes As Any, _
    lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal _
    dwCreationFlags As Any, lpEnvironment As Any, ByVal _
    lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION) As Long

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

Public Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess _
    As Long, ByVal uExitCode As Long) As Long
Global sNull As String

Public Function RunProcess(sCmd As String, start_size As enSW) As Boolean
    'Use the CreateProcess API to start the job. This will give us
    'Process,Thread,ProcessID and ThreadID handles
    sInfo.cb = Len(sInfo)
    sInfo.wShowWindow = start_size
    lngReply = CreateProcess(sNull, sCmd, ByVal 0&, ByVal 0&, 1&, _
        NORMAL_PRIORITY_CLASS, ByVal 0&, sNull, sInfo, pInfo)
    If lngReply = 0 Then
        RunProcess = False
        lngProcessID = pInfo.dwProcessId
        lngThreadID = pInfo.dwThreadId
        lngProcess = pInfo.hProcess
        lngThread = pInfo.hThread
        'Check every 100 milliseconds if the job is finished
        'Any job started with CreateProcess must call CloseHandle for both the
        'Process and Thread handles. See Timer1 on frmMain
        RunProcess = True
    End If
End Function


SqueebeeAuthor Commented:
Thanks, I will try that when I get home and get back to you.
Try to invioke the executable using shellexecuteex, and terminate the process using Terminateprocess.
Cos, the sheellexecuteex gives the processid, which can used to kill the process

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.