如何在winform中使用UI托管控制台exe

时间:2011-10-14 09:15:43

标签: c# .net winforms

我正在开发一个具有一些特定要求的项目:我需要创建一个程序,它可以使用c#监视和运行其中的exe。但是,使用Console程序实际托管另一个exe的方法似乎没有尽头。所以我使用了WinForm。

我一直在寻找并找到一些非常好的解决方案,它在WinForm中托管一个UI应用程序。但在我的情况下,exe没有UI,但它能够创建UI(OpenGL),因此它不适用于那些解决方案。有没有办法在WinForm中托管这种exe?哪个我可以同时运行多个?

由于

3 个答案:

答案 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用于您可以嵌入的开源终端模拟器。