/// <summary> /// Gets the <see cref="Installation"/> class given the <see cref="Parameters"/>. /// </summary> /// <param name="param">The <see cref="Parameters"/> of the <see cref="Installation"/> to get.</param> /// <returns>An <see cref="Installation"/> given the <see cref="Parameters"/>.</returns> protected Installation GetInstallation(Parameters param) { Installation installation = null; try { if (string.IsNullOrEmpty(param.PatchCode)) { installation = ProductInstallation.GetProducts(param.ProductCode, param.UserSid, param.UserContext).FirstOrDefault(); } else { installation = PatchInstallation.GetPatches(param.PatchCode, param.ProductCode, param.UserSid, param.UserContext, PatchStates.All).FirstOrDefault(); } } catch (InstallerException ex) { var pse = new PSInstallerException(ex); if (null != pse.ErrorRecord) { base.WriteError(pse.ErrorRecord); } } return(installation); }
/// <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); }
/// <summary> /// Applies any applicable transforms from <see cref="Patch"/> and <see cref="Transform"/> to the given package. /// </summary> /// <param name="db">The <see cref="InstallPackage"/> database to which applicable transforms are applied.</param> protected void ApplyTransforms(InstallPackage db) { // Apply transforms first since they likely apply to the unpatched product. if (0 < this.Transform.Count()) { this.Transform = this.ResolveFiles(this.Transform).ToArray(); foreach (string path in this.Transform) { try { db.ApplyTransform(path, PatchApplicator.IgnoreErrors); db.ApplyTransform(path, PatchApplicator.IgnoreErrors | TransformErrors.ViewTransform); } catch (InstallerException ex) { using (var pse = new PSInstallerException(ex)) { if (null != pse.ErrorRecord) { base.WriteError(pse.ErrorRecord); } } } } db.Commit(); } // Apply applicable patch transforms. if (0 < this.Patch.Count()) { this.Patch = this.ResolveFiles(this.Patch).ToArray(); var applicator = new PatchApplicator(db); foreach (string path in this.Patch) { applicator.Add(path); } applicator.InapplicablePatch += (source, args) => { var message = string.Format(CultureInfo.CurrentCulture, Resources.Error_InapplicablePatch, args.Patch, args.Product); base.WriteVerbose(message); }; // The applicator will commit the changes. applicator.Apply(); } }
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); }
/// <summary> /// Processes the input paths and writes the file hashes to the pipeline. /// </summary> protected override void ProcessRecord() { // If no path was provided, enumerate all child items. if (null == this.Path || 0 == this.Path.Length) { this.Path = All; } // Enumerate all the file system items. var items = this.InvokeProvider.Item.Get(this.Path, true, this.IsLiteralPath); foreach (var item in items) { // Get the provider path. var path = item.GetPropertyValue <string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); if (File.Exists(path) || Directory.Exists(path)) { try { this.ProcessItem(item); } catch (InstallerException ex) { var pse = new PSInstallerException(ex); if (null != pse.ErrorRecord) { base.WriteError(pse.ErrorRecord); } } } else { var message = string.Format(CultureInfo.CurrentCulture, Properties.Resources.Error_InvalidFile, path); var ex = new NotSupportedException(message); var error = new ErrorRecord(ex, "UnsupportedItemType", ErrorCategory.InvalidType, path); this.WriteError(error); } } }
private void ExecuteActions() { using (new UserInterfaceHandler(this.OnMessage, this.Force)) { // Keep track of the total weight for all queued actions. this.Actions.OriginalWeight = this.Actions.Sum(data => data.Weight); // Create a single restore point for chained packages. SystemRestorePoint restorePoint = null; if (this.Chain) { try { restorePoint = SystemRestorePoint.Create(this.Operation); } catch (Win32Exception ex) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Error_NoRestorePoint, ex.Message); this.WriteWarning(message); } } // Execute the actions. while (0 < this.Actions.Count) { try { T data = this.Actions.Dequeue(); this.progress.CurrentWeight = data.Weight; string extra = null != data ? data.LogName : null; Installer.EnableLog(this.log.Mode, this.log.Next(extra)); // If a system restore point was successfully created, // disable creating restore points for each package. if (null != restorePoint) { data.CommandLine += " MSIFASTINSTALL=1"; } // Suppress reboots when possible if chaining. if (this.Chain) { data.CommandLine += " REBOOT=ReallySuppress"; } this.ExecuteAction(data); } catch (InstallerException ex) { using (var psiex = new PSInstallerException(ex)) { if (null != psiex.ErrorRecord) { this.WriteError(psiex.ErrorRecord); } else { // Unexpected not to have an ErrorRecord. throw; } } } finally { if (null != this.result) { this.result.RebootInitiated = Installer.RebootInitiated; this.result.RebootRequired = Installer.RebootRequired; } } } // Complete an existing restore point. if (null != restorePoint) { restorePoint.Commit(); } // Make sure progress is completed. this.WriteProgress(true); // Warn the user if a restart is required. if (Installer.RebootRequired) { var ex = new Win32Exception(3010); this.WriteWarning(ex.Message); } } }
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; }
/// <summary> /// Merges ICE cubes into the database <paramref name="item"/> and executes selected ICEs. /// </summary> /// <param name="item">The database to validate.</param> protected override void ProcessItem(PSObject item) { // Get the item path and set the current context. string path = item.GetPropertyValue<string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); this.CurrentPath = path; // Copy the database to a writable location and open. string copy = this.Copy(path); using (var db = new InstallPackage(copy, DatabaseOpenMode.Direct)) { // Apply any patches or transforms before otherwise modifying. this.ApplyTransforms(db); // Copy the ProductCode and drop the Property table to avoid opening an installed product. bool hasProperty = db.IsTablePersistent("Property"); string productCode = null; if (hasProperty) { productCode = db.ExecutePropertyQuery("ProductCode"); } // Merge the ICE cubes and fix up the database if needed. this.MergeCubes(db); if (!hasProperty) { db.Execute("DROP TABLE `Property`"); } var included = new List<WildcardPattern>(); if (null != this.Include) { Array.ForEach(this.Include, pattern => included.Add(new WildcardPattern(pattern))); } var excluded = new List<WildcardPattern>(); if (null != this.Exclude) { Array.ForEach(this.Exclude, pattern => excluded.Add(new WildcardPattern(pattern))); } // Get all the ICE actions in the database that are not excluded. var actions = new List<string>(); foreach (var action in db.ExecuteStringQuery("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) { if (!action.Match(excluded)) { actions.Add(action); } } // Remove any actions not explicitly included. if (0 < included.Count) { for (int i = actions.Count - 1; 0 <= i; --i) { if (!actions[i].Match(included)) { actions.RemoveAt(i); } } } // Open a session with the database. using (var session = Installer.OpenPackage(db, false)) { // Put the original ProductCode back. if (!string.IsNullOrEmpty(productCode)) { db.Execute("DELETE FROM `Property` WHERE `Property` = 'ProductCode'"); db.Execute("INSERT INTO `Property` (`Property`, `Value`) VALUES ('ProductCode', '{0}')", productCode); } // Now execute all the remaining actions in order. foreach (string action in actions) { try { session.DoAction(action); this.Flush(); } catch (InstallerException ex) { using (var pse = new PSInstallerException(ex)) { if (null != pse.ErrorRecord) { this.WriteError(pse.ErrorRecord); } } } } } } }
/// <summary> /// Processes the input paths and writes the file hashes to the pipeline. /// </summary> protected override void ProcessRecord() { // If no path was provided, enumerate all child items. if (null == this.Path || 0 == this.Path.Length) { this.Path = All; } // Enumerate all the file system items. var items = this.InvokeProvider.Item.Get(this.Path, true, this.IsLiteralPath); foreach (var item in items) { // Get the provider path. var path = item.GetPropertyValue<string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); if (File.Exists(path) || Directory.Exists(path)) { try { this.ProcessItem(item); } catch (InstallerException ex) { var pse = new PSInstallerException(ex); if (null != pse.ErrorRecord) { base.WriteError(pse.ErrorRecord); } } } else { var message = string.Format(CultureInfo.CurrentCulture, Properties.Resources.Error_InvalidFile, path); var ex = new NotSupportedException(message); var error = new ErrorRecord(ex, "UnsupportedItemType", ErrorCategory.InvalidType, path); this.WriteError(error); } } }
/// <summary> /// Merges ICE cubes into the database <paramref name="item"/> and executes selected ICEs. /// </summary> /// <param name="item">The database to validate.</param> protected override void ProcessItem(PSObject item) { // Get the item path and set the current context. string path = item.GetPropertyValue <string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); this.CurrentPath = path; // Copy the database to a writable location and open. string copy = this.Copy(path); using (var db = new InstallPackage(copy, DatabaseOpenMode.Direct)) { // Apply any patches or transforms before otherwise modifying. this.ApplyTransforms(db); // Copy the ProductCode and drop the Property table to avoid opening an installed product. bool hasProperty = db.IsTablePersistent("Property"); string productCode = null; if (hasProperty) { productCode = db.ExecutePropertyQuery("ProductCode"); } // Merge the ICE cubes and fix up the database if needed. this.MergeCubes(db); if (!hasProperty) { db.Execute("DROP TABLE `Property`"); } var included = new List <WildcardPattern>(); if (null != this.Include) { Array.ForEach(this.Include, pattern => included.Add(new WildcardPattern(pattern))); } var excluded = new List <WildcardPattern>(); if (null != this.Exclude) { Array.ForEach(this.Exclude, pattern => excluded.Add(new WildcardPattern(pattern))); } // Get all the ICE actions in the database that are not excluded. var actions = new List <string>(); foreach (var action in db.ExecuteStringQuery("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) { if (!action.Match(excluded)) { actions.Add(action); } } // Remove any actions not explicitly included. if (0 < included.Count) { for (int i = actions.Count - 1; 0 <= i; --i) { if (!actions[i].Match(included)) { actions.RemoveAt(i); } } } // Open a session with the database. using (var session = Installer.OpenPackage(db, false)) { // Put the original ProductCode back. if (!string.IsNullOrEmpty(productCode)) { db.Execute("DELETE FROM `Property` WHERE `Property` = 'ProductCode'"); db.Execute("INSERT INTO `Property` (`Property`, `Value`) VALUES ('ProductCode', '{0}')", productCode); } // Now execute all the remaining actions in order. foreach (string action in actions) { try { session.DoAction(action); this.Flush(); } catch (InstallerException ex) { using (var pse = new PSInstallerException(ex)) { if (null != pse.ErrorRecord) { this.WriteError(pse.ErrorRecord); } } } } } } }
/// <summary> /// Applies any applicable transforms from <see cref="Patch"/> and <see cref="Transform"/> to the given package. /// </summary> /// <param name="db">The <see cref="InstallPackage"/> database to which applicable transforms are applied.</param> protected void ApplyTransforms(InstallPackage db) { // Apply transforms first since they likely apply to the unpatched product. if (0 < this.Transform.Count()) { this.Transform = this.ResolveFiles(this.Transform).ToArray(); foreach (string path in this.Transform) { try { db.ApplyTransform(path, PatchApplicator.IgnoreErrors); db.ApplyTransform(path, PatchApplicator.IgnoreErrors | TransformErrors.ViewTransform); } catch (InstallerException ex) { using (var pse = new PSInstallerException(ex)) { if (null != pse.ErrorRecord) { base.WriteError(pse.ErrorRecord); } } } } db.Commit(); } // Apply applicable patch transforms. if (0 < this.Patch.Count()) { this.Patch = this.ResolveFiles(this.Patch).ToArray(); var applicator = new PatchApplicator(db); foreach (string path in this.Patch) { applicator.Add(path); } applicator.InapplicablePatch += (source, args) => { var message = string.Format(CultureInfo.CurrentCulture, Resources.Error_InapplicablePatch, args.Patch, args.Product); base.WriteVerbose(message); }; // The applicator will commit the changes. applicator.Apply(); } }