MyInstaller _installer = BackgroundWorker _installerBGWorker = _installer </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> MyInstaller();
_installerBGWorker.WorkerReportsProgress </span>= <span style="color: #0000ff">true</span><span style="color: #000000">;
_installerBGWorker.WorkerSupportsCancellation </span>= <span style="color: #0000ff">true</span><span style="color: #000000">;
_installerBGWorker.DoWork </span>+=<span style="color: #000000"> _installerBGWorker_DoWork;
_installerBGWorker.RunWorkerCompleted </span>+=<span style="color: #000000"> _installerBGWorker_RunWorkerCompleted;
_installerBGWorker.ProgressChanged </span>+=<span style="color: #000000"> _installerBGWorker_ProgressChanged;
</span><span style="color: #0000ff">this</span>.Shown +=<span style="color: #000000"> InstallProcessForm_Shown;
}
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> InstallProcessForm_Shown(<span style="color: #0000ff">object</span><span style="color: #000000"> sender,EventArgs e)
{
</span><span style="color: #008000">//</span><span style="color: #008000"> 当窗口打开后就开始后台的安装</span>
<span style="color: #000000"> _installerBGWorker.RunWorkerAsync();
}
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> _installerBGWorker_ProgressChanged(<span style="color: #0000ff">object</span><span style="color: #000000"> sender,ProgressChangedEventArgs e)
{
</span><span style="color: #008000">//</span><span style="color: #008000"> 消息通过 e.UserState 传回,并通过label显示在窗口上</span>
<span style="color: #0000ff">string</span> message =<span style="color: #000000"> e.UserState.ToString();
</span><span style="color: #0000ff">this</span>.label1.Text =<span style="color: #000000"> message;
</span><span style="color: #0000ff">if</span> (message == <span style="color: #800000">"</span><span style="color: #800000">正在取消安装 ...</span><span style="color: #800000">"</span><span style="color: #000000">)
{
</span><span style="color: #0000ff">this</span>.CancelButton.Enabled = <span style="color: #0000ff">false</span><span style="color: #000000">;
}
}
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> _installerBGWorker_RunWorkerCompleted(<span style="color: #0000ff">object</span><span style="color: #000000"> sender,RunWorkerCompletedEventArgs e)
{
</span><span style="color: #008000">//</span><span style="color: #008000"> 安装过程结束</span>
<span style="color: #000000"> }
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> _installerBGWorker_DoWork(<span style="color: #0000ff">object</span><span style="color: #000000"> sender,DoWorkEventArgs e)
{
BackgroundWorker bgWorker </span>= sender <span style="color: #0000ff">as</span><span style="color: #000000"> BackgroundWorker;
</span><span style="color: #008000">//</span><span style="color: #008000"> 开始执行安装方法</span>
_installer = <span style="color: #0000ff">new</span><span style="color: #000000"> MyInstaller();
</span><span style="color: #0000ff">string</span> msiFilePath = <span style="color: #800000">"</span><span style="color: #800000">xxx.msi</span><span style="color: #800000">"</span>; <span style="color: #008000">//</span><span style="color: #008000"> msi file path</span>
<span style="color: #000000"> _installer.Install(bgWorker,msiFilePath);
}
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> CancelButton_Click(<span style="color: #0000ff">object</span><span style="color: #000000"> sender,EventArgs e)
{
_installer.Canceled </span>= <span style="color: #0000ff">true</span><span style="color: #000000">;
_installerBGWorker.CancelAsync();
}
}
MyInstaller.cs
<span style="color: #0000ff">internal <span style="color: #0000ff">class<span style="color: #000000"> MyInstaller
{
<span style="color: #0000ff">private BackgroundWorker _bgWorker = <span style="color: #0000ff">null<span style="color: #000000">;
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Canceled { <span style="color: #0000ff">get</span>; <span style="color: #0000ff">set</span><span style="color: #000000">; }
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Install(BackgroundWorker bgWorker,<span style="color: #0000ff">string</span><span style="color: #000000"> msiFileName)
{
_bgWorker </span>=<span style="color: #000000"> bgWorker;
NativeMethods.MyMsiInstallUIHandler oldHandler </span>= <span style="color: #0000ff">null</span><span style="color: #000000">;
</span><span style="color: #0000ff">try</span><span style="color: #000000">
{
</span><span style="color: #0000ff">string</span> logPath = <span style="color: #800000">"</span><span style="color: #800000">test.log</span><span style="color: #800000">"</span><span style="color: #000000">;
NativeMethods.MsiEnableLog(NativeMethods.LogMode.Verbose,logPath,</span><span style="color: #800080">0u</span><span style="color: #000000">);
NativeMethods.MsiSetInternalUI(</span><span style="color: #800080">2</span><span style="color: #000000">,IntPtr.Zero);
oldHandler </span>= NativeMethods.MsiSetExternalUI(<span style="color: #0000ff">new</span><span style="color: #000000"> NativeMethods.MyMsiInstallUIHandler(MsiProgressHandler),NativeMethods.LogMode.ExternalUI,IntPtr.Zero);
</span><span style="color: #0000ff">string</span> param = <span style="color: #800000">"</span><span style="color: #800000">ACTION=INSTALL</span><span style="color: #800000">"</span><span style="color: #000000">;
_bgWorker.ReportProgress(</span><span style="color: #800080">0</span>,<span style="color: #800000">"</span><span style="color: #800000">正在安装 xxx ...</span><span style="color: #800000">"</span><span style="color: #000000">);
NativeMethods.MsiInstallProduct(msiFileName,param);
}
</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e)
{
</span><span style="color: #008000">//</span><span style="color: #008000"> todo</span>
<span style="color: #000000"> }
<span style="color: #0000ff">finally<span style="color: #000000">
{
<span style="color: #008000">//<span style="color: #008000"> 一定要把默认的handler设回去。
<span style="color: #0000ff">if(oldHandler != <span style="color: #0000ff">null<span style="color: #000000">)
{
NativeMethods.MsiSetExternalUI(oldHandler,NativeMethods.LogMode.None,IntPtr.Zero);
}
}
}
</span><span style="color: #008000">//</span><span style="color: #008000">最重要的就是这个方法了,这里仅演示了如何cancel一个安装,更多详情请参考MSDN文档</span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> MsiProgressHandler(IntPtr context,<span style="color: #0000ff">int</span> messageType,<span style="color: #0000ff">string</span><span style="color: #000000"> message)
{
</span><span style="color: #0000ff">if</span> (<span style="color: #0000ff">this</span><span style="color: #000000">.Canceled)
{
</span><span style="color: #0000ff">if</span> (_bgWorker != <span style="color: #0000ff">null</span><span style="color: #000000">)
{
_bgWorker.ReportProgress(</span><span style="color: #800080">0</span>,<span style="color: #800000">"</span><span style="color: #800000">正在取消安装 ...</span><span style="color: #800000">"</span><span style="color: #000000">);
}
</span><span style="color: #008000">//</span><span style="color: #008000"> 这个返回值会告诉msi,cancel当前的安装</span>
<span style="color: #0000ff">return</span> <span style="color: #800080">2</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">return</span> <span style="color: #800080">1</span><span style="color: #000000">;
}
}
<span style="color: #0000ff">internal <span style="color: #0000ff">static <span style="color: #0000ff">class<span style="color: #000000"> NativeMethods
{
[DllImport(<span style="color: #800000">"<span style="color: #800000">msi.dll<span style="color: #800000">",CharSet =<span style="color: #000000"> CharSet.Auto)]
<span style="color: #0000ff">internal <span style="color: #0000ff">static <span style="color: #0000ff">extern <span style="color: #0000ff">int MsiSetInternalUI(<span style="color: #0000ff">int<span style="color: #000000"> dwUILevel,IntPtr phWnd);
[DllImport(</span><span style="color: #800000">"</span><span style="color: #800000">msi.dll</span><span style="color: #800000">"</span>,CharSet =<span style="color: #000000"> CharSet.Auto)]
</span><span style="color: #0000ff">internal</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">extern</span><span style="color: #000000"> MyMsiInstallUIHandler MsiSetExternalUI([MarshalAs(UnmanagedType.FunctionPtr)] MyMsiInstallUIHandler puiHandler,NativeMethods.LogMode dwMessageFilter,IntPtr pvContext);
[DllImport(</span><span style="color: #800000">"</span><span style="color: #800000">msi.dll</span><span style="color: #800000">"</span>,CharSet =<span style="color: #000000"> CharSet.Auto)]
</span><span style="color: #0000ff">internal</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">extern</span> <span style="color: #0000ff">uint</span> MsiInstallProduct([MarshalAs(UnmanagedType.LPWStr)] <span style="color: #0000ff">string</span> szPackagePath,[MarshalAs(UnmanagedType.LPWStr)] <span style="color: #0000ff">string</span><span style="color: #000000"> szCommandLine);
[DllImport(</span><span style="color: #800000">"</span><span style="color: #800000">msi.dll</span><span style="color: #800000">"</span>,CharSet =<span style="color: #000000"> CharSet.Auto)]
</span><span style="color: #0000ff">internal</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">extern</span> <span style="color: #0000ff">uint</span> MsiEnableLog(NativeMethods.LogMode dwLogMode,<span style="color: #0000ff">uint</span><span style="color: #000000"> dwLogAttributes);
</span><span style="color: #0000ff">internal</span> <span style="color: #0000ff">delegate</span> <span style="color: #0000ff">int</span> MyMsiInstallUIHandler(IntPtr context,[MarshalAs(UnmanagedType.LPWStr)] <span style="color: #0000ff">string</span><span style="color: #000000"> message);
[Flags]
</span><span style="color: #0000ff">internal</span> <span style="color: #0000ff">enum</span> LogMode : <span style="color: #0000ff">uint</span><span style="color: #000000">
{
None </span>= <span style="color: #800080">0u</span><span style="color: #000000">,Verbose </span>= <span style="color: #800080">4096u</span><span style="color: #000000">,ExternalUI </span>= <span style="color: #800080">20239u</span><span style="color: #000000">
}
}