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"
精彩评论