25

我正在使用以下代码启动一个可执行文件:

Process proc = new Process();
proc.StartInfo.FileName = executablePath;
proc.Start();
proc.WaitForInputIdle();

在这个调用之后proc.Id它给了我一些整数,这不是真正的进程 ID。在任务管理器中,此进程有另一个 ID,而且我正在使用 MS UI 自动化访问此应用程序,它也返回与任务管理器中相同的 ID。所以我的问题是如何获得已启动进程的真实进程 ID?

更新

我发现在 Windows 7 上它可以正常工作并返回正确的 ID,但在 Windows XP 上却不行。可能是什么原因?

设想

应用场景如下。我有一个正在运行的嵌入式 HTTP 服务器,它不是由我实现的(这里是源代码)。客户端连接到 Web 服务器并发送运行程序的请求。在我的服务器的请求处理程序中,我只是Process.start()用来启动请求的应用程序。作为一个 Web 服务器,该程序为连接到它的每个客户端会话创建线程(我假设是这样,因为我没有编写它)。这能以某种方式帮助识别仅存在于 Windows XP X86 Service Pack 3 上的问题吗?

4

4 回答 4

24

我是如何做到的一个例子:

    bool started = false;
    var p = new Process();

    p.StartInfo.FileName = "notepad.exe";

    started = p.Start();

    try {
      var procId = p.Id;
      Console.WriteLine("ID: " + procId);
    }
    catch(InvalidOperationException)
    {
        started = false;
    }
    catch(Exception ex)
    {
        started = false;
    }

否则,请尝试使用这样的句柄:
使用处理程序
获取处理程序

hWnd = (int) process.MainWindowHandle;
int processId;
GetWindowThreadProcessId(hWnd, out processId);

[DllImport("user32")]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);

旁注:
如果您获取进程数组并遍历它们并比较 PID,会发生什么?

Process[] p = Process.GetProcessesByName( "testprogram" );
foreach(var proc in p)
    Console.WriteLine("Found: "+proc.Id == myExpectedProcId);
于 2012-10-15T09:02:20.470 回答
6

这:

using (Process process = Process.Start("notepad.exe"))
{
    process.WaitForInputIdle();
    Console.WriteLine(process.Id);
}

实际上对我有用:

http://pasteboard.s3.amazonaws.com/images/1350293463417532.png

任务管理器:

http://pasteboard.s3.amazonaws.com/images/1350293536498959.png

我的想法:

实际上,您的进程启动了另一个进程,并且正在尝试获取某种启动器的 ID。(顺便说一句,它可以自己启动)。

于 2012-10-15T09:30:12.883 回答
2

下面还返回一个进程的PID

Process[] p = Process.GetProcessesByName("YourProcessName");

现在您可以使用p[i].Id;

于 2012-10-15T09:39:36.980 回答
0

我只是想在这里猜测,因为如果没有看到真实的代码就很难理解真正发生的事情。无论如何,您在其中一条评论中提到了 Trthreads。您是否有可能在主线程中初始化一个 Process 类型的单个变量 proc,然后在另一个线程中启动该进程?

如果是这种情况,可能进程不止一次启动,而您只获得其中一个的 PID。我能够重现您的案例的唯一方法是:

     private Process proc;
     private List<int> pids = new List<int>();

     public void StartProc()
     {
         // this tries to simulate what you're doing. Starts the process, then 
         // wait to be sure that the second process starts, then kill proc
         proc.Start();
         pids.Add(proc.Id);
         Thread.Sleep(300);
         try
         {
             proc.Kill();
         }
         catch {}
     }
     // the method returns the PID of the process
     public int Test()
     {
         proc = new Process();
         proc.StartInfo.FileName = @"notepad.exe";
         for (int i = 0; i < 2; i++)
         {
             Thread t = new Thread(StartProc);
             t.Start();
             Thread.Sleep(200);
         }
         Thread.Sleep(500);
         return proc.Id;
     }

当您执行测试时,您应该会看到一个活动的记事本,并且该方法返回的 PID 与任务管理器显示的不同。但是如果你看一下 pids 列表,你应该看到任务管理器 PID 是列表中的第一个元素,而方法返回的那个是第二个。

你有没有可能做过类似的事情?

于 2012-10-15T10:13:21.337 回答