C# 面板中的压井过程

C# 面板中的压井过程,c#,winforms,forms,process,handle,C#,Winforms,Forms,Process,Handle,我有一个Win Forms应用程序,其中我从另一个.exe文件启动一个进程,然后将其句柄属性设置为Win Form应用程序中的一个面板。这将产生Win Forms应用程序内部运行的其他应用程序的效果 以下是我如何做到这一点的: [DllImport("user32.dll", SetLastError = true)] static extern IntPtr SetParent(IntPtr hwc, IntPtr hwp); string exepath = "myProgram.exe"

我有一个Win Forms应用程序,其中我从另一个.exe文件启动一个进程,然后将其句柄属性设置为Win Form应用程序中的一个面板。这将产生Win Forms应用程序内部运行的其他应用程序的效果

以下是我如何做到这一点的:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hwc, IntPtr hwp);

string exepath = "myProgram.exe";
ProcessStartInfo p = new ProcessStartInfo(exepath);
process = Process.Start(p);
Thread.Sleep(500);  //sleep to allow program to start up properly        
SetParent(process.MainWindowHandle, pictureBox1.Handle); //then set the handle to give the effect of being run inside the win forms app
现在我知道我可以在FormClosed事件中调用process.Kill(),该事件会在该窗体关闭时终止该进程,但是如果我的Win form应用程序被强制退出,我将如何终止该进程?这可能吗

由于进程的句柄设置为Win Form应用程序中的一个面板,因此它不会显示在任务栏上,但如果未调用process.Kill(),它仍将继续运行,这在Win Form被强制关闭时发生。这意味着每次我都必须通过任务管理器将其关闭,这是一种痛苦

如果这是不可能的,我不会费心设置面板的手柄,我只会让它在一个新窗口中打开


感谢

为了确保应用程序一关闭(优雅地或强制地)您的子进程就被正确擦除,您可以使用

作业对象允许将进程组作为一个单元进行管理。工作 对象是可命名、安全、可共享的对象,用于控制 与之关联的进程的属性。进行的手术 在作业对象上影响与该作业对象关联的所有进程。 示例包括强制执行限制,如工作集大小和进程 优先级或终止与作业关联的所有进程


关于StackOverflow,有一个类似的问题,在C#中有一个详细的实现:

试试这段代码,我已经用了很长时间了:

public partial class Launcher : Form
{
    /// <summary>Collection of process. </summary>
    private Dictionary<IntPtr, Process> _processCollection = new Dictionary<IntPtr, Process>();

    #region DLL Import


    [DllImport("user32.dll")]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);


    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

    #endregion


    /// <summary>Default constructor. </summary>
    public Launcher()
    {
        InitializeComponent();

        try {
            FormClosing += Launcher_FormClosing;
            StartInstances();
        }
        catch (Exception ex) {
            MessageBox.Show(ex.Message);
        }
    }

    /// <summary>Starts the instances. </summary>
    private void StartInstances()
    {
        var path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
        var numberOfInstances = Int32.Parse(ConfigurationManager.AppSettings["NumerOfInstances"]);
        for (int i = 0; i < numberOfInstances; i++) {
            StartInstance(i, path);
        }
    }

    /// <summary>Starts an instance. </summary>
    private void StartInstance(int instanceId, string path)
    {
        Process proc = Process.Start(path + "\\foo.exe", instanceId.ToString());
        IntPtr handlerDocked = IntPtr.Zero;

        Panel panel = new Panel();
        panel.Size = new Size(flwPanel.Width / 3, flwPanel.Height / 2);
        flwPanel.Controls.Add(panel);

        do {
            try {
                proc.WaitForInputIdle(1000); //wait for the window to be ready for input;
                proc.Refresh();              //update process info
                if (proc.HasExited) {
                    return; //abort if the process finished before we got a handle.
                }
                handlerDocked = proc.MainWindowHandle;  //cache the window handle
            }
            catch {
                Thread.Sleep(500);
            }

        } while (handlerDocked == IntPtr.Zero);

        //hWndOriginalParent = SetParent(hWndDocked, panel1.Handle);
        SetParent(handlerDocked, panel.Handle);

        var docked = new DockedElement(handlerDocked, panel);

        panel.SizeChanged += new EventHandler(Panel_Resize);
        Panel_Resize(docked, new EventArgs());

        _processCollection.Add(handlerDocked, proc);
    }
    private void Panel_Resize(object sender, EventArgs e)
    {
        var docked = (DockedElement)sender;
        //Change the docked windows size to match its parent's size. 
        MoveWindow(docked.Handle, 0, 0, docked.Container.Width, docked.Container.Height, true);
    }

    /// <summary>Finallize instances. </summary>
    public void FinallizeInstances()
    {

        foreach (var docked in _processCollection) {
            docked.Value.Close();
        }
        _processCollection.Clear();
    }

    private void Launcher_FormClosing(object sender, FormClosingEventArgs e)
    {
        FinallizeInstances();
    }

    protected override void Dispose(bool disposing)
    {
        FinallizeInstances();

        if (disposing && (components != null)) {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
}
公共部分类启动器:表单
{
///过程的集合。
私有字典_processCollection=新字典();
#区域DLL导入
[DllImport(“user32.dll”)]
公共静态外部IntPtr SetParent(IntPtr hWndChild、IntPtr hwndnnewparent);
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部布尔移动窗口(IntPtr hWnd、intx、inty、intnwidth、intnheight、bool bRepaint);
#端区
///默认构造函数。
公共启动器()
{
初始化组件();
试一试{
FormClosing+=启动器\u FormClosing;
起始状态();
}
捕获(例外情况除外){
MessageBox.Show(例如Message);
}
}
///启动实例。
私有无效起始状态()
{
var path=System.IO.path.GetDirectoryName(Assembly.getExecutionGassembly().GetName().CodeBase);
var numberOfInstances=Int32.Parse(ConfigurationManager.AppSettings[“numberOfInstances]”);
对于(int i=0;i