How To: Update the bootstrapper to install a ClickOnce application using Internet Explorer
For completeness sake, I decided to add the postbuild step for using a modified bootstrapper to launch a ClickOnce deployment manifest (.application) file using Internet Explorer. As I detailed here , the original use for this change was to work-around a ClickOnce liimitation when attempting to install the app via Fire Fox. We have since discovered another use for this type of work-around: the bootstrapper may claim it can not find the .application file on a web server if the application file contains DBCS characters. By using the stub executable to launch Internet Explorer, the problem should be avoided.
The task works by re-defining what the
PublishOnly target does, replacing
_DeploymentGenerateBootstrapper with a new target,
CreateBootstrapper. This target is what calls
GenerateExtractedBootstrapper. Note that this task is conditioned to run only if the
IsWebBootstrapper property is true.
Without more ado, here are the steps necessary to get the modified bootstrapper up and running:
Download and install the binaries for post-build steps (see the attachment of this post)
Unload your project and edit the project file (via the project node's context menu)
Towards the bottom of the file, there should be a comment which starts with
To modify your build process. Immediately below the end of that comment, paste the following XML:
<Import Project="$(MSBuildExtensionsPath)\SetupProjects\SetupProjects.Targets" /> <PropertyGroup> <PublishOnlyDependsOn> SetGenerateManifests; PublishBuild; BeforePublish; GenerateManifests; CleanPublishFolder; _CopyFilesToPublishFolder; CreateBootstrapper; ResolveKeySource; _DeploymentSignClickOnceDeployment; AfterPublish </PublishOnlyDependsOn> </PropertyGroup> <Target Name="CreateBootstrapper"> <CallTarget Targets="_DeploymentGenerateBootstrapper" Condition="'$(IsWebBootstrapper)'!='true'" /> <CallTarget Targets="GenerateExtractedBootstrapper" Condition="'$(IsWebBootstrapper)'=='true' and '$(BootstrapperEnabled)'=='true'" /> </Target> <Target Name="GenerateExtractedBootstrapper"> <GenerateBootstrapper ApplicationFile="stub.exe" ApplicationName="$(AssemblyName)" ApplicationUrl="" BootstrapperItems="@(BootstrapperPackage)" ComponentsLocation="$(BootstrapperComponentsLocation)" ComponentsUrl="" Culture="$(TargetCulture)" FallbackCulture="$(FallbackCulture)" OutputPath="$(PublishDir)" SupportUrl="$(_DeploymentFormattedSupportUrl)" Path="$(GenerateBootstrapperSdkPath)" /> <GenerateExtractedBootstrapper ApplicationFile="$(TargetDeployManifestFileName)" ApplicationUrl="$(_DeploymentFormattedApplicationUrl)" BootstrapperFile="$(PublishDir)\setup.exe" ComponentsUrl="$(_DeploymentFormattedComponentsUrl)" OutputPath="$(PublishDir)" StubExe="$(MSBuildExtensionsPath)\SetupProjects\InstallApplication.exe" /> </Target>
Notice the steps are a little shorter than that for the setup project. That's because the necessary projects are already msbuild-based. One draw-back to this solution is that IExplorer will flash onto the screen when the bootstrapper is finished, at least until the file handler within Internet Explorer is able to take over. I do wonder if this could be avoided with smarter parameters to Internet Explorer (for example, how could you get the function call to re-use an existing Internet Explorer session).