C# 显示任何进程,如模式窗口

C# 显示任何进程,如模式窗口,c#,.net,vb.net,C#,.net,Vb.net,MessageBox.Show显示一个窗口,在MessageBox窗口未关闭之前,单击主应用程序仍将使MessageBox窗口具有焦点,并使MessageBox窗口闪烁。TaskDialogAPI和的行为相同 如何为不同的进程(如process.Start(“notepad.exe”)?好的,这里有一个可行的解决方案: 使用以下代码启动流程: Process p = new Process("cmd"); p.Start(); p.WaitForExit(); 现在,在激活应用程序的事件处理程

MessageBox.Show
显示一个窗口,在
MessageBox
窗口未关闭之前,单击主应用程序仍将使
MessageBox
窗口具有焦点,并使
MessageBox
窗口闪烁。
TaskDialog
API和的行为相同


如何为不同的进程(如
process.Start(“notepad.exe”)

好的,这里有一个可行的解决方案:

使用以下代码启动流程:

Process p = new Process("cmd");
p.Start();
p.WaitForExit();
现在,在激活应用程序的事件处理程序(active)中,再次将焦点设置在流程上。您可以使用process.HasExited来验证您的进程是否仍在运行

注意:我还没有测试过它,但我认为它应该能让你接近它。

看这里:

简而言之,您可以使用“process.WaitForExit();”暂停执行,直到进程退出,但我认为这不会闪烁窗口或自动聚焦到该进程

如果你想要更丰富的用户界面,你必须这样做:

while (!process.HasExited)
{
    //update UI
}
为了将焦点转移到另一个流程,您应该开始了

编辑:
有关闪烁窗口的更多信息。

好的,这是我想到的,不是最好或最优雅的方式,也不包含任何错误处理,但我认为它是有效的

我在代码中所做的是创建一个带有面板控件的虚拟表单(Form2),并将EXE的父级分配给面板的句柄(InPtr)。我已经删除了窗体的边框,使它看起来尽可能的刷新,但是在EXE加载和正在调用的SetParent方法之间仍然有一个明显的闪烁

表格1代码 表格2代码
这个黑客可能会成功。但是在使用这个之前一定要问自己两次

private void DoEvil()
{
    var windowField = typeof(Control).GetField("window", BindingFlags.Instance |
                            BindingFlags.NonPublic);

    Form notepad = new Form();
    NativeWindow window = (NativeWindow)windowField.GetValue(notepad);
    var process = Process.Start("notepad.exe");
    process.EnableRaisingEvents = true;

    while (process.MainWindowHandle == IntPtr.Zero)
    {
        Thread.Sleep(1);
    }

    window.AssignHandle(process.MainWindowHandle);
    Control.CheckForIllegalCrossThreadCalls = false;

    EventHandler handler = (s, ev) => notepad.DialogResult = DialogResult.OK;
    process.Exited += handler;
    notepad.ShowDialog(this);
    process.Exited -= handler;
    Control.CheckForIllegalCrossThreadCalls = true;
}

警告:不要在家里、办公室或任何地方尝试此操作:p

据我所知,这是不可能的,因为您启动的流程可以是任何内容,并且并不总是代表窗口。但是,您可以使用Process.WaitForExit和Process.HasExited来确定进程是否仍在运行(并且您可以阻止应用程序执行任何操作,直到调用的进程停止)。您尝试过类似的方法吗?@MPatel会阻止GUI线程,因为
WaitForExit()
只会使线程休眠。而不是MessageBox提供的行为。单击主应用程序将不会发生任何事情。的确,但它不会模仿flash行为。我希望最终我得到了它,请检查我的新答案。在发布答案之前,你应该阅读原始帖子下方的评论……。感谢你的努力,但这太疯狂了。:)(尝试调整/移动子窗口的大小)。一定有一些简单的事情。。。类似于ShowDialog的功能works@Zuck,同意,但我还不知道是什么,在哪里。找到它的那一刻,我将更新代码。我正试图理解dotPeek/Reflector/JustDecompile中的ShowDialog函数。在任何代码进入生产之前,我都会对其进行三次提问=pBtw,即使在我关上它们之后,邪恶的记事本还是神秘地出现了。记事本启示录!说真的,我建议大家不要使用这个代码。对我来说,它不是这样的,也许你应该检查一下,你只需要调用一次这个邪恶的代码。不管怎样,我玩得很开心,喜欢你的问题+1。你介意我问一下为什么会有这种奇怪的要求吗?我不是在用这个命令运行记事本,一些CMD/K命令。我正在考虑为此制作一个表单,以便将CMD输出重定向到表单。但是我没有完全理解你的代码。
public partial class Form2 : Form
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    [DllImport("user32.dll")]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);

    private readonly BackgroundWorker worker = new BackgroundWorker();
    private IntPtr mainHandle;
    private IntPtr processHandle;
    private Panel panel;

    public Form2()
    {
        InitializeComponent();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        FormBorderStyle = FormBorderStyle.None;
        StartPosition = FormStartPosition.CenterParent;
        AddPanel();
    }

    private void AddPanel()
    {
        panel = new Panel {Dock = DockStyle.Fill};
        mainHandle = panel.Handle;
        Controls.Add(panel);
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        worker.RunWorkerAsync();
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Invoke((MethodInvoker) Close);
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        var process = Process.Start("cmd.exe", "/k echo echo");
        if (process != null)
        {
            while (process.MainWindowHandle == IntPtr.Zero)
            {
                // Add some sort of timeout here, infintite loops are bad!!!
            }

            processHandle = process.MainWindowHandle;

            // Get the size of the EXE window and apply it to this form.
            var size = GetSize(processHandle);
            Invoke((MethodInvoker) delegate { Size = new Size(size.Width, size.Height);});

            // Hook the parent of the EXE window to this form
            SetHandle(processHandle);

            // Make sure the windows is positions at location x = 0, y = 0 of this form
            SetWindowPos(processHandle, IntPtr.Zero, 0, 0, size.Width, size.Height, SetWindowPosFlags.SWP_ASYNCWINDOWPOS);

            // wait for the EXE to terminate
            process.WaitForExit();

            // Unhook the closed process window
            SetParent(processHandle, IntPtr.Zero);
        }
    }

    private void SetHandle(IntPtr ptr)
    {
        if (ptr != IntPtr.Zero)
            SetParent(processHandle, mainHandle);
    }

    private static Size GetSize(IntPtr hWnd)
    {
        RECT pRect;
        var size = new Size();
        GetWindowRect(hWnd, out pRect);
        size.Width = pRect.Right - pRect.Left;
        size.Height = pRect.Bottom - pRect.Top;
        return size;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    [Flags]
    private enum SetWindowPosFlags : uint
    {
        SWP_ASYNCWINDOWPOS = 0x4000,
        SWP_DEFERERASE = 0x2000,
        SWP_DRAWFRAME = 0x0020,
        SWP_FRAMECHANGED = 0x0020,
        SWP_HIDEWINDOW = 0x0080,
        SWP_NOACTIVATE = 0x0010,
        SWP_NOCOPYBITS = 0x0100,
        SWP_NOMOVE = 0x0002,
        SWP_NOOWNERZORDER = 0x0200,
        SWP_NOREDRAW = 0x0008,
        SWP_NOREPOSITION = 0x0200,
        SWP_NOSENDCHANGING = 0x0400,
        SWP_NOSIZE = 0x0001,
        SWP_NOZORDER = 0x0004,
        SWP_SHOWWINDOW = 0x0040,
    }
}
private void DoEvil()
{
    var windowField = typeof(Control).GetField("window", BindingFlags.Instance |
                            BindingFlags.NonPublic);

    Form notepad = new Form();
    NativeWindow window = (NativeWindow)windowField.GetValue(notepad);
    var process = Process.Start("notepad.exe");
    process.EnableRaisingEvents = true;

    while (process.MainWindowHandle == IntPtr.Zero)
    {
        Thread.Sleep(1);
    }

    window.AssignHandle(process.MainWindowHandle);
    Control.CheckForIllegalCrossThreadCalls = false;

    EventHandler handler = (s, ev) => notepad.DialogResult = DialogResult.OK;
    process.Exited += handler;
    notepad.ShowDialog(this);
    process.Exited -= handler;
    Control.CheckForIllegalCrossThreadCalls = true;
}