首页 新闻 会员 周边 捐助

C#如何添加子进程并在任务管理中显示(Edge的多进程方式)

0
悬赏园豆:50 [待解决问题]

请问C#如何添加子进程并在任务管理中有显示,参考Edge的多进程例子:

这里这个Edge应用下有多个子进程,请问如何在C#中添加类似的进程并在任务管理器中显示出来。

lzhdim的主页 lzhdim | 小虾三级 | 园豆:584
提问于:2025-02-20 14:49
< > 人人可用的开源BI工具
分享
所有回答(3)
0

Winform无法实现,需要借用win api。


		[DllImport("user32.dll")]
		private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
		private Process childProcess;
		public Form1()
		{
			InitializeComponent();

		}
		private void button1_Click(object sender, System.EventArgs e)
		{
			// 启动一个新的子进程
			childProcess = new Process();
			childProcess.StartInfo.FileName = "cmd.exe";
			childProcess.StartInfo.UseShellExecute = false;
			childProcess.StartInfo.CreateNoWindow = true;  // 不显示CMD窗口

			// 启动进程
			childProcess.Start();

			// 等待进程启动完成
			//childProcess.WaitForInputIdle();

			// 将子进程附加到当前WinForms进程
			SetParent(childProcess.MainWindowHandle, this.Handle);
		}

喵咪咪喵喵喵 | 园豆:1664 (小虾三级) | 2025-02-20 16:01

有没有完整的解决方案代码?你上面那个MultiThreads(32位)就是多进程的吧???

请将解决方案代码发我邮箱,谢谢:

lzhdim@163.com

支持(0) 反对(0) lzhdim | 园豆:584 (小虾三级) | 2025-02-20 16:53

@lzhdim: 我就说你这个id怎么那么熟悉,我看过你很多篇文章!

支持(0) 反对(0) 喵咪咪喵喵喵 | 园豆:1664 (小虾三级) | 2025-02-20 17:28

试过SetParent,但是是在Winform里的,能嵌入到主窗体的Panel里,但是设置父子进程无效,所以来问问。。。

支持(0) 反对(0) lzhdim | 园豆:584 (小虾三级) | 2025-02-20 17:41

@echo_lovely: ChatGPT那个打不开,哈哈。。。

支持(0) 反对(0) lzhdim | 园豆:584 (小虾三级) | 2025-02-20 17:42

@lzhdim: 嵌入到主窗体Panel里的,我问GPT了,它回复我比较麻烦,我没有做测试

支持(0) 反对(0) 喵咪咪喵喵喵 | 园豆:1664 (小虾三级) | 2025-02-21 08:09

@lzhdim:
这是GPT回复我的代码,它尝试将记事本附加到winform:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MainForm : Form
{
    [DllImport("user32.dll")]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int Width, int Height, uint uFlags);

    const int SW_SHOWNORMAL = 1;

    private Process childProcess;

    public MainForm()
    {
        InitializeComponent();
    }

    private void btnStartProcess_Click(object sender, EventArgs e)
    {
        // 启动一个新的子进程
        childProcess = new Process();
        childProcess.StartInfo.FileName = "notepad.exe";
        childProcess.StartInfo.UseShellExecute = true;  // 使用Shell执行
        childProcess.StartInfo.CreateNoWindow = false;  // 显示Notepad窗口

        // 启动进程
        childProcess.Start();

        // 等待Notepad进程启动完成并获取窗口句柄
        childProcess.WaitForInputIdle();  // 这里需要等待Notepad进程准备好

        // 获取Notepad的主窗口句柄
        IntPtr notepadHandle = childProcess.MainWindowHandle;

        // 设置父窗口
        SetParent(notepadHandle, this.Handle);

        // 将Notepad窗口大小调整以适应父窗口
        SetWindowPos(notepadHandle, IntPtr.Zero, 0, 0, this.Width, this.Height, 0);

        // 显示Notepad窗口
        ShowWindow(notepadHandle, SW_SHOWNORMAL);
    }
}

我记得楼主你搞过很多这种windows api的项目啊,应该比较熟悉,我班门弄斧了

支持(0) 反对(0) 喵咪咪喵喵喵 | 园豆:1664 (小虾三级) | 2025-02-21 08:12

@echo_lovely: 周一好啊。。。我用的Windows 11 24H2,Windows 10下能用的那个API函数SetParent在24H2下不兼容了,无法实现多进程。。。

支持(0) 反对(0) lzhdim | 园豆:584 (小虾三级) | 2025-03-10 13:56
0

这个分组不是单纯的父子关系,看看这个
https://cloud.tencent.com/developer/article/2259513

www378660084 | 园豆:1457 (小虾三级) | 2025-02-21 11:41
0

嵌入窗体不是找pid,而是找窗体句柄。
如果你process里可以找到MainWindowHandle的,那个就是主窗体句柄
主意窗体必须可见才有这个,窗体不可见。你需要遍历所有顶级窗体,EnumWindows 然后通过GetWindowThreadProcessId去比对这个顶级窗体隶属于pid下(有时候还需要查询pid的层级,因为有时候这个顶级窗体可能属于某个exe的子进程里)
代码我就不贴全了,只贴核心的

public static IntPtr FindMainWindowByPid(int pid)
{

  IntPtr r = IntPtr.Zero;
  EnumWindows((hWnd, param) =>
  {


      GetWindowThreadProcessId(hWnd, out uint windowPid);
      if ((int)windowPid == pid && IsMainWindow(hWnd))
      {
          r = hWnd;
          return false;
      }
      else if (isChirldProcess(pid, windowPid.ToString()) && IsMainWindow(hWnd))
      {
          r = hWnd;
          return false;
      }


      return true;
  }, IntPtr.Zero);

  return r;

}

gihelo01 | 园豆:225 (菜鸟二级) | 2025-02-27 15:27

另外补充说明,如果进程不是你自己启动的。windows下未公开接收孤儿进程的手段。
我大体猜一下,通常想这么做是希望关闭的时候一起关闭。标准做法是使用job任务,把主进程和你嵌入的进程使用job关联到一起。
非标准做法就是自己在closing的时候,强行给对方发送关闭消息

支持(0) 反对(0) gihelo01 | 园豆:225 (菜鸟二级) | 2025-02-28 12:00

我这写的一个从指定进程下找指定窗体的:

/***

    进程工具类

    Austin Liu 刘恒辉
    Project Manager and Software Designer

    E-Mail: lzhdim@163.com
    Blog:   http://lzhdim.cnblogs.com
    Date:   2024-01-15 15:18:00

***/

namespace Lzhdim.LPF.Utility
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Text;

    /// <summary>
    /// 进程工具类
    /// </summary>
    public class ProcessUtil
    {
        #region Windows 32 API

        private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowTextLength(IntPtr hWnd);

        #endregion Windows 32 API

        /// <summary>
        /// 根据进程名查找底下的某个窗体
        /// </summary>
        /// <param name="processName">进程名</param>
        /// <param name="windowTitle">窗体名</param>
        /// <returns>该窗体的句柄</returns>
        public static IntPtr FindWindowHandleFormProcess(string processName, string windowTitle)
        {
            IntPtr intPtr = IntPtr.Zero;

            bool bIsFind = false;
            Process[] processes = Process.GetProcessesByName(processName); // 替换为实际进程名
            foreach (Process process in processes)
            {
                EnumChildWindows(process.MainWindowHandle, (hWnd, param) =>
                {
                    int length = GetWindowTextLength(hWnd);
                    if (length > 0)
                    {
                        StringBuilder sb = new StringBuilder(length);
                        GetWindowText(hWnd, sb, length + 1);
                        if (sb.ToString() == windowTitle)
                        {
                            intPtr = hWnd;
                            bIsFind = true;
                            return true;
                        }
                    }

                    return true;
                }, IntPtr.Zero);

                if (bIsFind) break;
            }

            return intPtr;
        }
    }
}

 

支持(0) 反对(0) lzhdim | 园豆:584 (小虾三级) | 2025-03-01 21:54
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册
Top