我需要在默认浏览器中打开一个网站。然后我想在第二个屏幕上显示浏览器。因此,我尝试以下方法:
private void button1_Click(object sender, EventArgs e)
{
var externalApplication = new Process();
externalApplication.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
externalApplication.StartInfo.FileName = "http://www.example.com/";
externalApplication.Start();
externalApplication.WaitForInputIdle();
var handle = externalApplication.MainWindowHandle;
Console.Write(handle);
Program.MoveWindow(handle, 0, 0, 1500, 1, true);
}
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
现在我的问题是,WaitForInputIdle()
和MainWindowHandle()
似乎都不起作用。他们都扔了InvalidOperationException: No process is associated with this object
答案 0 :(得分:0)
我通过使用@Simon Mourier to get the parent
的答案获得父母句柄解决了这个问题并以这种方式更改代码:
private void OpenUrl(string url)
{
var oldProcessIds = Process.GetProcesses().Select(pr => pr.Id);
IntPtr handle = OpenApplication(url);
if (handle==IntPtr.Zero)
{
// Find out what Process is new
var processes = Process.GetProcesses();
var newProcess = processes.Where(pr => !oldProcessIds.Contains(pr.Id));
var parent = ParentProcessUtilities.GetParentProcess(newProcess.First().Handle);
Program.MoveWindow(parent.MainWindowHandle, 0, 500, 500, 300, true);
}
else
{
Program.MoveWindow(handle, 0, 0, 1500, 100, true);
}
}
private IntPtr OpenApplication(string application)
{
var externalApplication = new Process();
externalApplication.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
externalApplication.StartInfo.FileName = "http://www.example.com";
externalApplication.Start();
externalApplication.Refresh();
try
{
externalApplication.WaitForInputIdle();
return externalApplication.MainWindowHandle;
} catch
{
// Cannot get Handle. Application managaes multiple Threads
return IntPtr.Zero;
}
}
检索父级的代码:
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
// These members must match PROCESS_BASIC_INFORMATION
internal IntPtr Reserved1;
internal IntPtr PebBaseAddress;
internal IntPtr Reserved2_0;
internal IntPtr Reserved2_1;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
[DllImport("ntdll.dll")]
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
/// <summary>
/// Gets the parent process of the current process.
/// </summary>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess()
{
return GetParentProcess(Process.GetCurrentProcess().Handle);
}
/// <summary>
/// Gets the parent process of specified process.
/// </summary>
/// <param name="id">The process id.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(int id)
{
Process process = Process.GetProcessById(id);
return GetParentProcess(process.Handle);
}
/// <summary>
/// Gets the parent process of a specified process.
/// </summary>
/// <param name="handle">The process handle.</param>
/// <returns>An instance of the Process class or null if an error occurred.</returns>
public static Process GetParentProcess(IntPtr handle)
{
ParentProcessUtilities pbi = new ParentProcessUtilities();
int returnLength;
int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
if (status != 0)
return null;
try
{
return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
catch (ArgumentException)
{
// not found
return null;
}
}
说明:
在打开URL之前,程序会记住之前存在的进程。因此,在创建之后,可以抓住新流程。从进程中搜索父进程,该进程应该是主进程。然后,该进程的MainWindowHandle将移动窗口。
注意:的
到目前为止,这是一个“粗略”的第一个解决方案(更像是POC)。缺少错误处理例程,并乐观地假设没有其他进程同时启动。