C# GetProcessesByName 在多个 运行 时返回 1 个进程
C# GetProcessByName returning 1 Process when multiple are running
我正在编写一个程序,让用户单击 link,这将打开一个信息路径表单并为他们自动填充一些字段。
但是,由于我无法访问表单源代码来查找字段变量名称,因此我必须通过使用 SendKeys 向表单发送“\t”来输入信息以到达适当的字段。这意味着 window 必须有焦点。所以我用了:
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetForegroundWindow(IntPtr hWnd);
为了把window带到最前面。出于某种原因,如果同一进程的多个 windows 打开并且我尝试提供一个进程焦点,SetForegroundWindow 会抛出一个合适的......即使我自己创建了进程并确定我正在发送正确的 window,它会产生错误消息:
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 只是 return 最近打开的 InfoPath 进程。即使我有 5 或 6 个 运行,它 return 只是最近打开并关闭的一个。
所以基本上我正在寻找以下两件事之一:
1) 获取 GetProcessByName 实际上 return 信息路径进程的完整列表
或
2) 了解当我向 SetForegroundWindow 发送我刚刚打开的进程时它是如何失败的。
所以可能发生的事情是 infopath 为 UI window 生成一个新进程并且 parent 进程退出。所以你瞬间打开infopath.exe但是返回的进程ID并不是最终的UI进程。如果您希望获得特定的 UI window,最好按 window 标题搜索。 User32.dll 这里有一个方法可以帮助你:
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(IntPtr className, string lpWindowName);
您可以将 IntPtr.Zero 传递给 className。
- 如果您未绑定到 GetProcessByName 并且可以使用 WMI,那么此主题可能会有所帮助:How do I find out what user owns what process programmatically?。基本上,使用查询 "Select * from Win32_Process" 来枚举所有进程并按可执行文件进行过滤。
- 显然,SetForegroundWindow 需要提升权限才能继续。您可以使用此处描述的方法:UAC Window On Top
我正在编写一个程序,让用户单击 link,这将打开一个信息路径表单并为他们自动填充一些字段。
但是,由于我无法访问表单源代码来查找字段变量名称,因此我必须通过使用 SendKeys 向表单发送“\t”来输入信息以到达适当的字段。这意味着 window 必须有焦点。所以我用了:
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetForegroundWindow(IntPtr hWnd);
为了把window带到最前面。出于某种原因,如果同一进程的多个 windows 打开并且我尝试提供一个进程焦点,SetForegroundWindow 会抛出一个合适的......即使我自己创建了进程并确定我正在发送正确的 window,它会产生错误消息:
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 只是 return 最近打开的 InfoPath 进程。即使我有 5 或 6 个 运行,它 return 只是最近打开并关闭的一个。
所以基本上我正在寻找以下两件事之一:
1) 获取 GetProcessByName 实际上 return 信息路径进程的完整列表
或
2) 了解当我向 SetForegroundWindow 发送我刚刚打开的进程时它是如何失败的。
所以可能发生的事情是 infopath 为 UI window 生成一个新进程并且 parent 进程退出。所以你瞬间打开infopath.exe但是返回的进程ID并不是最终的UI进程。如果您希望获得特定的 UI window,最好按 window 标题搜索。 User32.dll 这里有一个方法可以帮助你:
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(IntPtr className, string lpWindowName);
您可以将 IntPtr.Zero 传递给 className。
- 如果您未绑定到 GetProcessByName 并且可以使用 WMI,那么此主题可能会有所帮助:How do I find out what user owns what process programmatically?。基本上,使用查询 "Select * from Win32_Process" 来枚举所有进程并按可执行文件进行过滤。
- 显然,SetForegroundWindow 需要提升权限才能继续。您可以使用此处描述的方法:UAC Window On Top