private void GetDataFromSource(ICollection<Bundle> installables, Bundle rel, string filetype, string filepath) { switch (filetype) { case FILETYPE_WIXPDB: var pdb = Wix.Pdb.Load(filepath, false, false); if (pdb.Output.Type == Wix.OutputType.Bundle) { var wixbundle = pdb.Output.Tables[WIXBUNDLE]; //Id: 32 in pdb.Output.Rows var chainmsipackageTable = pdb.Output.Tables[CHAINMSIPACKAGE]; //Id: 0 in pdb.Output.Rows var ChainPackageInfoTable = pdb.Output.Tables[CHAINPACKAGEINFO]; //Id: 0 in pdb.Output.Rows if (wixbundle != null) { var bundlerow = (Wix.WixBundleRow)wixbundle.Rows[0]; var bundle = new Bundle(bundlerow.BundleId, bundlerow.Name, bundlerow.Version); bundlerow = null; if (chainmsipackageTable != null) { GetMSIDataFromTable(bundle, chainmsipackageTable, ChainPackageInfoTable); } bundle.Selected = rel.Selected; Logger.Log(String.Format(CultureInfo.InvariantCulture, "Successfully loaded: {0} [{1}]", rel.Name, FILETYPE_WIXPDB)); installables.Add(bundle); } } break; case FILETYPE_BIN: var binload = LoadFromFile(filepath); rel.FileType = string.IsNullOrEmpty(rel.FileType) ? binload.FileType : rel.FileType; rel.BundleId = rel.BundleId.ToString().Count() == 0 ? binload.BundleId : rel.BundleId; if (rel.Packages == null) // if the Packages object is null, we have no MSIs listed in the bundle { foreach (Package package in binload.Packages) { rel.Packages.Add(package); } } rel.Name = string.IsNullOrEmpty(rel.Name) ? binload.Name : rel.Name; rel.binPath = binload.Path; rel.ReleasePdb = string.IsNullOrEmpty(rel.ReleasePdb) ? binload.ReleasePdb : rel.ReleasePdb; rel.Version = rel.Version == null ? binload.Version : rel.Version; rel.Selected = rel.Selected ? rel.Selected : binload.Selected; installables.Add(rel); Logger.Log(String.Format(CultureInfo.InvariantCulture, "Successfully loaded: {0} [{1}]", rel.Name, FILETYPE_BIN)); break; } }
/// <summary> /// Load a wixpdb /// </summary> /// <param name="path"></param> /// <returns></returns> public bool LoadFromWixpdb(string path) { try { // Get all files associated with WixPDBs in directory Logger.Log(String.Format(CultureInfo.InvariantCulture, "Loading {0}", path), Logger.MessageLevel.Information, "Utility"); var pdb = Wix.Pdb.Load(Path.GetFullPath(path), true, true); var bundlerowinfo = (Wix.WixBundleRow)GetBundlesFromWixPDB(pdb).Rows[0]; var bundle = new Bundle(bundlerowinfo.BundleId, bundlerowinfo.Name, bundlerowinfo.Version, Path.GetFileNameWithoutExtension(path), Path.GetFullPath(path), FILETYPE_WIXPDB, false); if (!this.BundlesAndPackagesStore.Bundles.Any(b => b.BundleId == bundle.BundleId)) { this.BundlesAndPackagesStore.Bundles.Add(bundle); } if (pdb.Output.Type == Wix.OutputType.Bundle) { var wixbundle = pdb.Output.Tables[WIXBUNDLE]; //Id: 32 in pdb.Output.Rows var chainmsipackageTable = pdb.Output.Tables[CHAINMSIPACKAGE]; //Id: 0 in pdb.Output.Rows var uxPackageBehavior = pdb.Output.Tables[UXPACKAGEBEHAVIOR]; //Id: 0 in pdb.Output.Rows if (wixbundle != null) { if (chainmsipackageTable != null) { this.GetUniquePackages( this.BundlesAndPackagesStore.UpgradeCodeHash, this.BundlesAndPackagesStore.NoUpgradeCodeProductCodeHash, chainmsipackageTable, uxPackageBehavior); } } } bundlerowinfo = null; } catch (Exception e) { Logger.Log("Unable to load wixpdb: " + path, Logger.MessageLevel.Error); Logger.Log(e); return false; } return true; }
private void GetContent(ref ICollection<Bundle> rels, string path) { try { if (Directory.Exists(@"content")) { if (Directory.GetFiles(@"content").Length != 0) { ICollection<string> list = new List<string>(Directory.GetFiles(@"content")); rels = new List<Bundle>(); foreach (string entry in list) { try { // Get all files associated with WixPDBs in directory Logger.Log(String.Format(CultureInfo.InvariantCulture, "Loading {0}", entry), Logger.MessageLevel.Information, "Utility"); Wix.Pdb.Load(Path.GetFullPath(entry), true, true); var bundlerowinfo = (Wix.WixBundleRow)GetBundlesFromWixPDB(entry).Rows[0]; var newrel = new Bundle(bundlerowinfo.BundleId, bundlerowinfo.Name, bundlerowinfo.Version, Path.GetFileNameWithoutExtension(entry), Path.GetFullPath(entry), FILETYPE_WIXPDB, false); rels.Add(newrel); bundlerowinfo = null; } catch(Exception e) { Logger.Log("Unable to load wixpdb: " + entry, Logger.MessageLevel.Error); Logger.Log(e); } } } } if (Directory.Exists(path) && Directory.GetFiles(path).Length != 0) { // Get all already processed files available Get working directory iterate // through remove foreach (string fileitem in Directory.GetFiles(path)) { // Does a PDB exist for the file that we are reading? var filenamewithoutextension = Path.GetFileNameWithoutExtension(fileitem); if (releases.Where(x => x.Name == filenamewithoutextension) != null) { // Update values to use the file instead releases.FirstOrDefault(x => x.Name == filenamewithoutextension).FileType = FILETYPE_BIN; releases.FirstOrDefault(x => x.Name == filenamewithoutextension).binPath = Path.Combine(path, fileitem); } else // If there is no wixpdb does not exist, pull data from the file to populate releases { try { var tempbundle = FileToBundle(fileitem); var rel = new Bundle(tempbundle.BundleId, tempbundle.Name, tempbundle.Version, "", path, FILETYPE_BIN, false, tempbundle.Packages) { binPath = Path.Combine(path, fileitem) }; rels.Add(rel); tempbundle = null; rel = null; } catch(Exception e) { Logger.Log("Unable to load bundle file: " + fileitem, Logger.MessageLevel.Error); Logger.Log(e); } } } } } catch (Exception ex) { Logger.Log(ex); } finally { } }
private static ICollection<Package> GetMSIDataFromTable(Bundle bundle, Wix.Table chainmsipackageTable, Wix.Table cpiTable) { try { foreach (Wix.Row msirow in chainmsipackageTable.Rows) { var msi = new Package(); foreach (Wix.Field field in msirow.Fields) { switch (field.Column.Name.ToString(CultureInfo.InvariantCulture).ToUpperInvariant()) { case "CHAINPACKAGE_": msi.ChainingPackage = field.Data.ToString(); break; case "PRODUCTCODE": // id 23 msi.ProductCode = field.Data.ToString(); break; case "PRODUCTVERSION": msi.ProductVersion = field.Data.ToString(); break; case "PRODUCTNAME": msi.ProductName = field.Data.ToString(); break; case "PACKAGETYPE": msi.Type = Package.PackageType.MSI; break; default: break; } } bundle.Packages.Add(msi); } if (cpiTable != null) { foreach (Wix.Row packageinforow in cpiTable.Rows) { if (packageinforow.Fields[1].Data.ToString().ToUpperInvariant() == "MSU") { var msu = new Package(); foreach (Wix.Field field in packageinforow.Fields) { switch (field.Column.Name.ToString(CultureInfo.InvariantCulture).ToUpperInvariant()) { case "ID": // id 0 msu.ChainingPackage = field.Data.ToString(); break; case "MSUKB": // id 13 msu.ProductCode = field.Data.ToString().Replace("KB", ""); break; case "VERSION": // id 25 msu.ProductVersion = (field.Data != null) ? field.Data.ToString() : ""; break; case "DISPLAYNAME": // id 27 msu.ProductName = (field.Data != null) ? field.Data.ToString() : ""; break; case "PACKAGETYPE": // id 1 msu.Type = Package.PackageType.MSU; break; default: break; } } bundle.Packages.Add(msu); } } } } catch (Exception ex) { Logger.Log(ex); } return bundle.Packages; }
public int Uninstall(Bundle bundle) { var exitcode = -1; var uninstallactionerrorcode = -1; if (!Processed) { GetDataFromPdb(); } if (Releases.Where(x=>x.Selected) != null) { try { Logger.Log(String.Format(CultureInfo.InvariantCulture, "Pre-requisite uninstall actions running"), Logger.MessageLevel.Information, AppName); uninstallactionerrorcode = UninstallActionExecution(bundle, UninstallAction.TemplateType.Pre); Logger.Log(String.Format(CultureInfo.InvariantCulture, "Pre-requisite uninstall actions finished"), Logger.MessageLevel.Information, AppName); switch (uninstallactionerrorcode) { case 3010: // Reboot required break; default: if (!DoNotExecuteProcess) { exitcode = bundle.Uninstall(); } else { Logger.Log(String.Format(CultureInfo.InvariantCulture, "Bundle uninstall method bypassed - DoNotExecute is true"), Logger.MessageLevel.Verbose, AppName); exitcode = 0; } Logger.Log(String.Format(CultureInfo.InvariantCulture, "Post-requisite uninstall actions started"), Logger.MessageLevel.Information, AppName); UninstallActionExecution(bundle, UninstallAction.TemplateType.Post); Logger.Log(String.Format(CultureInfo.InvariantCulture, "Post-requisite uninstall actions finished"), Logger.MessageLevel.Information, AppName); break; } } catch (Exception ex) { Logger.Log(ex, AppName); } } else { throw new ConfigurationManagerException("A release has not been selected for use with this method. Please use SelectedReleases to select a Release."); } return exitcode; }
private int UninstallActionExecution(Bundle bundle, UninstallAction.TemplateType template) { var DidInstallRun = false; var errorcode = 0; var currenterrorcode = 0; var rebootrequired = false; Logger.Log(String.Format(CultureInfo.InvariantCulture, "Starting Template Type: {0} Bundle: {1}", template.ToString(), bundle.Name), Logger.MessageLevel.Information, AppName); ICollection<UninstallAction> _uas = UninstallActions.Where(x => x.Template == template).ToList(); // For each uninstall item, only select those that are either before or after the main uninstall process // and match the machine OS and Architecture. This is defined by the template parameter. // Only for given machine architecture Logger.Log(String.Format(CultureInfo.InvariantCulture, "Uninstall actions found: {0}", _uas.Count().ToString(CultureInfo.InvariantCulture)), Logger.MessageLevel.Verbose, AppName); foreach (UninstallAction ua in _uas) { foreach (ArchitectureConfiguration ac in ua.Architectures) { if (ac.Value == MachineArchitectureConfiguration.Value) { // Only get one OS version that matches to integer value from the OS foreach (OperatingSystemConfiguration osc in ua.OS) { if (osc.Value == MachineOSVersion) { // Uninstall the selected package foreach (Package package in bundle.Packages.Where(x => x.ProductCode == ua.ProductCode)) { if (!DoNotExecuteProcess) { Logger.Log(String.Format(CultureInfo.InvariantCulture, "Package found to match architecture and OS: {0}", package.ProductName), Logger.MessageLevel.Information, AppName); currenterrorcode = package.Uninstall(); DidInstallRun = true; switch (currenterrorcode) { case 0: errorcode = currenterrorcode; break; case 3010: Logger.Log(String.Format(CultureInfo.InvariantCulture, "Reboot required"), Logger.MessageLevel.Information, AppName); errorcode = currenterrorcode; rebootrequired = true; break; default: Logger.Log(String.Format(CultureInfo.InvariantCulture, "Exitcode: {0} Returned Error code: {1}", errorcode.ToString(CultureInfo.InvariantCulture), currenterrorcode.ToString(CultureInfo.InvariantCulture)), Logger.MessageLevel.Information, AppName); errorcode = errorcode == 3010 ? errorcode : currenterrorcode; break; } break; } } } } } } if ( (errorcode != 0 || errorcode != 3010) // Did we get a non-zero error code && DidInstallRun // Was an installer run? ) // If so, we need to break the loop as the user likely has an action to take { // Allow reboot required to drop out like a success. This will allow all pre-requisite installers to complete regardless of a reboot being required. // - Break out on all other error codes. Any other status is a hard error that needs to be handled outside of this process. break; } } errorcode = errorcode != 0 ? errorcode : rebootrequired ? 3010 : errorcode; return errorcode; }
public void BundleConstructorTest() { Bundle bundle = new Bundle(); Assert.IsTrue(bundle.BundleId == Guid.Empty); }