/// <summary> /// Gets a formatted Windows Installer error message in a specified language. /// </summary> /// <param name="errorRecord">Error record containing the error number in the first field, and /// error-specific parameters in the other fields.</param> /// <param name="culture">The locale for the message.</param> /// <returns>The message string, or null if the error message or locale is not found.</returns> /// <remarks><p> /// Error numbers greater than 2000 refer to MSI "internal" errors, and are always /// returned in English. /// </p></remarks> public static string GetErrorMessage(Record errorRecord, CultureInfo culture) { if (errorRecord == null) { throw new ArgumentNullException("errorRecord"); } int errorNumber; if (errorRecord.FieldCount < 1 || (errorNumber = (int)errorRecord.GetInteger(1)) == 0) { throw new ArgumentOutOfRangeException("errorRecord"); } string msg = Installer.GetErrorMessage(errorNumber, culture); if (msg != null) { errorRecord.FormatString = msg; msg = errorRecord.ToString((IFormatProvider)null); } return(msg); }
/// <summary> /// Gets a formatted Windows Installer error message in a specified language. /// </summary> /// <param name="errorRecord">Error record containing the error number in the first field, and /// error-specific parameters in the other fields.</param> /// <param name="culture">The locale for the message.</param> /// <returns>The message string, or null if the error message or locale is not found.</returns> /// <remarks><p> /// Error numbers greater than 2000 refer to MSI "internal" errors, and are always /// returned in English. /// </p></remarks> internal static string GetErrorMessage(Record errorRecord, CultureInfo culture) { if (errorRecord == null) { throw new ArgumentNullException("errorRecord"); } int errorNumber; if (errorRecord.FieldCount < 1 || (errorNumber = (int) errorRecord.GetInteger(1)) == 0) { throw new ArgumentOutOfRangeException("errorRecord"); } string msg = Installer.GetErrorMessage(errorNumber, culture); if (msg != null) { errorRecord.FormatString = msg; msg = errorRecord.ToString((IFormatProvider)null); } return msg; }
private void ProcessProgressMessage(Record progressRecord) { // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#. if (progressRecord == null || progressRecord.FieldCount == 0) { return; } int fieldCount = progressRecord.FieldCount; int progressType = progressRecord.GetInteger(1); string progressTypeString = String.Empty; switch (progressType) { case 0: // Master progress reset if (fieldCount < 4) { return; } this.progressPhase++; this.total = progressRecord.GetInteger(2); if (this.progressPhase == 1) { // HACK!!! this is a hack courtesy of the Windows Installer team. It seems the script planning phase // is always off by "about 50". So we'll toss an extra 50 ticks on so that the standard progress // doesn't go over 100%. If there are any custom actions, they may blow the total so we'll call this // "close" and deal with the rest. this.total += 50; } this.moveForward = (progressRecord.GetInteger(3) == 0); this.completed = (this.moveForward ? 0 : this.total); // if forward start at 0, if backwards start at max this.enableActionData = false; this.UpdateProgress(); break; case 1: // Action info if (fieldCount < 3) { return; } if (progressRecord.GetInteger(3) == 0) { this.enableActionData = false; } else { this.enableActionData = true; this.step = progressRecord.GetInteger(2); } break; case 2: // Progress report if (fieldCount < 2 || this.total == 0 || this.progressPhase == 0) { return; } if (this.moveForward) { this.completed += progressRecord.GetInteger(2); } else { this.completed -= progressRecord.GetInteger(2); } this.UpdateProgress(); break; case 3: // Progress total addition this.total += progressRecord.GetInteger(2); break; } }
/// <summary> /// Handler for external UI messages. /// </summary> /// <param name="messageType">The type of message.</param> /// <param name="messageRecord">The message details.</param> /// <param name="buttons">Buttons to show (unused).</param> /// <param name="icon">The icon to show (unused).</param> /// <param name="defaultButton">The default button (unused).</param> /// <returns>How the message was handled.</returns> public MessageResult UIRecordHandler( InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { #if False Console.WriteLine("Message type {0}: {1}", messageType.ToString(), this.session.FormatRecord(messageRecord)); #endif if (!this.session.IsClosed && 1 <= messageRecord.FieldCount) { switch (messageType) { case InstallMessage.ActionStart: // only try to interpret the messages if they're coming from WixRunImmediateUnitTests string action = messageRecord.GetString(1); this.runningTests = Constants.LuxCustomActionName == action; return MessageResult.OK; case InstallMessage.User: if (this.runningTests) { string message = messageRecord.ToString(); int id = messageRecord.GetInteger(1); if (Constants.TestIdMinimumSuccess <= id && Constants.TestIdMaximumSuccess >= id) { this.OnMessage(NitVerboses.TestPassed(message)); ++this.passes; } else if (Constants.TestIdMinimumFailure <= id && Constants.TestIdMaximumFailure >= id) { this.OnMessage(NitErrors.TestFailed(message)); ++this.failures; } } return MessageResult.OK; case InstallMessage.Error: case InstallMessage.FatalExit: this.OnMessage(NitErrors.PackageFailed(this.session.FormatRecord(messageRecord))); return MessageResult.Error; } } return MessageResult.OK; }