/// <summary> /// Writes and error to the pipeline. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing the error details.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnError(Deployment.WindowsInstaller.Record record) { if (null == record) { return(MessageResult.None); } else if (0 < record.FieldCount) { // Ignore certain errors. int code = record.GetInteger(1); switch (code) { case 1605: // Continue even if there isn't enough disk space for rollback. return(MessageResult.Ignore); case 1704: // Roll back suspended installs so we can continue. return(MessageResult.OK); } } using (var ex = new PSInstallerException(record)) { if (null != ex.ErrorRecord) { this.WriteError(ex.ErrorRecord); } } return(MessageResult.OK); }
private void TestProgressPhase2() { // With product name, estimated tick count, generating script. using (var rec = new Deployment.WindowsInstaller.Record(4)) { // CommonData: set CurrentProductName. rec.SetInteger(1, 1); rec.SetString(2, "INSTALL"); this.OnMessage(InstallMessage.CommonData, rec); // Progress: master rest. rec.SetInteger(1, 0); // Master reset. rec.SetInteger(2, 50); // Total; test that 50 is added. rec.SetInteger(3, 0); // Forward. rec.SetInteger(4, 1); // Generating script. this.OnMessage(InstallMessage.Progress, rec); // ActionStart: set CurrentAction. rec.FormatString = "Action: [1]: [2]"; rec.SetString(1, "Time"); rec.SetString(2, "Testing"); this.OnMessage(InstallMessage.ActionStart, rec); // Progress: report progress. rec.SetInteger(1, 2); rec.SetInteger(2, 50); this.OnMessage(InstallMessage.Progress, rec); // Progress: expand total. rec.SetInteger(1, 3); rec.SetInteger(2, 50); this.OnMessage(InstallMessage.Progress, rec); } }
public void DeserializePSInstallerException() { PSInstallerException ex; var formatter = new BinaryFormatter(); using (var ms = new MemoryStream()) { // Serialize the error record. using (var record = new Deployment.WindowsInstaller.Record(2)) { record.FormatString = "Installed [2]"; record.SetInteger(1, 1715); record.SetString(2, "TEST"); using (ex = new PSInstallerException(record)) { formatter.Serialize(ms, ex); } } // Reset the position. ms.Position = 0; // Deserialize the error record. using (ex = formatter.Deserialize(ms) as PSInstallerException) { Assert.IsNotNull(ex); var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual("Installed TEST", ex.Message, true); Assert.AreEqual("TEST", error.TargetObject as string, true); } } }
public void DeserializePSInstallerException() { PSInstallerException ex; var formatter = new BinaryFormatter(); using (var ms = new MemoryStream()) { // Serialize the error record. using (var record = new Deployment.WindowsInstaller.Record(2)) { record.FormatString = "Installed [2]"; record.SetInteger(1, 1715); record.SetString(2, "TEST"); using (ex = new PSInstallerException(record)) { formatter.Serialize(ms, ex); } } // Reset the position. ms.Position = 0; // Deserialize the error record. using (ex = formatter.Deserialize(ms) as PSInstallerException) { Assert.IsNotNull(ex); var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual("Installed TEST", ex.Message, true); Assert.AreEqual("TEST", error.TargetObject as string, true); } } }
private MessageResult OnInformation(Deployment.WindowsInstaller.Record record) { if (null != record) { string message = record.ToString(); if (!string.IsNullOrEmpty(message)) { var ice = new IceMessage(message); var obj = PSObject.AsPSObject(ice); if (!string.IsNullOrEmpty(this.CurrentPath)) { ice.Path = this.CurrentPath; // Set the PSPath for cmdlets that would use it. string path = this.SessionState.Path.GetUnresolvedPSPathFromProviderPath(this.CurrentPath); obj.SetPropertyValue <string>("PSPath", path); } var data = new Data(DataType.Information, obj); this.Output.Enqueue(data); } } return(MessageResult.OK); }
/// <summary> /// Called when an action sends more information. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing additional information.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnActionData(Deployment.WindowsInstaller.Record record) { if (this.progress.IsValid) { // Step the current progress completed. var current = this.progress.Current; if (current.EnableActionData) { if (current.Forward) { current.Complete += current.Step; } else { current.Complete -= current.Step; } } // Set the current action message when executing the script. if (null != record && !current.GeneratingScript) { if (!string.IsNullOrEmpty(this.progress.CurrentActionTemplate)) { record.FormatString = this.progress.CurrentActionTemplate; } this.progress.CurrentActionDetail = record.ToString(); } this.WriteProgress(); } return(MessageResult.OK); }
private void TestVerbose() { using (var verbose = new Deployment.WindowsInstaller.Record(0)) { verbose.FormatString = "verbose"; this.OnMessage(InstallMessage.Info, verbose); } }
private void TestWarning() { using (var warning = new Deployment.WindowsInstaller.Record(0)) { warning.FormatString = "warning"; this.OnMessage(InstallMessage.Warning, warning); } }
private void TestError() { using (var error = new Deployment.WindowsInstaller.Record(2)) { error.SetInteger(1, 1301); error.SetString(2, "error"); this.OnMessage(InstallMessage.Error, error); } }
/// <summary> /// Writes a verbose message to the pipeline. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing the verbose message details.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnVerbose(Deployment.WindowsInstaller.Record record) { if (null != record) { string message = record.ToString(); this.WriteVerbose(message); } return(MessageResult.OK); }
private void TestProgressPhase1() { // No product name or total tick count yet. using (var rec = new Deployment.WindowsInstaller.Record(2)) { rec.SetInteger(1, 2); rec.SetInteger(2, 0); this.OnMessage(InstallMessage.Progress, rec); } }
private MessageResult OnWarning(Deployment.WindowsInstaller.Record record) { if (null != record) { string message = record.ToString(); var data = new Data(DataType.Warning, message); this.Output.Enqueue(data); } return(MessageResult.OK); }
private static ErrorCategory GetErrorCategory(Deployment.WindowsInstaller.Record record, out string resource) { resource = null; if (1 < record.FieldCount) { int code = record.GetInteger(1); if (1000 <= code && code < 25000) { // Specifically handle common errors. switch (code) { case 1301: case 1304: resource = record.GetString(2); return(ErrorCategory.WriteError); case 1303: case 1306: case 1718: resource = record.GetString(2); return(ErrorCategory.PermissionDenied); case 1305: resource = record.GetString(2); return(ErrorCategory.ReadError); case 1308: case 1334: resource = record.GetString(2); return(ErrorCategory.ResourceUnavailable); case 1706: resource = record.GetString(2); return(ErrorCategory.ResourceUnavailable); case 1715: case 1716: case 1717: resource = record.GetString(2); return(ErrorCategory.NotSpecified); case 1935: case 1937: resource = record.GetString(6); return(ErrorCategory.InvalidData); } } } return(ErrorCategory.NotSpecified); }
private MessageResult OnError(Deployment.WindowsInstaller.Record record) { if (null != record) { using (var ex = new PSInstallerException(record)) { if (null != ex.ErrorRecord) { var data = new Data(DataType.Error, ex.ErrorRecord); this.Output.Enqueue(data); } } } return(MessageResult.OK); }
private MessageResult OnMessage(InstallMessage messageType, Deployment.WindowsInstaller.Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { switch (messageType) { case InstallMessage.FatalExit: case InstallMessage.Error: return(this.OnError(messageRecord)); case InstallMessage.Warning: return(this.OnWarning(messageRecord)); case InstallMessage.User: return(this.OnInformation(messageRecord)); default: return(MessageResult.None); } }
public void ValidateErrorRecordOpenError() { using (var record = new Deployment.WindowsInstaller.Record(2)) { record.SetInteger(1, 1301); record.SetString(2, @"C:\test.txt"); using (var ex = new PSInstallerException(record)) { var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual(@"C:\test.txt", error.TargetObject as string, true); var info = error.CategoryInfo; Assert.IsNotNull(info); Assert.AreEqual(ErrorCategory.WriteError, info.Category); } } }
private static byte[] CopyStream(Deployment.WindowsInstaller.Record record, int index) { using (var ms = new MemoryStream()) { var buffer = new byte[4096]; int read = 0; var stream = record.GetStream(index); do { read = stream.Read(buffer, 0, buffer.Length); if (0 < read) { ms.Write(buffer, 0, read); } }while (0 < read); return(ms.ToArray()); } }
/// <summary> /// Called when a new action starts. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing additional information.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnActionStart(Deployment.WindowsInstaller.Record record) { if (this.progress.IsValid) { var current = this.progress.Current; if (current.EnableActionData) { current.EnableActionData = false; } if (current.GeneratingScript) { this.progress.CurrentAction = Resources.Action_GeneratingScript; } else if (null != record && 2 < record.FieldCount) { var action = record.GetString(1); Debug.Assert(!string.IsNullOrEmpty(action), "Action should not be null at this point"); this.progress.CurrentAction = record.GetString(2); this.progress.CurrentActionTemplate = record.GetString(3); // Use current culture resources if ActionText is missing or doesn't match the current culture. var culture = this.progress.CurrentCulture ?? CultureInfo.InvariantCulture; if (string.IsNullOrEmpty(this.progress.CurrentAction) || !culture.Equals(CultureInfo.CurrentCulture)) { this.progress.CurrentAction = ActionText.GetActionText(action) ?? string.Empty; } if (string.IsNullOrEmpty(this.progress.CurrentActionTemplate) || !culture.Equals(CultureInfo.CurrentCulture)) { this.progress.CurrentActionTemplate = ActionText.GetActionData(action); } } } return(MessageResult.OK); }
/// <summary> /// Provides information about the install session. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing common details.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnCommonData(Deployment.WindowsInstaller.Record record) { // Get the current session language and Windows Installer-generated caption. if (1 < record.FieldCount) { var subtype = record.GetInteger(1); if (0 == subtype) { var langId = record.GetInteger(2); if (0 != langId) { this.progress.CurrentCulture = CultureInfo.GetCultureInfo(langId); } } else if (1 == subtype) { this.progress.CurrentName = record.GetString(2); } } return(MessageResult.OK); }
private PSInstallerException(SerializationInfo info, StreamingContext context) : base(info, context) { // ErrorRecord is cache only. this.errorRecord = null; int fieldCount = (int)info.GetValue(PSInstallerException.FieldCount, typeof(int)); if (0 < fieldCount) { this.record = new Deployment.WindowsInstaller.Record(fieldCount); for (int i = 0; i <= fieldCount; ++i) { string name = PSInstallerException.FieldPrefix + i.ToString(CultureInfo.InvariantCulture); string value = (string)info.GetValue(name, typeof(string)); this.record.SetString(i, value); } } else { this.record = null; } }
public void ValidateErrorRecordForFusion() { using (var record = new Deployment.WindowsInstaller.Record(6)) { record.SetInteger(1, 1935); record.SetString(2, "TestComponent"); record.SetInteger(3, unchecked ((int)0x80070005)); record.SetString(4, "ITestInterface"); record.SetString(5, "TestFunction"); record.SetString(6, "TestAssembly"); using (var ex = new PSInstallerException(record)) { var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual("TestAssembly", error.TargetObject as string, true); var info = error.CategoryInfo; Assert.IsNotNull(info); Assert.AreEqual(ErrorCategory.InvalidData, info.Category); } } }
private PSInstallerException(SerializationInfo info, StreamingContext context) : base(info, context) { // ErrorRecord is cache only. this.errorRecord = null; int fieldCount = (int)info.GetValue(PSInstallerException.FieldCount, typeof(int)); if (0 < fieldCount) { this.record = new Deployment.WindowsInstaller.Record(fieldCount); for (int i = 0; i <= fieldCount; ++i) { string name = PSInstallerException.FieldPrefix + i.ToString(CultureInfo.InvariantCulture); string value = (string)info.GetValue(name, typeof(string)); this.record.SetString(i, value); } } else { this.record = null; } }
/// <summary> /// Handles a message <see cref="Deployment.WindowsInstaller.Record"/> from Windows Installer. /// </summary> /// <param name="messageType">The <see cref="InstallMessage"/> type of the message.</param> /// <param name="messageRecord">The <see cref="Deployment.WindowsInstaller.Record"/> containing more information.</param> /// <param name="buttons">the <see cref="MessageButtons"/> to display.</param> /// <param name="icon">The <see cref="MessageIcon"/> to display.</param> /// <param name="defaultButton">The <see cref="MessageDefaultButton"/> to display.</param> /// <returns>The <see cref="MessageResult"/> that informs Windows Installer was action to take in response to the message.</returns> protected MessageResult OnMessage(InstallMessage messageType, Deployment.WindowsInstaller.Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { // Log all messages in debug mode. this.WriteMessage(messageType, messageRecord); switch (messageType) { case InstallMessage.Initialize: return(this.OnInitialize(messageRecord)); case InstallMessage.ActionStart: return(this.OnActionStart(messageRecord)); case InstallMessage.ActionData: return(this.OnActionData(messageRecord)); case InstallMessage.Error: case InstallMessage.FatalExit: case InstallMessage.OutOfDiskSpace: return(this.OnError(messageRecord)); case InstallMessage.Warning: return(this.OnWarning(messageRecord)); case InstallMessage.Info: case InstallMessage.User: return(this.OnVerbose(messageRecord)); case InstallMessage.Progress: return(this.OnProgress(messageRecord)); case InstallMessage.CommonData: return(this.OnCommonData(messageRecord)); } return(MessageResult.None); }
private void TestProgressPhase3() { // With product name, estimated tick count, executing script. using (var rec = new Deployment.WindowsInstaller.Record(4)) { // CommonData: set CurrentProductName. rec.SetInteger(1, 1); rec.SetString(2, "INSTALL"); this.OnMessage(InstallMessage.CommonData, rec); // Progress: master reset. rec.SetInteger(1, 0); // Master reset. rec.SetInteger(2, 100); // Total. rec.SetInteger(3, 0); // Forward. rec.SetInteger(4, 0); // Executing script. this.OnMessage(InstallMessage.Progress, rec); // ActionStart: set CurrentAction. rec.FormatString = "Action: [1]: [2]"; rec.SetString(1, "Time"); rec.SetString(2, "Testing"); rec.SetString(3, null); this.OnMessage(InstallMessage.ActionStart, rec); // Progress: update progress. rec.SetInteger(1, 1); // update progress. rec.SetInteger(2, 50); // Step. rec.SetInteger(3, 1); // Enable ActionData. this.OnMessage(InstallMessage.Progress, rec); // ActionData: set CurrentActionDetail and step progress. rec.FormatString = "Testing: [1]"; rec.SetString(1, "ActionData"); this.OnMessage(InstallMessage.ActionData, rec); } }
private void WriteMessage(InstallMessage type, Deployment.WindowsInstaller.Record record) { var sb = new StringBuilder(); sb.AppendFormat(CultureInfo.InvariantCulture, "{0} ({0:d})", type); if (null != record) { sb.Append(": "); // Show field 0 (format string) as well. for (int i = 0; i <= record.FieldCount; ++i) { if (0 != i) { sb.Append(", "); } sb.AppendFormat(CultureInfo.InvariantCulture, "{0}: {1}", i, record.GetString(i)); } } this.WriteDebug(sb.ToString()); }
/// <summary> /// Creates a <see cref="PSInstallerException"/> from the given <paramref name="record"/>. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing error details.</param> public PSInstallerException(Deployment.WindowsInstaller.Record record) { this.errorRecord = null; this.record = record; }
/// <summary> /// Creates a <see cref="PSInstallerException"/> from the given <paramref name="record"/>. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing error details.</param> public PSInstallerException(Deployment.WindowsInstaller.Record record) { this.errorRecord = null; this.record = record; }
/// <summary> /// Creates a <see cref="PSInstallerException"/> from the given inner exception. /// </summary> /// <param name="innerException">The <see cref="InstallerException"/> containing error details.</param> public PSInstallerException(InstallerException innerException) : base(null, innerException) { this.errorRecord = null; this.record = null; }
public void ValidateErrorRecordForFusion() { using (var record = new Deployment.WindowsInstaller.Record(6)) { record.SetInteger(1, 1935); record.SetString(2, "TestComponent"); record.SetInteger(3, unchecked((int)0x80070005)); record.SetString(4, "ITestInterface"); record.SetString(5, "TestFunction"); record.SetString(6, "TestAssembly"); using (var ex = new PSInstallerException(record)) { var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual("TestAssembly", error.TargetObject as string, true); var info = error.CategoryInfo; Assert.IsNotNull(info); Assert.AreEqual(ErrorCategory.InvalidData, info.Category); } } }
public void ValidateErrorRecordOpenError() { using (var record = new Deployment.WindowsInstaller.Record(2)) { record.SetInteger(1, 1301); record.SetString(2, @"C:\test.txt"); using (var ex = new PSInstallerException(record)) { var error = ex.ErrorRecord; Assert.IsNotNull(error); Assert.AreEqual(@"C:\test.txt", error.TargetObject as string, true); var info = error.CategoryInfo; Assert.IsNotNull(info); Assert.AreEqual(ErrorCategory.WriteError, info.Category); } } }
/// <summary> /// Creates a <see cref="PSInstallerException"/> from the given inner exception. /// </summary> /// <param name="innerException">The <see cref="InstallerException"/> containing error details.</param> public PSInstallerException(InstallerException innerException) : base(null, innerException) { this.errorRecord = null; this.record = null; }
private void OnMessage(InstallMessage type, Deployment.WindowsInstaller.Record record = null) { this.OnMessage(type, record, MessageButtons.OKCancel, MessageIcon.None, MessageDefaultButton.Button1); }
/// <summary> /// Initializes a new instance of the <see cref="Record"/> class. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> from which to copy values.</param> /// <param name="columns">The <see cref="ColumnCollection"/> for a <see cref="Deployment.WindowsInstaller.View"/>.</param> /// <param name="transform">The <see cref="TransformView"/> containing information about operations performed on this record.</param> /// <param name="path">The path to the package that contains the record.</param> internal Record(Deployment.WindowsInstaller.Record record, ColumnCollection columns, TransformView transform = null, string path = null) { // Internal constructor will assume valid parameters. // Shared reference to the column collection. this.Columns = columns; this.Path = path; // Cache the data from the record. var primaryKeys = new List <string>(); this.Data = new List <object>(columns.Count); for (int i = 0; i < columns.Count; ++i) { // Windows Installer uses 1-based indices. var offset = i + 1; var type = columns[i].Type; if (type.IsEnum) { var value = record.GetNullableInteger(offset); this.Data.Add(new AttributeColumn(type, value)); if (columns[i].IsPrimaryKey) { primaryKeys.Add(null != value ? value.Value.ToString(CultureInfo.InvariantCulture) : string.Empty); } } else if (typeof(Stream) == type) { var buffer = CopyStream(record, offset); this.Data.Add(buffer); // Binary column types cannot be primary keys. } else { var data = record[offset]; this.Data.Add(data); if (columns[i].IsPrimaryKey) { primaryKeys.Add(null != data ? data.ToString() : string.Empty); } } } if (0 < primaryKeys.Count) { this.PrimaryKey = primaryKeys.Join(Record.KeySeparator); } // Can only reliably get row operations performed on rows in a single table. if (null != transform && 1 == columns.TableNames.Count()) { var tableName = columns.TableNames[0]; this.Operation = transform.GetRowOperation(tableName, this.PrimaryKey); } else { this.Operation = RowOperation.None; } }
/// <summary> /// Writes progress information. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing the progress details.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnProgress(Deployment.WindowsInstaller.Record record) { if (null == record || 2 > record.FieldCount) { return(MessageResult.None); } switch (record.GetInteger(1)) { // Add a new phase of progress information. case 0: if (4 > record.FieldCount) { // Invalid message. break; } // Add a new phase of progress. var current = this.progress.Add(); current.Forward = 0 == record.GetInteger(3); current.Total = record.GetInteger(2); current.Complete = current.Forward ? 0 : current.Total; current.EnableActionData = false; current.GeneratingScript = 1 == record.GetInteger(4); // Windows Installer team advises to add ~50 ticks to script generation. if (0 == this.progress.CurrentIndex) { current.Total += 50; } break; // Update progress information. case 1: if (3 > record.FieldCount) { // Invalid message. break; } else if (!this.progress.IsValid) { // Progress not initialized. break; } if (0 == record.GetInteger(3)) { this.progress.Current.EnableActionData = false; } else { this.progress.Current.EnableActionData = true; this.progress.Current.Step = record.GetInteger(2); } break; // Report progress information. case 2: if (!this.progress.IsValid || 0 == this.progress.Current.Total) { // Progress not initialized. break; } // Adjust the current progress. if (this.progress.Current.Forward) { this.progress.Current.Complete += record.GetInteger(2); } else { this.progress.Current.Complete -= record.GetInteger(2); } break; // Expand the total. case 3: if (!this.progress.IsValid) { // Progress not initialized. break; } // Expand the progress maximum. this.progress.Current.Total += record.GetInteger(2); break; default: return(MessageResult.None); } this.WriteProgress(); return(MessageResult.OK); }
/// <summary> /// Initializes the execution state. /// </summary> /// <param name="record">The <see cref="Deployment.WindowsInstaller.Record"/> containing additional information.</param> /// <returns>The result code indicating how Windows Installer should proceed.</returns> protected MessageResult OnInitialize(Deployment.WindowsInstaller.Record record) { this.Reset(); return(MessageResult.OK); }