Introduction
This article introduces a way to host an EXE in a WPF window. To make the code easy to reuse, it is set into
a WPF user control and also implements the IDisposable
interface. A test WPF window app is added as a test project.
Background
As a development request I needed to embed a wPython Python edit and compare tool, built by me, into
a newly developed WPF application. With the magic power of search engines,
I found an article in CodeProject on embedding an EXE into a WinForms program. It's needed to make several changes to become a new WPF control. I also added
the
IDisposable
interface to improve the resource control ability. The links
to the reference articles are listed here:
Using the code
To use the control,
we only need to specify the full path of the executable to be embedded and when to dispose it.
appControl.ExeName = "notepad.exe";
this.Unloaded += new RoutedEventHandler((s, e) => { appControl.Dispose(); });
How does it works
The embedded application is launched with its containing directory as
a working directory.
try
{
var procInfo = new System.Diagnostics.ProcessStartInfo(this.exeName);
procInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(this.exeName);
_childp = System.Diagnostics.Process.Start(procInfo);
_childp.WaitForInputIdle();
_appWin = _childp.MainWindowHandle;
}
catch (Exception ex)
{
Debug.Print(ex.Message + "Error");
}
Get the container WPF control's handle and set the embedded application's parent window to the container. Change the style for the embedded application.
var helper = new WindowInteropHelper(Window.GetWindow(this.AppContainer));
SetParent(_appWin, helper.Handle);
SetWindowLongA(_appWin, GWL_STYLE, WS_VISIBLE);
MoveWindow(_appWin, 0, 0, (int)this.ActualWidth, (int)this.ActualHeight, true);
The embedded application is disposed when the container is disposed.
if (!_isdisposed)
{
if (disposing)
{
if (_iscreated && _appWin != IntPtr.Zero && !_childp.HasExited)
{
_childp.Kill();
_appWin = IntPtr.Zero;
}
}
_isdisposed = true;
}
Points of Interest
Some of the embedded applications can't be closed as mentioned in the article: Hosting EXE Application in a WinForms project. So it is changed to use the
Process.Kill()
method to make sure the embedded application is closed.
Also the signature of SetWindowLongA
is changed a little as the previous one throws an error
in the VS2012 compiler.
History