开发者

Sample for Multi-process C# app like Google Chrome

Is Any body knows good sample for Multi-process C# app like Googl开发者_如何转开发e Chrome.

Thanks for help.


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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜