-
Notifications
You must be signed in to change notification settings - Fork 175
Tips'n'Tricks
public class ManagedBa : BootstrapperApplication
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
protected override void OnStartup(StartupEventArgs args)
{
SetProcessDPIAware(); // https://stackoverflow.com/a/44839778
Debug.Assert(false);
base.OnStartup(args);
}
Dedicated wiki page: https://github.com/oleg-shilo/wixsharp/issues/1173
Thanks to the fact that ManagedAction is implemented in a plain .NET assembly it can be debugged as easily as any other managed code. The most practical way of debugging is to put an assert statement and attach the debugger when prompted:
[CustomAction] public static ActionResult MyAction(Session session) { Debug.Assert(false); ...
Note, when attaching the debugger you need to ensure that you have your Visual Studio is running elevated. Otherwise, your VS debugger you may not be able to attach. When attaching, you will need to attach to the msiexec.exe process if you are debugging Managed UI and to rundll32.exe process if you are debugging a custom action.
Note: Normally you will have two msiexec.exe processes: one is the system Windows Installer service and another one is the active MSI session.
Some of the checking can be done by native MSI mechanisms (e.g. LaunchCondition
). However, you do not have much control over when the condition is evaluated if you want it to be done before the UI is displayed. You also have rather limited control over CPU architecture context. Thus implementing the condition checking with C# seems like a more versatile option.
It is also important to recognize that you will need to handle both types of installation: with and without UI. It seems to me that your task can be solved in a much easier way than it seems.
For "With UI" scenario place your C# routine in your earliest event which is UIInitialized
event.
For "Without UI" scenario place your C# reading routine in your earliest event that is Loaded
event.
If the target system does not meet the prerequisite conditions one of these events will detect it and prevent further installation. If the target system does meet the prerequisite conditions then both events will do the check and happily pass the execution flow further to the chain.
You can read more about event-driven WixSharp session architecture here. And this is the diagram that can help you to understand the order of the events:
Note, if you are using MSI native UI (or a third-party EmbeddedUI) you will not have WixSharp UI events UIInitialized
and UILoaded
fired.
In this case the only way to implement a universal generic checking is to use a bootstrapper with a single item (your msi) and the custom BA where you do your checking.
While it's possible (e.g. MultiLanguageSupport sample) it seems like a very over-engineered solution for such a simple task. Thus you may want to consider a very simple functional equivalent but without a hefty price tag - Self-executable_Msi. It does the same thing but for fraction of the cost.
If you are using stock BA application(s) then displaying MSI UI is done by setting the MSI package DisplayInternalUI
and using an appropriate BA application:
Show both standard BA and MSI UI:
new Bundle("MyProduct",
. . .
new MsiPackage(productMsi) { DisplayInternalUI = true });
bundle.Application = new LicenseBootstrapperApplication(. . .);
Show MSI UI but hide standard BA UI:
new Bundle("MyProduct",
. . .
new MsiPackage(productMsi) { . . .});
bundle.Application = new WixInternalUIBootstrapperApplication { . . . };
Show custom BA UI and MSI UI:
new Bundle("MyProduct",
. . .
new MsiPackage(productMsi)
{
Id = "MyProductPackageId"
});
bootstrapper.Application = new ManagedBootstrapperApplication("%this%") { . . . };
. . .
public class ManagedBA : mba.BootstrapperApplication
{
public ManagedBA(mba.IEngine engine, mba.IBootstrapperCommand command) : base(engine)
{
this.PlanMsiPackage += (s, e) =>
{
if (e.PackageId == "MyProductPackageId")
e.UiLevel = e.Action == ActionState.Uninstall ?
INSTALLUILEVEL.ProgressOnly :
INSTALLUILEVEL.Full;
};
this.Command = command;
}
See an interesting relevant discussion here: https://github.com/oleg-shilo/wixsharp/issues/1554
Based on #1526:
task: DotNetCoreCLI@2
displayName: 'Install wix as a dotnet tool -- dotnet tool install --global wix'
inputs:
command: custom
custom: tool
arguments: 'install --global wix'
If you are using managed UI then it's easy. You just need to remove the not needed dialog from the runtime dialog sequence.Just iterate through the all dialogs, find the one you want to skip and remove it.
If you want to do it before UI is displayed then you can do it from the UI Initialized event:
project.UIInitialized += e =>
{
if (needToSkip)
e.ManagedUI.Shell.Dialogs.RemoveAt(1); // remove Licence dialog
};
If you want to do it from a specific dialog then you do the same but from the dialog event handler. IE on next button click of a previous dialog
// WPF
public void GoNext()
{
if (needToSkip)
this.shell.Dialogs.RemoveAt(1); // remove Licence dialog
}
// WinForm
void next_Click(object sender, EventArgs e)
{
if (needToSkip)
this.Shell.Dialogs.RemoveAt(1); // remove Licence dialog
}
All WixSharp SDK assemblies are already signed. However, any other files included in the msi package may not be as normally it is a developer's responsibility to sign them. This can be assisted with WixSharp though. Thus by setting project.SignAllFiles
to true you can trigger signing the files included in the MSI just before assembling the msi file. And you can control some aspects of the signing process (e.g. which files to sign) via Compiler.SignAllFilesOptions
settings. See signing sample.
Compiler.SignAllFilesOptions.SkipSignedFiles = true;
...
project.DigitalSignature = new DigitalSignature
{
PfxFilePath = "wixsharp.pfx",
Password = "my_password",
Description = "MyProduct",
TimeUrl = new Uri("http://timestamp.verisign.com/scripts/timstamp.dll")
}
project.SignAllFiles = true;
- Home - Overview
- Architecture
- Documentation
- Samples Library
- Product Roadmap
- Tips'n'Tricks