/// <summary> /// Writes a <see cref="SummaryInfo"/> object for each supported file type to the pipeline. /// </summary> /// <param name="item">A <see cref="PSObject"/> representing the file system object to process.</param> protected override void ProcessItem(PSObject item) { var path = item.GetPropertyValue<string>("PSPath"); var providerPath = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); // Make sure the file exists and is a patch. var type = FileInfo.GetFileTypeInternal(providerPath); if (FileType.Package == type || FileType.Patch == type || FileType.Transform == type) { using (var info = new Deployment.WindowsInstaller.SummaryInfo(providerPath, false)) { var copy = new SummaryInfo(info); var obj = PSObject.AsPSObject(copy); // Add the class type as the first type name. var name = typeof(SummaryInfo).FullName + "#" + type; obj.TypeNames.Insert(0, name); // Attach the original PSPath and write to the pipeline. obj.SetPropertyValue("PSPath", path); this.WriteObject(obj); } } // Enumerate transforms in the patch. if (FileType.Patch == type && this.IncludeTransforms) { using (var patch = new PatchPackage(providerPath)) { foreach (var transform in patch.GetTransformsInfo(true)) { var obj = PSObject.AsPSObject(transform); // Attach the original patch path and write to the pipeline. obj.SetPropertyValue("Patch", providerPath); this.WriteObject(obj); } } } }
/// <summary> /// Gets property records from the item. /// </summary> /// <param name="item">The item from which properties are retrieved.</param> protected override void ProcessItem(PSObject item) { var path = item.GetPropertyValue<string>("PSPath"); var providerPath = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); var db = this.OpenDatabase(providerPath); if (null != db) { // Keep track of which properties were selected. IList<string> properties = null; if (this.PassThru) { properties = new List<string>(); } using (db) { TransformView transform = null; if (db.Tables.Contains(TransformView.TableName)) { transform = new TransformView(db); } var table = "Property"; if ((db is PatchPackage) && db.Tables.Contains("MsiPatchMetadata")) { table = "MsiPatchMetadata"; } var query = string.Format("SELECT `Property`, `Value` FROM `{0}`", table); using (var view = db.OpenView(query)) { view.Execute(); // Get column information from the view before being disposed. var columns = ViewManager.GetColumns(view); var record = view.Fetch(); while (null != record) { using (record) { var name = record.GetString(1); if (0 == this.propertyPatterns.Count() || name.Match(this.propertyPatterns)) { if (this.PassThru) { if (0 == item.Properties.Match(name).Count()) { properties.Add(name); var property = new PSNoteProperty(name, record.GetString(2)); item.Properties.Add(property, true); } } else { // Create a locally cached copy of the record. var copy = new Record(record, columns, transform, providerPath); var obj = PSObject.AsPSObject(copy); // Show only column properties by default. var memberSet = ViewManager.GetMemberSet(view); obj.Members.Add(memberSet, true); base.WriteObject(obj); } } } record = view.Fetch(); } } } if (this.PassThru) { var propertySet = new PSPropertySet("MSIProperties", properties); item.Members.Add(propertySet, true); base.WriteObject(item); } } }
/// <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> /// Adds each patch enumerated to the <see cref="PatchSequencer"/> to sequence for each product in <see cref="EndProcessing"/>. /// </summary> /// <param name="item">A <see cref="PSObject"/> representing the path to a patch package.</param> protected override void ProcessItem(PSObject item) { string path = item.GetPropertyValue<string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); this.sequencer.Add(path); }
/// <summary> /// Attempts to open the item in Orca, if installed; otherwise, tries to invoke the "edit" verb on the package. /// </summary> /// <param name="item">The <see cref="PSObject"/> representing a package to open.</param> protected override void ProcessItem(PSObject item) { string path = item.GetPropertyValue<string>("PSPath"); path = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); // Make sure the item is an MSI or MSP package. var type = FileInfo.GetFileTypeInternal(path); if (FileType.Package != type && FileType.Patch != type) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Error_InvalidStorage, path); var ex = new PSInvalidOperationException(message); this.WriteError(ex.ErrorRecord); return; } var info = new ProcessStartInfo() { WorkingDirectory = System.IO.Path.GetDirectoryName(path), }; if (!string.IsNullOrEmpty(this.orcaPath)) { // Open in Orca, if installed. info.FileName = this.orcaPath; info.Arguments = "\"" + path + "\""; } else { // Try to use the edit verb instead. info.FileName = path; info.UseShellExecute = true; info.Verb = "edit"; } Process process = null; try { process = Process.Start(info); if (this.Wait) { process.WaitForExit(); } } catch (Exception ex) { if (ex is InvalidOperationException || ex is Win32Exception) { // Likely the "edit" verb is not supported so terminate. var pse = new PSInvalidOperationException(ex.Message, ex); this.ThrowTerminatingError(pse.ErrorRecord); } else { throw; } } finally { if (null != process) { process.Dispose(); } } }
/// <summary> /// Opens the database specified by the <paramref name="item"/> and executes the specified query. /// </summary> /// <param name="item">A file item that references a package database.</param> protected override void ProcessItem(PSObject item) { var path = item.GetPropertyValue<string>("PSPath"); var providerPath = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); var db = base.OpenDatabase(providerPath); if (null != db) { using (db) { this.WriteRecords(db, providerPath); } } }