-
Notifications
You must be signed in to change notification settings - Fork 179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic custom UI sequence #1218
Comments
Yes, and it is in fact very easy. |
I've experimenting with sample in Custom_UI folder and could not figure out how to do this. Anyway.. just to be clear when I said upgrading, I meant when we install with newer build version. Thx |
You can detect if a product is installed via an upgrade code public class MsiHelper
{
private const uint ERROR_SUCCESS = 0;
private static class MsiWinApi
{
[DllImport("msi.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern uint MsiEnumRelatedProducts(string strUpgradeCode, int reserved, int iIndex, StringBuilder sbProductCode);
[DllImport("msi.dll", ExactSpelling = true)]
internal static extern IntPtr MsiGetActiveDatabase(IntPtr hInstall);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
internal static extern InstallState MsiGetComponentPath(string szProduct, string szComponent, [Out] StringBuilder lpPathBuf, ref int pcchBuf);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
internal static extern Int32 MsiGetProductInfo(string product, string property, [Out] StringBuilder valueBuf, ref Int32 len);
}
public static bool DetectInstallByUpgradeCode()
{
try
{
string upgradeCode = _session["UpgradeCode"];
//found related productCode for installation version
string productCode = GetRelatedProductCode(upgradeCode);
return !string.IsNullOrEmpty(productCode)
}
catch (Exception ex)
{
_session.LogMessage(ex.ToString());
}
return false;
}
private static string GetRelatedProductCode(string upgradeCode)
{
StringBuilder productCodeBuffer = new StringBuilder(38);
uint err = MsiWinApi.MsiEnumRelatedProducts(upgradeCode, 0, 0, productCodeBuffer);
if (err != ERROR_SUCCESS) throw new ArgumentException($"Can't found related products for UpgradeCode: {upgradeCode}");
return productCodeBuffer.ToString();
}
} |
Hi @Zerpico , Thx for your reply. Here's my use case:
AFAIK, this sequence is set prior to BuildMSI() and I want to know how to change it dynamically. Thx |
@serezlan //dialogs for install
project.ManagedUI.InstallDialogs
.Add(WixSharp.Forms.Dialogs.Welcome)
.Add(WixSharp.Forms.Dialogs.Licence)
.Add<CustomDialogs.MyCustomDialog>()
.Add(WixSharp.Forms.Dialogs.InstallDir)
.Add(WixSharp.Forms.Dialogs.Progress)
.Add(WixSharp.Forms.Dialogs.Exit);
//dialogs for modify and uninstall
project.ManagedUI.ModifyDialogs
.Add(WixSharp.Forms.Dialogs.MaintenanceType)
.Add(WixSharp.Forms.Dialogs.Features)
.Add(WixSharp.Forms.Dialogs.Progress)
.Add(WixSharp.Forms.Dialogs.Exit); You can create MyCustomDialog and when initializing the form, detect if product already installed and display or skip it public partial class MyCustomDialog : ManagedForm, IManagedDialog
{
public MyCustomDialog()
{
InitializeComponent();
this.Load += new System.EventHandler(this.MyCustomDialog_Load);
}
void MyCustomDialog_Load(object sender, EventArgs e)
{
banner.Image = Runtime.Session.GetResourceBitmap("WixUI_Bmp_Banner");
ResetLayout();
if (IsInstalledProduct())
{
Shell.GoNext();
}
}
//...
} But there is one problem with this solution. If you go to the previous step with the InstallDir step, you will open MyCustomDialog and it can immediately execute Shell.GoNext() if it detects that the product is installed |
@Zerpico is right, the key algorithm is to detect if you want to skip the dialog in the BTW you already have all information about prv version in the event argument: static void project_Load(SetupEventArgs e)
{
if (e.IsUpgradingInstalledVersion)
{
. . .
} Or in the dialog static class DialogsHistory
{
public static Type LastDialog;
}
...
public MyCustomDialog()
{
DialogsHistory.LastDialog = this.GetType(); // should implement it in "License Agreement" and "InstallDir" dialogs too
InitializeComponent();
this.Load += new System.EventHandler(this.MyCustomDialog_Load);
}
void MyCustomDialog_Load(object sender, EventArgs e)
{
banner.Image = Runtime.Session.GetResourceBitmap("WixUI_Bmp_Banner");
ResetLayout();
if (this.MsiRuntime.MsiSession.IsUpgradingInstalledVersion())
{
if(DialogsHistory.LastDialog = typeof(InstallDir))
Shell.GoPrev();
else
Shell.GoNext();
}
} As for that problem @Zerpico mentioned, it is enough for you to know what is you prev screen was and you can either call |
BTW you don't have to do skipping from the dialog. You can use Type LastDialog;
static void Project_UILoaded(SetupEventArgs e)
{
e.ManagedUI.OnCurrentDialogChanged += IManagedDialog obj) =>
{
var prevDialog = LastDialog;
LastDialog = obj.GetType();
if (obj.GetType() == typeof(MyCustomDialog)
{
if (prevDialog == typeof(InstallDir))
obj.Shell.GoPrev();
else
obj.Shell.GoNext();
}
};
} |
Hi @oleg-shilo , After reading your comment, I searched and found one sample with similar code in wixsharp sample and it works great. Thank you. |
- Issue #1244: The directory Id generated can be too long - Issue #1223: Non LegacyDummyDirAlgorithm creates C:\ProgramFilesFolder empty folder - Issue #1220: ElevatedManagedAction issue - Feature #1204: Feature - RegisterCom class to ease the registration of COM files - Issue #1203: SilentBootstrapperApplication - Issue #182 (extended solution): RegistrySearch has "Win64=no" when building x64 installers - Added Self-executable_Msi sample - Added WixBootstrapper_EmbeddedUI to demonstrate how to show managed UI if the bundled MSI - Added sample for customization of the stock Burn UI. Triggered by #1219 - Added sample for "Issue #1218: Dynamic custom UI sequence" - Resurrected setting user input from BA UI and passing it to the msi. RegistrySearch input is also retained. - Added validation for `Issue #1075: [FEAT] Add error if LaunchApplicationFromExitDialog using in common Project` error. - Fixed problem with RegKey being placed in the x86 root XML dir for the x64 project
Hi oleg-,
Is there a way to set UI sequence dynamically?
My use case is when user is doing fresh install then custom page is shown requesting additional info.
If user is upgrading then skip custom page.
I'm able to inject custom page but do not know how to do it dynamically.
Thx.
The text was updated successfully, but these errors were encountered: