View Single Post
Old 01-16-2004, 05:45 AM   #4 (permalink)
wondash
Psycho
 
I wrote this class module some years ago. It's a bit long, and may do more than you want. Hopefully it will help or at least give you some idea on how to do it yourself.

Option Explicit

'Properties
'-----------
' ShowWindow as integer         (write-only)
'     SW_HIDE = 0
'     SW_SHOWNORMAL = 1
'     SW_NORMAL = 1
'     SW_SHOWMINIMIZED = 2
'     SW_SHOWMAXIMIZED = 3
'     SW_MAXIMIZE = 3
'     SW_SHOWNOACTIVATE = 4
'     SW_SHOW = 5
'     SW_MINIMIZE = 6
'     SW_SHOWMINNOACTIVE = 7
'     SW_SHOWNA = 8
'     SW_RESTORE = 9
'     SW_SHOWDEFAULT = 10
'     SW_MAX = 10
' LastError as string         (read-only) Last error message
' LastErrorNumber as integer    (read-only) Last error number
'
'Methods
'-----------
' RunAndWaitForTerminate
'             (Process As String)
'             As Boolean
'             Executes the specified process and waits for it to terminate.
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' RunAndGetProccessId
'             (Process as String, ProcessID as Long, ProcessHandle as Long)
'             As Boolean
'             Input: Process
'             Ouput: ProcessID, ProcessHandle
'                 Executes the specified process and returns it's process id and handle
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' CheckStillRunning
'             (ProcessHandle as Long, StillRunning as Boolean)
'             As Boolean
'             Input: ProcessId
'             Ouput: StillRunning
'                 StillRunning returns True if still running, returns False and closes handle
'                 if not running.
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' CloseWindow
'             (WindowHandle as Long)
'             as Boolean
'             Input: WindowHandle
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' GetWindowHandleForProcessId
'             (ProcessId as Long, WindowHandle as Long, Optional WindowTitle as String)
'             as Boolean
'             Input: ProcessId
'             Ouput: WindowHandle, WindowTitle (optional)
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' GetWindowHandleByTitle
'             (WindowTitle as String, WindowHandle as Long, Optional MatchExact as Boolean)
'             as Boolean
'             Input: WindowTitle
'                     MatchExact - Only return window with exact match on WindowTitle,
'                                 otherwise use sub-string match.
'             Output: WindowHandle
'             Returns true if successful, else sets LastError and LastErrorNumber.
'             Note: Returns the 1st window that matches the WindowTitle.
'
' GetShortFileName
'             (sLongFileName As String, sShortFileName As String)
'             As Boolean
'             Input: sLongFileName
'             Output: sShortFileName
'             Returns true if successful, else sets LastError and LastErrorNumber.
'
' SplitFileNameAndParams
'             (sFilePathNameParams As String, sFilePathName As String, sParams As String)
'             Input: sFilePathNameParams
'             Output: sFilePathName
'                     sParams
'
Private sLastError As String
Private lLastError As Long

'API stuff
Public Enum ShowWindow
    SW_HIDE = 0
    SW_SHOWNORMAL = 1
    SW_NORMAL = 1
    SW_SHOWMINIMIZED = 2
    SW_SHOWMAXIMIZED = 3
    SW_MAXIMIZE = 3
    SW_SHOWNOACTIVATE = 4
    SW_SHOW = 5
    SW_MINIMIZE = 6
    SW_SHOWMINNOACTIVE = 7
    SW_SHOWNA = 8
    SW_RESTORE = 9
    SW_SHOWDEFAULT = 10
    SW_MAX = 10
End Enum
Private Const STARTF_USESHOWWINDOW = &H1

Private Const SYNCHRONIZE = &H100000
Private Const INFINITE = &HFFFF         ' Infinite timeout
Private Const CREATE_SUSPENDED = &H4
Private Const DETACHED_PROCESS = &H8
Private Const CREATE_NEW_CONSOLE = &H10

Private Const NORMAL_PRIORITY_CLASS = &H20
Private Const IDLE_PRIORITY_CLASS = &H40
Private Const HIGH_PRIORITY_CLASS = &H80
Private Const REALTIME_PRIORITY_CLASS = &H100

Private Const CREATE_NEW_PROCESS_GROUP = &H200
Private Const CREATE_NO_WINDOW = &H8000000

Private Const WAIT_FAILED = -1&
Private Const WAIT_OBJECT_0 = 0
Private Const WAIT_ABANDONED = &H80&
Private Const WAIT_ABANDONED_0 = &H80&
Private Const WAIT_TIMEOUT = &H102&

Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type

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 myStartupInfo As STARTUPINFO

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateProcessBynum Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function GetLastError Lib "kernel32" () As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag 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 GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Const GW_CHILD = 5
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_CLOSE = &H10

Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" _
    (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long

'FileSystemObject (scrrun.dll)
Private fso As New Scripting.FileSystemObject

Property Get LastError() As String
    LastError = sLastError
    
End Property

Property Get LastErrorNumber() As Long
    LastErrorNumber = lLastError
    
End Property

Property Let ShowWindow(ShowWindow As Integer)
    myStartupInfo.wShowWindow = ShowWindow
    
End Property

Public Function RunAndGetProcessId(Process As String, ProcessId As Long, ProcessHandle As Long) As Boolean
    Dim lRtnCode As Long
    Dim myProcessInfo As PROCESS_INFORMATION
    Dim sPathAndName As String
    Dim sParams As String
    Dim sTemp As String
    
    sLastError = ""
    lLastError = 0
    On Error GoTo RunAndGetProcessIdError
    
    SplitFileNameAndParams Process, sPathAndName, sParams
    If sParams = "" Then sParams = vbNullString
    
    'Make sure the process file path and name are specified as short names (8.3, no spaces)
    sTemp = sPathAndName
    GetShortFileName sTemp, sPathAndName

    'Confirm process exists
    If Dir(sPathAndName) = "" Then
        'Try again with .exe added
        If Dir(sPathAndName & ".exe") = "" Then
            lLastError = vbObjectError + 500
            sLastError = "File Not Found [" & sPathAndName & "]"
            Exit Function
        Else
            sPathAndName = sPathAndName & ".exe"
        End If
    End If
    
    lRtnCode = CreateProcessBynum(vbNullString, sPathAndName & " " & sParams, 0, 0, True, _
    NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, myStartupInfo, myProcessInfo)
    If lRtnCode = 0 Then 'Failure
        lLastError = GetLastError()
        sLastError = "CreateProcessBynum Error; Process [" & Process & "], Short Filename Process [" & sPathAndName & " " & sParams & "]"
        
        'Just in case, close the process handle
        On Error Resume Next
        Call CloseHandle(myProcessInfo.hThread)
        
        Exit Function
    End If

    'We don't need the thread handle
    Call CloseHandle(myProcessInfo.hThread)

    'Return the processid and thread
    ProcessHandle = myProcessInfo.hProcess
    ProcessId = myProcessInfo.dwProcessId
    RunAndGetProcessId = True
    Exit Function
    
RunAndGetProcessIdError:
    sLastError = Error$
    lLastError = Err
    
End Function

Public Function CheckStillRunning(ProcessHandle As Long, StillRunning As Boolean) As Boolean
    Dim lRtnCode As Long
    
    sLastError = ""
    lLastError = 0
    On Error GoTo StillRunningError
    
    'Check if running
    lRtnCode = WaitForSingleObject(ProcessHandle, 0)
    
&nbsp;&nbsp;&nbsp;&nbsp;If lRtnCode <> WAIT_TIMEOUT Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' No timeout, app is terminated
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StillRunning = False
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' Kill the last handle of the process
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(ProcessHandle)
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StillRunning = True
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;CheckStillRunning = True
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
StillRunningError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err

End Function

Public Function GetWindowHandleForProcessId(ProcessId As Long, WindowHandle As Long, _
&nbsp;&nbsp;&nbsp;&nbsp;Optional WindowTitle As String) As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;Dim lHwnd As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim lThread As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim lProcessId As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim lTitleLen As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim sTitle As String
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = ""
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = 0
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo GetWindowHandleForProcessIdError
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'The desktop is the highest window
&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetDesktopWindow()
&nbsp;&nbsp;&nbsp;&nbsp;'Its first child is the 1st top level window
&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetWindow(lHwnd, GW_CHILD)

&nbsp;&nbsp;&nbsp;&nbsp;'Search through all the windows
&nbsp;&nbsp;&nbsp;&nbsp;Do While lHwnd <> 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lThread = GetWindowThreadProcessId(lHwnd, lProcessId)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If lProcessId = ProcessId Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'MsgBox "Handle:" & lHwnd & " Thread:" & lThread & " ProcessId" & lProcessId
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WindowHandle = lHwnd
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Get the next window
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetNextWindow(lHwnd, GW_HWNDNEXT)
&nbsp;&nbsp;&nbsp;&nbsp;Loop
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Did we find the window?
&nbsp;&nbsp;&nbsp;&nbsp;If lHwnd <> 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Get the window title
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Not IsMissing(WindowTitle) Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lTitleLen = GetWindowTextLength(lHwnd)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTitle = String(lTitleLen + 1, " ")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lTitleLen = GetWindowText(lHwnd, sTitle, lTitleLen + 1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WindowTitle = Left$(sTitle, lTitleLen)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetWindowHandleForProcessId = True
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "No window handle found for ProcessId [" & ProcessId & "]"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lLastError = vbObjectError + 501
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
GetWindowHandleForProcessIdError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err
&nbsp;&nbsp;&nbsp;&nbsp;
End Function

Public Function CloseWindow(WindowHandle As Long) As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;Dim lRtnCode As Long
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = ""
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = 0
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo CloseWindowError
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Post a message to the process to close
&nbsp;&nbsp;&nbsp;&nbsp;lRtnCode = PostMessage(WindowHandle, WM_CLOSE, 0&, 0&)
&nbsp;&nbsp;&nbsp;&nbsp;If lRtnCode = 0 Then 'Failure
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lLastError = GetLastError()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "PostMessage Error; WindowHandle [" & WindowHandle & "]"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;CloseWindow = True
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
CloseWindowError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err

End Function

Public Function RunAndWaitForTerminate(Process As String) As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;Dim lRtnCode As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim myProcessInfo As PROCESS_INFORMATION
&nbsp;&nbsp;&nbsp;&nbsp;Dim sPathAndName As String
&nbsp;&nbsp;&nbsp;&nbsp;Dim sParams As String
&nbsp;&nbsp;&nbsp;&nbsp;Dim sTemp As String
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = ""
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = 0
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo RunAndWaitForTerminateError
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;SplitFileNameAndParams Process, sPathAndName, sParams
&nbsp;&nbsp;&nbsp;&nbsp;If sParams = "" Then sParams = vbNullString
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Make sure the process file path and name are specified as short names (8.3, no spaces)
&nbsp;&nbsp;&nbsp;&nbsp;sTemp = sPathAndName
&nbsp;&nbsp;&nbsp;&nbsp;GetShortFileName sTemp, sPathAndName
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Confirm process exists
&nbsp;&nbsp;&nbsp;&nbsp;If Dir(sPathAndName) = "" Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Try again with .exe added
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Dir(sPathAndName & ".exe") = "" Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lLastError = vbObjectError + 500
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "File Not Found [" & sPathAndName & "]"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sPathAndName = sPathAndName & ".exe"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;lRtnCode = CreateProcessBynum(vbNullString, sPathAndName & " " & sParams, 0, 0, True, _
&nbsp;&nbsp;&nbsp;&nbsp;NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, myStartupInfo, myProcessInfo)
&nbsp;&nbsp;&nbsp;&nbsp;If lRtnCode Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Not WaitForTerm(myProcessInfo) Then Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lLastError = GetLastError()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "CreateProcessBynum Error; Process [" & Process & "], Short Filename Process [" & sPathAndName & " " & sParams & "]"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Just in case, close the process handle
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;On Error Resume Next
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(myProcessInfo.hThread)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;End If

&nbsp;&nbsp;&nbsp;&nbsp;RunAndWaitForTerminate = True
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
RunAndWaitForTerminateError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err
&nbsp;&nbsp;&nbsp;&nbsp;
End Function

Public Function GetWindowHandleByTitle(WindowTitle As String, WindowHandle As Long, _
&nbsp;&nbsp;&nbsp;&nbsp;Optional MatchExact As Boolean, Optional FullWindowTitle As String) As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;Dim lHwnd As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim lTitleLen As Long
&nbsp;&nbsp;&nbsp;&nbsp;Dim sTitle As String
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;WindowHandle = 0
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = ""
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = 0
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo GetWindowHandleByTitleError
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'The desktop is the highest window
&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetDesktopWindow()
&nbsp;&nbsp;&nbsp;&nbsp;'Its first child is the 1st top level window
&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetWindow(lHwnd, GW_CHILD)

&nbsp;&nbsp;&nbsp;&nbsp;'Search through all the windows
&nbsp;&nbsp;&nbsp;&nbsp;Do While lHwnd <> 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lTitleLen = GetWindowTextLength(lHwnd)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTitle = String(lTitleLen + 1, " ") 'Clear title buffer
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lTitleLen = GetWindowText(lHwnd, sTitle, lTitleLen + 1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTitle = Left$(sTitle, lTitleLen)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If MatchExact Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If LCase$(WindowTitle) = LCase$(sTitle) Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WindowHandle = lHwnd
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If InStr(LCase$(sTitle), LCase$(WindowTitle)) > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WindowHandle = lHwnd
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Not IsMissing(FullWindowTitle) Then FullWindowTitle = sTitle
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Get the next window
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lHwnd = GetNextWindow(lHwnd, GW_HWNDNEXT)
&nbsp;&nbsp;&nbsp;&nbsp;Loop
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Did we find the window?
&nbsp;&nbsp;&nbsp;&nbsp;If WindowHandle <> 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetWindowHandleByTitle = True
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "No window found for Window Title [" & WindowTitle & "]"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lLastError = vbObjectError + 502
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
GetWindowHandleByTitleError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err

End Function

Private Function WaitForTerm(myProcessInfo As PROCESS_INFORMATION) As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;Dim lRtnCode As Long
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;WaitForTerm = False
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo WaitForTermError
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Let the process initialize (This is only necessary if we were going
&nbsp;&nbsp;&nbsp;&nbsp;'to perform interprocess communication).
&nbsp;&nbsp;&nbsp;&nbsp;Call WaitForInputIdle(myProcessInfo.hProcess, INFINITE)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'We don't need the thread handle
&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(myProcessInfo.hThread)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lRtnCode = WaitForSingleObject(myProcessInfo.hProcess, 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If lRtnCode <> WAIT_TIMEOUT Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' No timeout, app is terminated
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exit Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoEvents
&nbsp;&nbsp;&nbsp;&nbsp;Loop While True
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;' Kill the last handle of the process
&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(myProcessInfo.hProcess)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;WaitForTerm = True
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
WaitForTermError:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = Error$
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err
&nbsp;&nbsp;&nbsp;&nbsp;
End Function

Public Sub SplitFileNameAndParams(sFilePathNameParams As String, sFilePathName As String, sParams As String)
'The expected input is a run string which may contain
'command line parameters. This sub splits the File Path and Name from the Parameters
'Example;
'sFilePathNameParams= "c:\fund reporting\sungrd.bat 157 5/14/95"
'sFilePathName=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"c:\fund reporting\sungrd.bat"
'sParams=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "157 5/14/95"
&nbsp;&nbsp;&nbsp;&nbsp;Dim sTrimmedProcess As String
&nbsp;&nbsp;&nbsp;&nbsp;Dim nBackSlashIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nSpaceIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nSecondColenIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nSecondDblBackslashIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nSecondMarkerIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nIndex As Integer

&nbsp;&nbsp;&nbsp;&nbsp;sTrimmedProcess = Trim$(sFilePathNameParams)
&nbsp;&nbsp;&nbsp;&nbsp;If Len(sTrimmedProcess) < 3 Then Exit Sub
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Note: The function will not work if the file name has spaces (My File Name.exe)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'This can be very tricky; The file path and name may start with a drive letter
&nbsp;&nbsp;&nbsp;&nbsp;'and colen ( c: ), or may start with two backslashes (\\computer\server\...).
&nbsp;&nbsp;&nbsp;&nbsp;'Also, one or more parameters may be included which are also files (path and name).
&nbsp;&nbsp;&nbsp;&nbsp;'We need to find the first space after the last backslash but prior to a second colon
&nbsp;&nbsp;&nbsp;&nbsp;'or double backslash.
&nbsp;&nbsp;&nbsp;&nbsp;'Examples:
&nbsp;&nbsp;&nbsp;&nbsp;'c:\Program Files\myprog.exe -R c:\data\file.dat
&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^
&nbsp;&nbsp;&nbsp;&nbsp;'c:\Program Files\myprog.exe -R \\comp1\data\file.dat
&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^
&nbsp;&nbsp;&nbsp;&nbsp;'\\comp1\Program Files\myprog.exe -R c:\data\file.dat
&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^
&nbsp;&nbsp;&nbsp;&nbsp;'\\comp1\Program Files\myprog.exe -R \\comp1\data\file.dat
&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Find the second colon (if any)
&nbsp;&nbsp;&nbsp;&nbsp;nSecondColenIndex = InStr(3, sTrimmedProcess, ":")
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Find the second double backslash (if and)
&nbsp;&nbsp;&nbsp;&nbsp;nSecondDblBackslashIndex = InStr(3, sTrimmedProcess, "\\")
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'It's possible that one parameter has a path with a colen and another
&nbsp;&nbsp;&nbsp;&nbsp;'parameter has a path with double backslashes. Keep the first one.
&nbsp;&nbsp;&nbsp;&nbsp;If nSecondColenIndex > 0 And nSecondDblBackslashIndex > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If nSecondColenIndex < nSecondDblBackslashIndex Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSecondMarkerIndex = nSecondColenIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSecondMarkerIndex = nSecondDblBackslashIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Otherwise, the parameters only have the same path type (if any at all)
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If nSecondColenIndex > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSecondMarkerIndex = nSecondColenIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ElseIf nSecondDblBackslashIndex > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSecondMarkerIndex = nSecondDblBackslashIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSecondMarkerIndex = Len(sTrimmedProcess) + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;If nSecondMarkerIndex = 3 Then Exit Sub
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Next find the last backslash prior to the second marker (colen or double backslash)
&nbsp;&nbsp;&nbsp;&nbsp;nIndex = 2
&nbsp;&nbsp;&nbsp;&nbsp;Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nBackSlashIndex = nIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nIndex = InStr(nIndex + 1, sTrimmedProcess, "\")
&nbsp;&nbsp;&nbsp;&nbsp;Loop While nIndex > 0 And nIndex < nSecondMarkerIndex
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Now find the space between the file name and input parameters
&nbsp;&nbsp;&nbsp;&nbsp;nSpaceIndex = InStr(nBackSlashIndex + 1, sTrimmedProcess, " ")
&nbsp;&nbsp;&nbsp;&nbsp;If nSpaceIndex > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sFilePathName = Left$(sTrimmedProcess, nSpaceIndex - 1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sParams = Mid$(sTrimmedProcess, nSpaceIndex + 1)
&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sFilePathName = sTrimmedProcess
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sParams = ""
&nbsp;&nbsp;&nbsp;&nbsp;End If

End Sub

Public Function GetShortFileName(sLongFileName As String, sShortFileName As String) As Boolean
'Converts long path and file names into 8.3 format
&nbsp;&nbsp;&nbsp;&nbsp;Dim FileObject As Scripting.File
&nbsp;&nbsp;&nbsp;&nbsp;Dim sShortPath As String
&nbsp;&nbsp;&nbsp;&nbsp;Dim sLongPath As String
&nbsp;&nbsp;&nbsp;&nbsp;Dim nLen As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim nBackSlashIndex As Integer
&nbsp;&nbsp;&nbsp;&nbsp;Dim bFileObjectError As Boolean
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo ErrorTrap
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'If any error occurs, we'll return a blank value
&nbsp;&nbsp;&nbsp;&nbsp;sShortFileName = ""
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'Use the FileObject to get the short file name.
&nbsp;&nbsp;&nbsp;&nbsp;'Note: The FileObject can only be used if the file has an extension.
&nbsp;&nbsp;&nbsp;&nbsp;If InStr(sLongFileName, ".") > 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;On Error Resume Next
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set FileObject = fso.GetFile(sLongFileName)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Err.Number <> 0 Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bFileObjectError = True
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sShortFileName = FileObject.ShortPath
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Err.Number <> 0 Then bFileObjectError = True
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Close the FileObject
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set FileObject = Nothing
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;On Error GoTo ErrorTrap
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;'If the file does not have a file extension, then we cannot use the
&nbsp;&nbsp;&nbsp;&nbsp;'FileObject to get it's short path and name. Instead,
&nbsp;&nbsp;&nbsp;&nbsp;'we'll use a Windows API call (but GetShortPathName can only
&nbsp;&nbsp;&nbsp;&nbsp;'return the short path name).
&nbsp;&nbsp;&nbsp;&nbsp;If InStr(sLongFileName, ".") = 0 Or bFileObjectError Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Unfortunatelly, the GetShortPathName function only works on paths without
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'the filename. So we need to try and remove the file name.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Find the last backslash.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nBackSlashIndex = nIndex
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nIndex = InStr(nIndex + 1, sLongFileName, "\")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loop While nIndex > 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If nBackSlashIndex = 0 Then Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sLongPath = Left$(sLongFileName, nBackSlashIndex)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sShortPath = String(255, " ")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nLen = GetShortPathName(sLongPath, sShortPath, Len(sShortPath))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sShortFileName = Left$(sShortPath, nLen) & Mid$(sLongFileName, nBackSlashIndex + 1)
&nbsp;&nbsp;&nbsp;&nbsp;End If
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;GetShortFileName = True
&nbsp;&nbsp;&nbsp;&nbsp;Exit Function
&nbsp;&nbsp;&nbsp;&nbsp;
ErrorTrap:
&nbsp;&nbsp;&nbsp;&nbsp;sLastError = "GetShortFileName: " & Err.Description
&nbsp;&nbsp;&nbsp;&nbsp;lLastError = Err.Number
&nbsp;&nbsp;&nbsp;&nbsp;
End Function

Private Sub Class_Initialize()
&nbsp;&nbsp;&nbsp;&nbsp;myStartupInfo.cb = Len(myStartupInfo)
&nbsp;&nbsp;&nbsp;&nbsp;myStartupInfo.dwFlags = STARTF_USESHOWWINDOW
&nbsp;&nbsp;&nbsp;&nbsp;myStartupInfo.wShowWindow = SW_SHOW

End Sub

Private Sub Class_Terminate()
&nbsp;&nbsp;&nbsp;&nbsp;Set fso = Nothing
&nbsp;&nbsp;&nbsp;&nbsp;
End Sub

wondash is offline  
 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360