【问题标题】:How to host an console exe with UI in winform如何在winform中使用UI托管控制台exe
【发布时间】:2011-10-14 09:15:43
【问题描述】:

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

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

谢谢

【问题讨论】:

  • 不确定在 WinForm 中“托管”它是什么意思?你的意思是你想让你的 WinForm 应用程序启动另一个 exe?
  • 是的。我需要在winform中运行一个exe。即使那个 exe 会生成一些其他的 UI,它仍然会在那个 winform 中。有可能吗?

标签: c# .net winforms


【解决方案1】:

在另一个进程中托管一个进程没有任何意义。如果你想从另一个启动一个 exe,你可以使用System.thread.Process,如果这些进程需要相互交互,那么 WCF 就是为此而生的。

【讨论】:

    【解决方案2】:

    感谢您的所有建议。但是,我确实找到了另一种方法来获取由我的控制台 exe 创建的正确窗口,并将其放入正确的 winform 中。不过,这确实是个骗局。 这个想法最初来自 codeproject 的 Window Tabifier:http://www.codeproject.com/KB/cs/WindowTabifier.aspx。由于我的 exe 没有进程的相应 UI。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);
    

    【讨论】:

      【解决方案3】:

      有关如何创建/附加到控制台的信息,请参阅 Is it possible to log message to cmd.exe in C#/.Net?

      另外,看看例如Poderosa 用于您可以嵌入的开源终端仿真器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-30
        • 2017-07-03
        • 1970-01-01
        相关资源
        最近更新 更多