Как разместить консольный exe с пользовательским интерфейсом в winform - PullRequest
3 голосов
/ 14 октября 2011

Я работаю над проектом с некоторыми конкретными требованиями: мне нужно создать программу, которая может отслеживать и запускать exe внутри него, используя c #.Тем не менее, подход к использованию консольной программы для размещения другого исполняемого файла, похоже, не имеет конца.Поэтому я использовал WinForm.

Я искал и нашел довольно неплохое решение, которое размещает приложение пользовательского интерфейса внутри WinForm.Но в моем случае исполняемый файл не имеет пользовательского интерфейса, но он способен создавать пользовательский интерфейс (OpenGL), поэтому он не применим для этих решений.Есть ли способ разместить такой exe-файл внутри WinForm?Что я могу запустить многие из них одновременно?

Спасибо

Ответы [ 3 ]

1 голос
/ 18 октября 2011

Спасибо за все ваши предложения. Тем не менее, я нашел другой способ получить правильное окно, созданное моей консольной программой, и поместить его в правильную форму win. Это довольно обман, хотя. Эта идея изначально взята из Window Tabifier из codeproject: http://www.codeproject.com/KB/cs/WindowTabifier.aspx. Поскольку у моего 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);
1 голос
/ 14 октября 2011

Хостинг процесса внутри другого не имеет смысла.Если вы хотите запустить exe-файл из другого, вы можете использовать System.thread.Process, и если этим процессам нужно взаимодействовать друг с другом, ну, WCF создан именно для этого.

0 голосов
/ 14 октября 2011

См. Можно ли зарегистрировать сообщение для cmd.exe в C # /. Net? для получения информации о том, как создать / подключить консоль.

Также посмотрите, например, Poderosa для эмулятора терминала с открытым исходным кодом, который вы можете встраивать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...