识别传递特定命令行参数的进程/ exe

时间:2014-06-11 06:01:06

标签: shell process vb6 hwnd window-handles

有两个exes /程序根据命令行参数执行任务,我们称之为Profile。用户可以使用特定的配置文件运行这些exes的多个实例。

我们遇到的情况是,如果一个exe运行一个配置文件,另一个不应该使用相同的配置文件运行,或者一个exe不能使用相同的配置文件实例化两次。为此,我们需要识别具有相同配置文件的运行流程。

一种可能性是记录,但如果进程/ exe终止,它可能会失败。

修改

我需要通过向他/她显示进程'窗口/表单标题来通知用户。由于我的exes是基于表单的,因此每个进程都将根据配置文件拥有自己的标题。基于WMI的解决方案,作为我的答案发布,只能找到带有文件名的进程,WMI没有列出窗口/表单标题的任何功能,所以我决定使用Win32 API。

我使用Code sample from this post因为我只有PID而不是句柄。代码示例没有返回标题。我检查了以下步骤

  1. 通过WMI的ProcessID时未返回任何标题。
  2. ParentProcessID时返回了父exe的正确标题 来自WMI的通过。
  3. 当form.hwnd为时,返回了子exe的正确标题 从另一个exe。传递。
  4. 看起来代码示例不适用于子exe(我的exes是从另一个exe调用的,即我的exes是child,而调用者是parent)。 EnumCallBack找到的句柄不等于表单hWnd,这就是它没有返回标题的原因。

4 个答案:

答案 0 :(得分:1)

感谢MC ND识别要使用的WMI和Evripidis

以下是获取所有进程的命令行参数的示例代码

    Dim objWMIService, objProcess, colProcess
    Dim strComputer, strList

    strComputer = "."

    Set objWMIService = GetObject("winmgmts:" & _
          "{impersonationLevel=impersonate}!\\" & _
           strComputer & "\root\cimv2")

    Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process")

    For Each objProcess In colProcess
        Debug.Print objProcess.Name & " | " & objProcess.CommandLine
    Next

获取已在其命令行参数中传递ABCD的进程的查询将是

Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process " & _
                                         " Where CommandLine Like ""%ABCD%"" ")

阅读更多

修改:

要从ProcessID获取窗口/表单标题,我使用了以下文章中的源代码 Evripidis

Get window handlle (hWnd) from process ID

这是中心思想

  1. 存储与PID相关的所有句柄
  2. 获取 Visible 顶级窗口的句柄文本 在任务栏上

答案 1 :(得分:0)

询问WMI

wmic process get name,commandline

答案 2 :(得分:0)

通常,单个实例程序会创建互斥锁。如果它可以,那么没有其他实例正在运行。如果它不能切换到上一个实例的窗口,然后退出。

在vb6中,app对象具有PrevInstance属性,但这只会提醒您需要检查参数。

因此,请创建一个与您的个人资料同名的互斥锁。

CreateMutex
The CreateMutex function creates or opens a named or unnamed mutex object. 

HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,  // SD
  BOOL bInitialOwner,                       // initial owner
  LPCTSTR lpName                            // object name
);

答案 3 :(得分:0)

这里有一些代码(没有删节,它来自表单,所以你需要编辑它)。它列出了系统中每个窗口的所有内容。

它输出像这样(进入rtfedit)。级别是显示父子关系的缩进数。

Order   Level   WindowText  ClassName   HWnd    ParentHWnd  ProcessID   ParentProcessID ThreadID    ModuleNameHWin  EXENameProcess
1   0   «No Window Text 0»  msvb_lib_tooltips   133318  133318  1648    3876    1944    C:\Windows\system32\MSCOMCTL.OCX    VB6.EXE
2   0   «No Window Text 0»  msvb_lib_tooltips   133316  133318  1648    3876    1944    C:\Windows\system32\MSCOMCTL.OCX    VB6.EXE
3   0   «No Window Text 0»  msvb_lib_tooltips   198898  133318  1648    3876    1944    C:\Windows\system32\MSCOMCTL.OCX    VB6.EXE
4   0   «No Window Text 0»  msvb_lib_tooltips   133276  133318  1648    3876    1944    C:\Windows\system32\MSCOMCTL.OCX    VB6.EXE
5   0   «No Window Text 0»  tooltips_class32    8585400 133318  1648    3876    1944    C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe   VB6.EXE
6   0   «No Window Text 0»  tooltips_class32    7341130 133318  1648    3876    1944    C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe   VB6.EXE
7   0   MSCTFIME UI MSCTFIME UI 8127794 133318  3356    1500    3240    C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe   explorer.exe
8   0   Default IME IME 721516  133318  3356    1500    3240    «Not Available Error=0» explorer.exe
9   0   «No Window Text 0»  tooltips_class32    7340808 133318  3356    1500    3240    «Not Available Error=0» explorer.exe
10  0   «No Window Text 0»  ThumbnailStackClass 4457892 133318  3356    1500    3240    «Not Available Error=0» explorer.exe

这是代码

Sub mnuInsertWindowList_Click()
'    WindowChain = 0
    Dim hwnd As Long
        hwnd = GetTopWindow(0)
        If hwnd <> 0 Then
            AddChildWindows hwnd, 0
        End If
End Sub


Private Function AddChildWindows(ByVal hwndParent As Long, ByVal Level As Long) As String
      Dim gwfnhwnd As Long, X As Long, WT As String, CN As String, Length As Long, hwnd As Long, TID As Long, PID As Long, MN As String, Ret As Long, Parenthwnd As Long
        Static Order As Long
        Static FirstTime As Long
        Parenthwnd = hwndParent
        If Level = 0 Then
                        hwnd = hwndParent
        Else
            hwnd = GetWindow(hwndParent, GW_CHILD)
        End If
        Do While hwnd <> 0
                 WT = Space(512)
                  Length = GetWindowText(hwnd, WT, 508)
                  WT = Left$(WT, Length)
                  If WT = "" Then WT = Chr(171) & "No Window Text " & Err.LastDllError & Chr(187)
                  CN = Space(512)
                  Length = GetClassName(hwnd, CN, 508)
                  CN = Left$(CN, Length)
                  If CN = "" Then CN = "Error=" & Err.LastDllError


                  TID = GetWindowThreadProcessId(hwnd, PID)

                  MN = Space(512)
                  Length = GetWindowModuleFileName(hwnd, MN, 508)
                  If Length = 0 Then
                    MN = Chr(171) & "Not Available Error=" & Err.LastDllError & Chr(187)
                  Else
                    MN = Left$(MN, Length)
                  End If


                 Dim f As Long, sname As String, PList As String, PPID As Long
                 Dim hSnap As Long, proc As PROCESSENTRY32, Temp As String
                 hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
                 If hSnap = hNull Then Exit Function
                 proc.dwSize = LenB(proc)
                 ' Iterate through the processes
                 f = Process32First(hSnap, proc)
                 Do
                        If PID = proc.th32ProcessID Then
                            sname = StrZToStr(proc.szExeFile)
                            PPID = proc.th32ParentProcessID
                        End If
                        f = Process32Next(hSnap, proc)
                 Loop While f = 1
                  Order = Order + 1
'                  CStr(Order) & " HWnd=" & FormatNumber$(hwnd, 0, vbFalse, vbFalse, vbFalse) & " Parent HWnd=" & FormatNumber$(Parenthwnd, 0, vbFalse, vbFalse, vbFalse) & " Level=" & CStr(Level) & WT & " (" & CN & ")" & " PID=" & FormatNumber$(PID, 0, vbFalse, vbFalse, vbFalse) & " TID=" & FormatNumber$(TID, 0, vbFalse, vbFalse, vbFalse) & " Module Name:" & MN & " ExeName:" & sname & vbCrLf
                If FirstTime = 0 Then
                    txtNote.SelText = vbCrLf & "Order" & vbTab & "Level" & vbTab & "WindowText" & vbTab & "ClassName" & vbTab & "HWnd" & vbTab & "ParentHWnd" & vbTab & "ProcessID" & vbTab & "ParentProcessID" & vbTab & "ThreadID" & vbTab & "ModuleNameHWin" & vbTab & "EXENameProcess"
                    FirstTime = 1
                End If
                txtNote.SelText = vbCrLf & CStr(Order) & vbTab & CStr(Level) & vbTab & WT & vbTab & CN & vbTab & CStr(hwnd) & vbTab & CStr(Parenthwnd) & vbTab & CStr(PID) & vbTab & CStr(PPID) & vbTab & CStr(TID) & vbTab & MN & vbTab & sname

                  AddChildWindows hwnd, Level + 1
                  hwnd = GetWindow(hwnd, GW_HWNDNEXT)
        Loop
      End Function

这些是声明。

Public Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function GetWindowModuleFileName Lib "user32" Alias "GetWindowModuleFileNameA" (ByVal hwnd As Long, ByVal WinModule As String, StringLength As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Public Declare Function IsUserAnAdmin Lib "Shell32" () As Boolean

  Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
  Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal Handle As Long) As Long
  Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
 Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

 Private Declare Function GetVersionExA Lib "kernel32" _
     (lpVersionInformation As OSVERSIONINFO) As Integer



  Private Type PROCESSENTRY32
     dwSize As Long
     cntUsage As Long
     th32ProcessID As Long           ' This process
     th32DefaultHeapID As Long
     th32ModuleID As Long            ' Associated exe
     cntThreads As Long
     th32ParentProcessID As Long     ' This process's parent process
     pcPriClassBase As Long          ' Base priority of process threads
     dwFlags As Long
     szExeFile As String * 260 ' MAX_PATH
  End Type

  Private Type OSVERSIONINFO
     dwOSVersionInfoSize As Long
     dwMajorVersion As Long
     dwMinorVersion As Long
     dwBuildNumber As Long
     dwPlatformId As Long           '1 = Windows 95 2 = Windows NT
     szCSDVersion As String * 128
  End Type

   Private Const PROCESS_QUERY_INFORMATION = 1024
   Private Const PROCESS_VM_READ = 16
   Private Const MAX_PATH = 260
   Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
   Private Const SYNCHRONIZE = &H100000
  'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
   Private Const PROCESS_ALL_ACCESS = &H1F0FFF
   Private Const TH32CS_SNAPPROCESS = &H2&
   Private Const hNull = 0
   Private Const GW_CHILD = 5
   Private Const GW_HWNDNEXT = 2