I have a vb.net program that watches for an event and then executes the associated program with that event. Then monitors the task and if it stops unexpectedly, then it is restarted. All this works, but I tried to make the program smart enough that if the controlling program is stopped and restarted, while one of the existing events is running, it would find the correct task, then start monitoring it. I did a Process.GetProcess and looped looking at the MainModule.Filename. This works for .exe, but when starting a .bat file, the file name is “cmd.exe”.
Any ideas what other properties I can use to match up a running task?
Basic Start task:
Dim psi As New ProcessStartInfo()
psi.FileName = tmpProgramToExcute
psi.UseShellExecute = True
psi.Arguments = tmpCommandLineOptions
psi.Verb = "runas"
psi.WindowStyle = tmpWindowStyle
tmpTask = New Process
tmpTask.StartInfo = psi
tmpTask.Start()
Searching code:
If (tmpTask IsNot Nothing) AndAlso tmpTask.HasExited Then
tmpTask.Dispose()
tmpTask = Nothing
End If
Dim tmpProcess() As Process = Process.GetProcesses
For xLoop_tmpProcess As Integer = 0 To tmpProcess.Count - 1
Try
If tmpProcess(xLoop_tmpProcess).MainModule.FileName.ToLower = tmpProgramToExcute.ToLower Then
tmpTask = tmpProcess(xLoop_tmpProcess)
NewProcessingList(tmpKey).Task = tmpTask
Exit For
End If
Catch ex As Exception
End Try
Next
Updated 9/8/2016 12:39pm Local time I went back to my old vb6 program, which is btw the one I am replacing, was written in 2003. I had as one of my black box functions was to start a program. This is it:
Function StartPrg(PrgName As String, Optional tmpText As String = "", Optional WindowState As WindowStyle = 4, Optional CmdPram As String = "") As Long
'0 hidden and focus is passed to the hidden window.
'1 Has focus and is restored to its original size and position.
'2 Is displayed as an icon with focus (minimized).
'3 Is maximized with focus.
'4 Is restored to its most recent size and position. No Focus.
'6 Is displayed as an icon. No Focus.
Dim tmpPID As Long
Dim xLoop As Long
Dim yLoop As Long
Dim PrgStarted As Boolean
'Log.It "Try to start " + PrgName
'tmpPID = Shell(PrgName, WindowState)
Dim Ret As Integer
Dim Bfr As String
Dim ExPath As String
Dim Ext As String
'If Dir(PrgName) = "" Or PrgName = "" Then
' StartPrg = -1
' Exit Function
'End If
If Ext = ".EXE" Or Ext = ".COM" Or Ext = ".BAT" Then
tmpPID = Shell(PrgName + " " + CmdPram, WindowState)
Else
Bfr = String(300, 32)
Ext = UCase(Right$(PrgName, 4))
Ret = FindExecutable(PrgName, vbNullString, Bfr)
If Ret > 32 Then
ExPath = Left$(Bfr, InStr(Bfr, Chr$(0)) - 1)
tmpPID = Shell(ExPath + " " + CmdPram, WindowState)
Else
StartPrg = -1
Exit Function
End If
End If
'Log.It PrgName + " started"
For xLoop = 1 To 10
DoEvents
If PrgStarted Then Exit For
For xSleepLoop = 1 To 100
PrgStarted = PrgExist(tmpPID)
If PrgStarted Then Exit For
Sleep 10
DoEvents
Next xSleepLoop
Next
If xLoop < 11 Then
MyPID = tmpPID
fEnumWindows
If Len(tmpText) > 0 Then
For xLoop = 1 To OnWin
If MyWinList(1, xLoop) = tmpPID Then
SendMessageA MyWinList(2, xLoop), WM_SETTEXT, 0&, tmpText
DoEvents
Sleep 10
End If
Next
End If
StartPrg = tmpPID
Else
StartPrg = -1
Exit Function
End If
End Function
So I tried to replcate it in vb.net:
Public Function ShellAndNotWait(ByVal sFilePath As String,
Optional ByVal sCommandLineOptions As String = "",
Optional ByRef sStdOut As Boolean = False,
Optional ByRef sStdError As Boolean = False,
Optional pWindowStyle As eShellWindowStyle = eShellWindowStyle.RecentSizeNoFocus,
Optional pWindowName As String = "") As Process
Dim psi As New ProcessStartInfo()
psi.FileName = sFilePath
psi.UseShellExecute = (Not (sFilePath.ToUpper.EndsWith(".EXE") Or sFilePath.ToUpper.EndsWith(".COM") Or sFilePath.ToUpper.EndsWith(".BAT")))
psi.Arguments = sCommandLineOptions
psi.RedirectStandardOutput = sStdOut
psi.RedirectStandardError = sStdError
psi.CreateNoWindow = sStdOut Or sStdError
Select Case pWindowStyle
Case eShellWindowStyle.HiddenFocus
psi.WindowStyle = ProcessWindowStyle.Hidden
Case eShellWindowStyle.IconFocus Or
eShellWindowStyle.IconNoFocus
psi.WindowStyle = ProcessWindowStyle.Minimized
Case eShellWindowStyle.RecentSizeFocus Or
eShellWindowStyle.RecentSizeNoFocus
psi.WindowStyle = ProcessWindowStyle.Normal
Case eShellWindowStyle.MaximizedFocus
psi.WindowStyle = ProcessWindowStyle.Maximized
End Select
Dim proc As New Process
proc.StartInfo = psi
proc.Start()
If proc Is Nothing Then Return Nothing
Sleep(100)
If pWindowName.Length > 0 Then SetWindowText(proc.MainWindowHandle, pWindowName)
If pWindowStyle = eShellWindowStyle.HiddenFocus OrElse
pWindowStyle = eShellWindowStyle.IconFocus OrElse
pWindowStyle = eShellWindowStyle.MaximizedFocus OrElse
pWindowStyle = eShellWindowStyle.RecentSizeFocus Then
AppActivate(proc.Id)
End If
Return proc
End Function
I can set the title all that works. Then as long as it is unique I can find the task again and assume the task as if I started it from the start. My issue is the VB6 shell had 6 modes of starting the window and .Net doesn't. I was trying to emulate some of it, but setting the startinfo windowstyle to minimize does not work. After some google it looks like if you are starting cmd.exe, it ignores the "hint". A lot of posts was about hiding the window, so the fix was set CreateWindow to false. Well I want a window, just minimize to the task bar. If someone says something simple, I will leave it on this thread. Also I will do some more google, but if I can't find anything on this, I will start a new thread. For now I am leaving it open just so it will all be in one place, but looks like I went with the window title for the fix.
Bottom line.... To find an existing app that I started, but was orphen because the app that started it was restarted itself, I went with window title. So the rule is, all window titles that this app is managing must be unique.
More detail.... I was wanting a program to manage a list of programs, I call services, but they are not true window services, they are just plain programs and batch files that if they stop, they will be restarted. I went with a window app so I can have some sort of GUI to start/stop and if a program was stated hidden it could be made visible. So I created a class to track the info needed (clsServiceList), then added it to a list of call lstServices (lstServices = new list(of clsServiceList)). There are two main subs "ServiceUpdate" and "StartService". After a call to ServiceUpdate, all the status (properties) of lstServices should be current. This could be called at the start up to find orphen task or every few seconds to see if one needed to be restarted. As part of this thread was to find a way to set the window title, then manage the window style. So here is the code, if I need to add to it just let me know. Thanks all for your help.
Private Class clsServiceList
';0 hidden And focus Is passed to the hidden window.
';1 Has focus And Is restored to its original size And position.
';2 Is displayed as an icon with focus (minimized).
';3 Is maximized with focus.
';4 Is restored to its most recent size And position. No Focus.
';6 Is displayed as an icon. No Focus.
Public ProcessName As String
Public ProgramToExcute As String
Public CommandLineOptions As String
Public Task As Process = Nothing
Public WindowTitle As String = ""
Public WindowStyle As eShellWindowStyle = eShellWindowStyle.RecentSizeNoFocus
Public HowRun As String = "" 'KR keep running or JS just once
Public IsWindowIconic As Boolean = False
Public IsWindowVisible As Boolean = False
Public IsWindowZoomed As Boolean = False
Public IsWindowNormal As Boolean = False
Sub New(pProcessName As String,
pProgramToExcute As String,
pCommandLineOptions As String,
pWindowTitle As String,
pWindowStyle As String,
pHowRun As String)
Me.ProcessName = pProcessName
Me.ProgramToExcute = pProgramToExcute
Me.CommandLineOptions = pCommandLineOptions
WindowStyle = CType(CIntNull(pWindowStyle), eShellWindowStyle)
WindowTitle = pWindowTitle
HowRun = pHowRun
End Sub
End Class
End Class
Private Sub ServicesUpdate()
Dim tmpProcess() As Process = Process.GetProcesses
For xLoop_Services As Integer = 0 To lstServices.Count - 1
For xLoop_Process As Integer = 0 To tmpProcess.Count - 1
If tmpProcess(xLoop_Process).MainWindowTitle = lstServices(xLoop_Services).WindowTitle Then
If lstServices(xLoop_Services).Task Is Nothing Then lstServices(xLoop_Services).Task = tmpProcess(xLoop_Process)
lstServices(xLoop_Services).IsWindowIconic = IsWindowIconic(lstServices(xLoop_Services).Task.MainWindowHandle)
lstServices(xLoop_Services).IsWindowZoomed = IsWindowZoomed(lstServices(xLoop_Services).Task.MainWindowHandle)
lstServices(xLoop_Services).IsWindowNormal = IsWindowNormal(lstServices(xLoop_Services).Task.MainWindowHandle)
lstServices(xLoop_Services).IsWindowVisible = IsWindowVisible(lstServices(xLoop_Services).Task.MainWindowHandle)
End If
Next
Next
End Sub
Public Function IsWindowIconic(ByVal hWnd As IntPtr) As Boolean
Return ((GetWindowLong(hWnd, WindowLongFlags.GWL_STYLE) And WS_MINIMIZE) = WS_MINIMIZE)
End Function
Public Function IsWindowVisible(ByVal hWnd As IntPtr) As Boolean
Return ((GetWindowLong(hWnd, WindowLongFlags.GWL_STYLE) And WS_VISIBLE) = WS_VISIBLE)
End Function
Public Function IsWindowZoomed(ByVal hWnd As IntPtr) As Boolean
Return ((GetWindowLong(hWnd, WindowLongFlags.GWL_STYLE) And WS_MAXIMIZE) = WS_MAXIMIZE)
End Function
Public Function IsWindowNormal(ByVal hWnd As IntPtr) As Boolean
Return Not (IsWindowIconic(hWnd) Or IsWindowZoomed(hWnd))
End Function
<DllImport("user32.dll", SetLastError:=True)>
Private Function GetWindowLong(hWnd As IntPtr,
<MarshalAs(UnmanagedType.I4)> nIndex As WindowLongFlags) As Integer
End Function
Public Enum WindowLongFlags As Integer
GWL_EXSTYLE = -20
GWLP_HINSTANCE = -6
GWLP_HWNDPARENT = -8
GWL_ID = -12
GWL_STYLE = -16
GWL_USERDATA = -21
GWL_WNDPROC = -4
DWLP_USER = &H8
DWLP_MSGRESULT = &H0
DWLP_DLGPROC = &H4
End Enum
' Window Styles
Const WS_OVERLAPPED As UInt32 = 0
Const WS_POPUP As UInt32 = &H80000000&
Const WS_CHILD As UInt32 = &H40000000
Const WS_MINIMIZE As UInt32 = &H20000000
Const WS_VISIBLE As UInt32 = &H10000000
Const WS_DISABLED As UInt32 = &H8000000
Const WS_CLIPSIBLINGS As UInt32 = &H4000000
Const WS_CLIPCHILDREN As UInt32 = &H2000000
Const WS_MAXIMIZE As UInt32 = &H1000000
Const WS_CAPTION As UInt32 = &HC00000 ' WS_BORDER or WS_DLGFRAME
Const WS_BORDER As UInt32 = &H800000
Const WS_DLGFRAME As UInt32 = &H400000
Const WS_VSCROLL As UInt32 = &H200000
Const WS_HSCROLL As UInt32 = &H100000
Const WS_SYSMENU As UInt32 = &H80000
Const WS_THICKFRAME As UInt32 = &H40000
Const WS_GROUP As UInt32 = &H20000
Const WS_TABSTOP As UInt32 = &H10000
Const WS_MINIMIZEBOX As UInt32 = &H20000
Const WS_MAXIMIZEBOX As UInt32 = &H10000
Const WS_TILED As UInt32 = WS_OVERLAPPED
Const WS_ICONIC As UInt32 = WS_MINIMIZE
Const WS_SIZEBOX As UInt32 = WS_THICKFRAME
' Extended Window Styles
Const WS_EX_DLGMODALFRAME As UInt32 = &H1
Const WS_EX_NOPARENTNOTIFY As UInt32 = &H4
Const WS_EX_TOPMOST As UInt32 = &H8
Const WS_EX_ACCEPTFILES As UInt32 = &H10
Const WS_EX_TRANSPARENT As UInt32 = &H20
Const WS_EX_MDICHILD As UInt32 = &H40
Const WS_EX_TOOLWINDOW As UInt32 = &H80
Const WS_EX_WINDOWEDGE As UInt32 = &H100
Const WS_EX_CLIENTEDGE As UInt32 = &H200
Const WS_EX_CONTEXTHELP As UInt32 = &H400
Const WS_EX_RIGHT As UInt32 = &H1000
Const WS_EX_LEFT As UInt32 = &H0
Const WS_EX_RTLREADING As UInt32 = &H2000
Const WS_EX_LTRREADING As UInt32 = &H0
Const WS_EX_LEFTSCROLLBAR As UInt32 = &H4000
Const WS_EX_RIGHTSCROLLBAR As UInt32 = &H0
Const WS_EX_CONTROLPARENT As UInt32 = &H10000
Const WS_EX_STATICEDGE As UInt32 = &H20000
Const WS_EX_APPWINDOW As UInt32 = &H40000
Const WS_EX_OVERLAPPEDWINDOW As UInt32 = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE)
Const WS_EX_PALETTEWINDOW As UInt32 = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST)
Const WS_EX_LAYERED As UInt32 = &H80000
Const WS_EX_NOINHERITLAYOUT As UInt32 = &H100000 ' Disable inheritence of mirroring by children
Const WS_EX_LAYOUTRTL As UInt32 = &H400000 ' Right to left mirroring
Const WS_EX_COMPOSITED As UInt32 = &H2000000
Const WS_EX_NOACTIVATE As UInt32 = &H8000000
Private Sub StartService(pServiceNumber As Integer)
If Path.GetFileName(lstServices(pServiceNumber).ProgramToExcute) = lstServices(pServiceNumber).ProgramToExcute Then
Dim tmpPath As String = Space(300)
Dim tmpValue As Long = FindExecutable(lstServices(pServiceNumber).ProgramToExcute, vbNullString, tmpPath)
If tmpValue > 32 Then
lstServices(pServiceNumber).ProgramToExcute = tmpPath.Substring(0, tmpPath.IndexOf(vbNullChar))
End If
End If
Dim tmpProcess As Process = ShellAndNotWait(lstServices(pServiceNumber).ProgramToExcute,
lstServices(pServiceNumber).CommandLineOptions,
False, False,
lstServices(pServiceNumber).WindowStyle,
lstServices(pServiceNumber).WindowTitle)
lstServices(pServiceNumber).Task = tmpProcess
lstServices(pServiceNumber).IsWindowIconic = IsWindowIconic(lstServices(pServiceNumber).Task.MainWindowHandle)
lstServices(pServiceNumber).IsWindowZoomed = IsWindowZoomed(lstServices(pServiceNumber).Task.MainWindowHandle)
lstServices(pServiceNumber).IsWindowNormal = IsWindowNormal(lstServices(pServiceNumber).Task.MainWindowHandle)
lstServices(pServiceNumber).IsWindowVisible = IsWindowVisible(lstServices(pServiceNumber).Task.MainWindowHandle)
If lstServices(pServiceNumber).WindowTitle.Length = 0 Then lstServices(pServiceNumber).WindowTitle = tmpProcess.MainWindowTitle
End Sub
Public Function ShellAndNotWait(ByVal sFilePath As String,
Optional ByVal sCommandLineOptions As String = "",
Optional ByRef sStdOut As Boolean = False,
Optional ByRef sStdError As Boolean = False,
Optional pWindowStyle As eShellWindowStyle = eShellWindowStyle.RecentSizeNoFocus,
Optional pWindowName As String = "") As Process
Dim psi As New ProcessStartInfo()
psi.FileName = sFilePath
psi.UseShellExecute = (Not (sFilePath.ToUpper.EndsWith(".EXE") Or sFilePath.ToUpper.EndsWith(".COM") Or sFilePath.ToUpper.EndsWith(".BAT")))
psi.Arguments = sCommandLineOptions
psi.RedirectStandardOutput = sStdOut
psi.RedirectStandardError = sStdError
psi.CreateNoWindow = sStdOut Or sStdError
Dim proc As New Process
proc.StartInfo = psi
proc.Start()
If proc Is Nothing Then Return Nothing
Sleep(100)
If pWindowName.Length > 0 Then SetWindowText(proc.MainWindowHandle, pWindowName)
Select Case pWindowStyle
Case eShellWindowStyle.HiddenFocus Or eShellWindowStyle.HiddenFocus
ShowWindow(proc.MainWindowHandle, eSHOW_WINDOW.SW_HIDE)
Case eShellWindowStyle.IconFocus Or eShellWindowStyle.IconNoFocus
ShowWindow(proc.MainWindowHandle, eSHOW_WINDOW.SW_MINIMIZE)
Case eShellWindowStyle.MaximizedFocus
ShowWindow(proc.MainWindowHandle, eSHOW_WINDOW.SW_MAXIMIZE)
Case eShellWindowStyle.RecentSizeFocus Or eShellWindowStyle.RecentSizeNoFocus
ShowWindow(proc.MainWindowHandle, eSHOW_WINDOW.SW_NORMAL)
End Select
If pWindowStyle = eShellWindowStyle.HiddenFocus OrElse
pWindowStyle = eShellWindowStyle.IconFocus OrElse
pWindowStyle = eShellWindowStyle.MaximizedFocus OrElse
pWindowStyle = eShellWindowStyle.RecentSizeFocus Then
AppActivate(proc.Id)
End If
Return proc
End Function
<DllImport("shell32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Function FindExecutable(ByVal lpFile As String,
ByVal lpDirectory As String,
ByVal lpResult As String) As Long
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As eSHOW_WINDOW) As Integer
End Function
<Flags()>
Public Enum eSHOW_WINDOW As Integer
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_FORCEMINIMIZE = 11
SW_MAX = 11
End Enum
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.