我正在开发一个具有一些特定要求的项目:我需要创建一个程序,它可以使用c#监视和运行其中的exe。但是,使用Console程序实际托管另一个exe的方法似乎没有尽头。所以我使用了WinForm。
我一直在寻找并找到一些非常好的解决方案,它在WinForm中托管一个UI应用程序。但在我的情况下,exe没有UI,但它能够创建UI(OpenGL),因此它不适用于那些解决方案。有没有办法在WinForm中托管这种exe?哪个我可以同时运行多个?
由于
答案 0 :(得分:1)
在另一个过程中托管一个过程毫无意义。如果你想从另一个exe中启动一个exe,你可以使用System.thread.Process
,如果这些进程需要相互交互,那么WCF就是为此做的。
答案 1 :(得分:1)
感谢您的所有建议。但是,我确实找到了另一种方法来获取由我的控制台exe创建的正确的Window,并将其放入正确的winform中。尽管如此,这还是一个骗子。 这个想法最初来自codeproject:http://www.codeproject.com/KB/cs/WindowTabifier.aspx的Window Tabifier。因为我的exe没有相应的进程用户界面.WaitForInputIdle,我在Thread.Sleep(2000)上作弊跳过开始时间,并根据它的名称获取创建的控制台窗口。
图书馆导入:
public delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool EnumThreadWindows(int threadId, EnumWindowsProc callback, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
找到正确的打开窗口的一些方法
public IntPtr FindWindowInProcess(Process process, Func<string, bool> compareTitle)
{
IntPtr windowHandle = IntPtr.Zero;
foreach (ProcessThread t in process.Threads)
{
windowHandle = FindWindowInThread(t.Id, compareTitle);
if (windowHandle != IntPtr.Zero)
{
break;
}
}
return windowHandle;
}
private IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle)
{
IntPtr windowHandle = IntPtr.Zero;
EnumThreadWindows(threadId, (hWnd, lParam) =>
{
StringBuilder text = new StringBuilder(200);
GetWindowText(hWnd, text, 200);
if (compareTitle(text.ToString()))
{
windowHandle = hWnd;
return false;
}
else
{
windowHandle = FindChildWindow(hWnd, compareTitle);
if (windowHandle != IntPtr.Zero)
{
return false;
}
}
return true;
}, IntPtr.Zero);
return windowHandle;
}
private IntPtr FindChildWindow(IntPtr hWnd, Func<string, bool> compareTitle)
{
IntPtr windowHandle = IntPtr.Zero;
EnumChildWindows(hWnd, (hChildWnd, lParam) =>
{
StringBuilder text = new StringBuilder(200);
GetWindowText(hChildWnd, text, 200);
if (compareTitle(text.ToString()))
{
windowHandle = hWnd;
return false;
}
return true;
}, IntPtr.Zero);
return windowHandle;
}
最后,启动流程:
String fileName = "myexe.exe";
String dir = Path.GetDirectoryName(fileName);
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = fileName;
process.StartInfo.WorkingDirectory = dir;
process.Start();
// Wait for process to be created and enter idle condition
Thread.Sleep(5000);
IntPtr appWin = FindWindowInProcess(process, s => s.StartsWith("Built on"));
// Put it into this form
SetParent(appWin, this.Handle);
// Remove border and whatnot
SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
// Move the window to overlay it on this window
MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
答案 2 :(得分:0)
有关如何创建/附加到控制台的信息,请参阅Is it possible to log message to cmd.exe in C#/.Net?。
另外,看看例如Poderosa用于您可以嵌入的开源终端模拟器。