0

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

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

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

编辑

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

我使用了这篇文章中的代码示例,因为我只有 PID,但没有句柄。代码示例不返回任何标题。我检查了以下步骤

  1. ProcessID通过 WMI时没有返回任何标题。
  2. ParentProcessID 从 WMI 传递时返回父 exe 的正确标题。
  3. 当 form.hwnd 从另一个 exe 传递时,返回了子 exe 的正确标题。

看起来代码示例不适用于子 exe(我的 exe 是从另一个 exe 调用的,即我的 exe 是孩子,调用者是父母)。找到的句柄EnumCallBack不等于表单的句柄hWnd,这就是它不返回标题的原因。

4

4 回答 4

1

Thanks to MC ND for identifying WMI to be used and Evripidis

Here is a sample code to get command line arguments of all processes

    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

The query to get processes which have been passed ABCD in their command line arguments would be

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

To read more

Edit:

To get window/form title from ProcessID, i used source code from below article by Evripidis

Get window handlle (hWnd) from process ID

Here is the central idea

  1. Store all handles pertaining to a PID
  2. Get the text of the handle which is Visible and Top Level Window On Taskbar
于 2014-06-11T10:08:12.320 回答
0

询问 WMI

wmic process get name,commandline
于 2014-06-11T09:01:20.320 回答
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
);
于 2014-06-11T18:57:09.887 回答
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
于 2014-06-14T23:01:25.000 回答