【问题标题】:C# GetProcessByName returning 1 Process when multiple are runningC#GetProcessByName 在多个运行时返回 1 个进程
【发布时间】:2017-11-03 19:33:59
【问题描述】:

我正在编写一个程序,让用户单击一个链接,该链接将打开一个信息路径表单并为他们自动填充一些字段。

但是,由于我无权访问表单源代码来查找字段变量名称,因此我必须通过将带有 SendKeys 的“\t”发送到表单来输入信息以到达相应的字段。这意味着窗口必须具有焦点。所以我用了:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SetForegroundWindow(IntPtr hWnd);

为了将窗口带到前面。出于某种原因,如果同一进程的多个窗口打开并且我尝试给予进程焦点,则 SetForegroundWindow 会抛出一个合适的结果......即使我自己创建了进程并确定我正在发送正确的窗口,它也会产生错误留言:

Process has exited, so the requested information is not available.

(这是我刚刚打开的进程。

基本上我的代码如下:

Process[] ps = Process.GetProcessByName("InfoPath");
if (ps.Length != 0)
{
    for(int i = 0; i < ps.Length; i ++)
        ps[i].Close();
}

Process infoPath = new Process();
infoPath.StartInfo.FileName = "InfoPath.exe";
infoPath.StartInfo.Arguments = "TemplateLocation.xsn";
infoPath.Start();

try{
    BringToFront(infoPath);
}catch (Exception e)
{
    // handle failure
}

SendKeys.SendWait("\t\t\t\t");
SendKeys.SendWait(information);

BringToFront 在哪里:

private void BringToFront(Process pTemp)
{
    try
    {
       SetForegroundWindow(pTemp.MainWindowHandle);
    }catch(Exception e)
    {
       //fails here saying that the process has exited, so the requested information is not available.
       throw e;
    }
}

我得到的问题是 GetProcessByName 只返回最近打开的 InfoPath 进程。即使我会运行 5 或 6 个,它也只会返回最近打开的一个并关闭它。

所以基本上我正在寻找两件事之一:

1) 获取 GetProcessByName 以实际返回 infopath 进程的完整列表

2) 当我向 SetForegroundWindow 发送我刚刚打开的进程时,了解它是如何失败的。

【问题讨论】:

  • 你应该使用Process.GetProcessesByName(注意复数)。 Process.GetProcessByName 没有定义,所以它让我相信你是手动输入的,可能还有其他错误。
  • @RonBeyer 是的.. 一个错字。

标签: c# process sendkeys


【解决方案1】:
  1. 如果您没有绑定到 GetProcessByName 并且可以使用 WMI,那么本主题可能会有所帮助:How do I find out what user owns what process programmatically?。基本上,使用查询“Select * from Win32_Process”来枚举所有进程并按可执行文件过滤。
  2. 显然,SetForegroundWindow 需要提升权限才能继续。您可以使用那里描述的方法:UAC Window On Top

【讨论】:

  • 谢谢!我会查一下,绝对不会绑定到 GetProcessesByName,只是我遇到的第一个似乎适合我的目的的东西!
【解决方案2】:

所以可能发生的是 infopath 为 UI 窗口生成一个新进程并且父进程退出。所以你立即打开 infopath.exe 但返回的进程 ID 不是最终的 UI 进程。如果您正在寻找特定的 UI 窗口,最好按窗口标题搜索。 User32.dll 有一个方法可以帮助你:

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(IntPtr className, string lpWindowName);

您可以将 IntPtr.Zero 传递给 className。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 2019-07-16
    • 2017-02-14
    • 2015-07-24
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    相关资源
    最近更新 更多