using System.Security.Principal;
using System.Windows.Media.Imaging;
using Caliburn.Micro;
using WixSharp;
using WixSharp.CommonTasks;
using WixSharp.UI.Forms;
using WixSharp.UI.WPF;
using WixToolset.Dtf.WindowsInstaller;
namespace Sai.RvKits_Setup
{
///
/// The standard ProgressDialog.
/// Follows the design of the canonical Caliburn.Micro View (MVVM).
/// See https://caliburnmicro.com/documentation/cheat-sheet
///
///
///
///
public partial class ProgressDialog : WpfDialog, IWpfDialog, IProgressDialog
{
///
/// Initializes a new instance of the class.
///
public ProgressDialog()
{
InitializeComponent();
}
///
/// This method is invoked by WixSharp runtime when the custom dialog content is internally fully initialized.
/// This is a convenient place to do further initialization activities (e.g. localization).
///
public void Init()
{
UpdateTitles(ManagedFormHost.Runtime.Session);
model = new ProgressDialogModel { Host = ManagedFormHost };
ViewModelBinder.Bind(model, this, null);
model.StartExecute();
}
///
/// Updates the titles of the dialog depending on what type of installation action MSI is performing.
///
/// The session.
public void UpdateTitles(ISession session)
{
if (session.IsUninstalling())
{
DialogTitleLabel.Text = "[ProgressDlgTitleRemoving]";
DialogDescription.Text = "[ProgressDlgTextRemoving]";
}
else if (session.IsRepairing())
{
DialogTitleLabel.Text = "[ProgressDlgTextRepairing]";
DialogDescription.Text = "[ProgressDlgTitleRepairing]";
}
else if (session.IsInstalling())
{
DialogTitleLabel.Text = "[ProgressDlgTitleInstalling]";
DialogDescription.Text = "[ProgressDlgTextInstalling]";
}
// `Localize` resolves [...] titles and descriptions into the localized strings stored in MSI resources tables
this.Localize();
}
ProgressDialogModel model;
///
/// Processes information and progress messages sent to the user interface.
/// This method directly mapped to the
/// .
///
/// Type of the message.
/// The message record.
/// The buttons.
/// The icon.
/// The default button.
///
public override MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton)
=> model?.ProcessMessage(messageType, messageRecord, CurrentStatus.Text) ?? MessageResult.None;
///
/// Called when MSI execution is complete.
///
public override void OnExecuteComplete()
=> model?.OnExecuteComplete();
///
/// Called when MSI execution progress is changed.
///
/// The progress percentage.
public override void OnProgress(int progressPercentage)
{
if (model != null)
model.ProgressValue = progressPercentage;
}
}
///
/// ViewModel for standard ProgressDialog.
/// Follows the design of the canonical Caliburn.Micro ViewModel (MVVM).
/// See https://caliburnmicro.com/documentation/cheat-sheet
///
///
internal class ProgressDialogModel : Caliburn.Micro.Screen
{
public ManagedForm Host;
ISession session => Host?.Runtime.Session;
IManagedUIShell shell => Host?.Shell;
public BitmapImage Banner => session?.GetResourceBitmap("WixSharpUI_Bmp_Banner").ToImageSource();
public bool UacPromptIsVisible => (!WindowsIdentity.GetCurrent().IsAdmin() && Uac.IsEnabled() && !uacPromptActioned);
public string CurrentAction { get => currentAction; set { currentAction = value; base.NotifyOfPropertyChange(() => CurrentAction); } }
public int ProgressValue { get => progressValue; set { progressValue = value; base.NotifyOfPropertyChange(() => ProgressValue); } }
bool uacPromptActioned = false;
string currentAction;
int progressValue;
public string UacPrompt
{
get
{
if (Uac.IsEnabled())
{
var prompt = session?.Property("UAC_WARNING");
if (prompt.IsNotEmpty())
return prompt;
else
return
"Please wait for UAC prompt to appear. " +
"If it appears minimized then activate it from the taskbar.";
}
else
return null;
}
}
public void StartExecute()
=> shell?.StartExecute();
public void Cancel()
{
if (shell.IsDemoMode)
shell.GoNext();
else
shell.Cancel();
}
public MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, string currentStatus)
{
switch (messageType)
{
case InstallMessage.InstallStart:
case InstallMessage.InstallEnd:
{
uacPromptActioned = true;
base.NotifyOfPropertyChange(() => UacPromptIsVisible);
}
break;
case InstallMessage.ActionStart:
{
try
{
//messageRecord[0] - is reserved for FormatString value
/*
messageRecord[2] unconditionally contains the string to display
Examples:
messageRecord[0] "Action 23:14:50: [1]. [2]"
messageRecord[1] "InstallFiles"
messageRecord[2] "Copying new files"
messageRecord[3] "File: [1], Directory: [9], Size: [6]"
messageRecord[0] "Action 23:15:21: [1]. [2]"
messageRecord[1] "RegisterUser"
messageRecord[2] "Registering user"
messageRecord[3] "[1]"
*/
if (messageRecord.FieldCount >= 3)
CurrentAction = messageRecord[2].ToString();
else
CurrentAction = null;
}
catch
{
//Catch all, we don't want the installer to crash in an attempt to process message.
}
}
break;
}
return MessageResult.OK;
}
public void OnExecuteComplete()
{
CurrentAction = null;
shell?.GoNext();
}
}
}