【问题标题】:How to find a running process when it is a bat file当它是bat文件时如何找到正在运行的进程
【发布时间】:2016-09-07 16:50:13
【问题描述】:

我有一个 vb.net 程序,它监视一个事件,然后执行与该事件相关的程序。然后监视任务,如果它意外停止,则重新启动。所有这些都有效,但我试图让程序足够智能,如果控制程序停止并重新启动,而现有事件之一正在运行,它会找到正确的任务,然后开始监视它。 我做了一个 Process.GetProcess 并循环查看 MainModule.Filename。这适用于 .exe,但在启动 .bat 文件时,文件名为“cmd.exe”。

任何想法我可以使用哪些其他属性来匹配正在运行的任务?

基本开始任务:

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()

搜索代码:

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

当地时间 2016 年 9 月 8 日下午 12:39 更新 我回到我的旧 vb6 程序,这是我要替换的那个,是 2003 年编写的。我的黑匣子功能之一是启动一个程序。就是这样:

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

所以我尝试在 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

我可以设置所有有效的标题。然后,只要它是唯一的,我就可以再次找到该任务并承担该任务,就好像我从一开始就开始了它一样。 我的问题是 VB6 shell 有 6 种启动窗口的模式,而 .Net 没有。我试图模仿其中的一些,但将 startinfo 窗口样式设置为最小化不起作用。经过一番谷歌搜索后,看起来如果您正在启动 cmd.exe,它会忽略“提示”。很多帖子都是关于隐藏窗口的,因此修复将 CreateWindow 设置为 false。好吧,我想要一个窗口,只需最小化到任务栏。如果有人说简单的话,我会把它留在这个线程上。另外我会做更多的谷歌,但如果我在这方面找不到任何东西,我会开始一个新的线程。 现在我将其保持打开状态,以便将其全部放在一个位置,但看起来我使用了修复的窗口标题。

【问题讨论】:

  • 您是否正在为批处理文件设置窗口标题?
  • 如何启动批处理文件?您可以执行类似start cmd /c %YourBatchFile% 的操作,这将启动批处理文件一个新的cmd 进程(和窗口),该进程将cmd /c %YourBatchFile% 作为命令行。
  • @Squashman,不,但这是一个想法。我不认为这是一个启动属性,但是我确实有一个 win api。我希望有一个任务的标签属性。让我看看其他一些建议,我会回来的。
  • @CristiFati,我想过这个问题。通过指定 cmd 和路径,我可以切换到 UseShellExecute=False。缺点是我希望任务有自己的窗口。我可以使用环境变量来传递标签的好处。我尝试设置一个,但任务似乎没有拿起它。但是,如果我查看计算机-> 属性,它就在那里。我的批处理文件中有一个“set”命令来查看有哪些变量,但我没有看到它。我有一个 VB6 程序,用来做我正在尝试的事情,我想我需要找到它并看看我如何处理它。谢谢你和壁球侠。
  • 在您的批处理文件中使用TITLE 命令,或者如果您使用cmd.exe 来START 批处理文件,您也可以指定窗口标题。

标签: vb.net windows batch-file process


【解决方案1】:

底线.... 为了找到我启动的现有应用程序,但由于启动它的应用程序本身重新启动而成为孤立应用程序,我选择了窗口标题。所以规则是,这个应用管理的所有窗口标题都必须是唯一的。

更多细节.... 我想要一个程序来管理程序列表,我称之为服务,但它们不是真正的窗口服务,它们只是普通程序和批处理文件,如果它们停止,它们将重新启动。我使用了一个窗口应用程序,这样我就可以有某种 GUI 来启动/停止,如果一个程序被声明为隐藏,它可以变得可见。所以我创建了一个类来跟踪所需的信息(clsServiceList),然后将其添加到调用 lstServices 的列表中(lstServices = new list(of clsServiceList))。有两个主要子“ServiceUpdate”和“StartService”。调用 ServiceUpdate 后,lstServices 的所有状态(属性)都应该是最新的。这可以在启动时调用以查找 orphen 任务,或者每隔几秒钟调用一次以查看是否需要重新启动。作为该线程的一部分,是找到一种方法来设置窗口标题,然后管理窗口样式。所以这里是代码,如果我需要添加它,请告诉我。谢谢大家的帮助。

    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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-30
    • 2010-10-14
    • 1970-01-01
    • 2021-11-23
    • 2021-05-28
    • 2022-10-24
    • 1970-01-01
    • 2012-04-04
    相关资源
    最近更新 更多