Sample for Multi-process C# app like Google Chrome

前端 未结 2 1195
谎友^
谎友^ 2020-12-30 12:41

Is Any body knows good sample for Multi-process C# app like Google Chrome.

Thanks for help.

相关标签:
2条回答
  • 2020-12-30 13:11

    Took me sooo long to get all the pieces put together, but here it is:

    The XAML:

    <Window x:Class="ProcessHoster.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ProcessHoster"
            xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel>
                <Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
            </StackPanel>
            <TabControl Grid.Row="1">
                <TabItem Header="Sample">
                    <WindowsFormsHost x:Name="test">
                        <wf:Panel Dock="Fill" x:Name="hostPanel" AutoSize="True" Resize="hostPanel_Resize" />
                    </WindowsFormsHost>
                </TabItem>
                <TabItem Header="Empty"/>
            </TabControl>
        </Grid>
    </Window>
    

    The code-behind

    // add references to 
    // System.Windows.Forms (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Windows.Forms.dll)
    // WindowsFormsIntegration (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\WindowsFormsIntegration.dll)
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Windows;
    
    namespace ProcessHoster
    {
        public partial class MainWindow : Window
        {
            [DllImport("user32.dll")]
            private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
            [DllImport("user32.dll")]
            static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
            [DllImport("user32.dll")]
            public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
            [DllImport("user32.dll", SetLastError = true)]
            internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
    
            enum WindowLongFlags : int
            {
                GWL_STYLE = -16,
            }
    
            enum WindowStyles : uint
            {
                WS_CHILD = 0x40000000,
                WS_BORDER = 0x00800000,
                WS_DLGFRAME = 0x00400000,
                WS_THICKFRAME = 0x00040000,
                WS_CAPTION = WS_BORDER | WS_DLGFRAME,
            }
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                string exeName = Environment.GetCommandLineArgs()[1];
                var procInfo = new ProcessStartInfo(exeName);
                procInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(exeName);
                childProcess = Process.Start(procInfo);
                childProcess.EnableRaisingEvents = true;
                childProcess.Exited += (sndr, args) => Debug.WriteLine($"Process {((Process)sndr).Id.ToString()} Exited");
                while (childProcess.MainWindowHandle == IntPtr.Zero) { Thread.Yield(); }
                var style = GetWindowLong(childProcess.MainWindowHandle, (int)WindowLongFlags.GWL_STYLE);
                style &= ~(int)WindowStyles.WS_CAPTION & ~(int)WindowStyles.WS_THICKFRAME;
                style |= ((int)WindowStyles.WS_CHILD);
                SetWindowLong(childProcess.MainWindowHandle, (int)WindowLongFlags.GWL_STYLE, Convert.ToUInt32(style));
                while (SetParent(childProcess.MainWindowHandle, hostPanel.Handle) == IntPtr.Zero) { Thread.Yield(); }
                hostPanel_Resize(null, null);
            }
    
            Process childProcess;
    
            private void hostPanel_Resize(object sender, EventArgs e)
            {
                if (childProcess?.MainWindowHandle != null)
                    MoveWindow(childProcess.MainWindowHandle, 0, 0, hostPanel.Width, hostPanel.Height, true);
            }
        }
    }
    

    Launch it with the name of the EXE you want to host, for example:

    ProcessHoster.exe "C:\Windows\System32\notepad.exe"

    0 讨论(0)
  • 2020-12-30 13:23

    Useful blog post (with actual C# source code):

    • http://wyday.com/blog/2010/multi-process-c-sharp-application-like-google-chrome-using-named-pipes/

    Other related SO posts:

    • Chrome / IE8 multi-process design, is it possible in .NET?
    • Windows Forms application like Google Chrome with multiple processes
    0 讨论(0)
提交回复
热议问题