public void DeleteRecord() { string dbFile = "DeleteRecord.msi"; using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db); WindowsInstallerUtils.CreateTestProduct(db); string query = "SELECT `Property`, `Value` FROM `Property` WHERE `Property` = 'UpgradeCode'"; using (View view = db.OpenView(query)) { view.Execute(); Record rec = view.Fetch(); Console.WriteLine("Calling ToString() : " + rec); view.Delete(rec); } Assert.AreEqual(0, db.ExecuteStringQuery(query).Count); } }
public void AutoGenInstanceProductCode() { string sourceFile = Path.Combine(InstanceTransformTests.TestDataDirectory, @"AutoGenInstanceProductCode\product.wxs"); string msi = Builder.BuildPackage(sourceFile); // Verify that an instance transforms was created string transformName = "Instance1.mst"; string mst = Path.Combine(Path.GetDirectoryName(msi), transformName); // Extract the transform InstanceTransformTests.ExtractTransform(msi, transformName, mst); // Verify that the base product code is the expected value Verifier.VerifyQuery(msi, "Select `Value` FROM `Property` WHERE `Property` = 'ProductCode'", "{4014E041-A968-4DE3-B43C-322DF9A19359}"); // Verify that the transform changes the product code using (Database msiDatabase = new Database(msi, DatabaseOpenMode.ReadOnly)) { msiDatabase.ApplyTransform(mst); string transformProductCode = null; using (View view = msiDatabase.OpenView("Select `Value` FROM `Property` WHERE `Property` = 'ProductCode'")) { view.Execute(); var record = view.Fetch(); if (null != record) { transformProductCode = Convert.ToString(record.GetString(1)); } } Assert.False("{4014E041-A968-4DE3-B43C-322DF9A19359}".Equals(transformProductCode), "The product code was not transformed by the instance transform."); } }
/// <summary> /// Get Msi Property /// </summary> /// <param name="database"></param> /// <param name="propertyName"></param> /// <returns></returns> private static string GetMsiProperty(Database database, string propertyName) { using (View view = database.OpenView("SELECT Value FROM Property WHERE Property.Property='{0}'", propertyName)) { view.Execute(); using (Record record = view.Fetch()) { return record[1].ToString(); } } }
public void FileTableRecordAdapted() { var path = Path.Combine(this.TestContext.DeploymentDirectory, "Example.msi"); using (var db = new Database(path, DatabaseOpenMode.ReadOnly)) { var query = db.Tables["File"].SqlSelectString; using (var view = db.OpenView(query)) { view.Execute(); var columns = ViewManager.GetColumns(view); // Fetch and test a single record. using (var record = view.Fetch()) { Assert.IsNotNull(record, "No record was found."); var copy = new Record(record, columns); var adapter = new RecordPropertyAdapter(); var properties = adapter.GetProperties(copy); Assert.IsNotNull(properties, "The properties were not adapted."); Assert.AreEqual<int>(8, properties.Count, "The number of columns are incorrect."); var property = adapter.GetProperty(copy, "FileName"); var type = typeof(string).FullName; Assert.IsNotNull(property, "The FileName property was not adapted."); Assert.IsTrue(adapter.IsGettable(property), "The FileName property is not gettable."); Assert.AreEqual(type, adapter.GetPropertyTypeName(property), true, "The FileName property type is incorrect."); Assert.AreEqual("product.wxs", RecordPropertyAdapter.GetPropertyValue(property, copy) as string, "The FileName propert value is incorrect."); property = adapter.GetProperty(copy, "Attributes"); type = typeof(AttributeColumn).FullName; Assert.IsNotNull(property, "The Attributes property was not adapted."); Assert.AreEqual(type, adapter.GetPropertyTypeName(property), true, "The Attributes property type is incorrect."); Assert.AreEqual<short>(512, Convert.ToInt16(RecordPropertyAdapter.GetPropertyValue(property, copy)), "The Attributes propert value is incorrect."); property = adapter.GetProperty(copy, "Sequence"); type = typeof(int).FullName; Assert.IsNotNull(property, "The Sequence property was not adapted."); Assert.AreEqual("System.Int32", adapter.GetPropertyTypeName(property), true, "The Sequence property type is incorrect."); Assert.AreEqual<int>(1, Convert.ToInt32(RecordPropertyAdapter.GetPropertyValue(property, copy)), "The Sequence propert value is incorrect."); } } } }
public void InstallerViewTables() { string dbFile = "InstallerViewTables.msi"; using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db); db.Commit(); using (View view1 = db.OpenView("SELECT `Property`, `Value` FROM `Property` WHERE `Value` IS NOT NULL")) { IList<TableInfo> viewTables = view1.Tables; Assert.IsNotNull(viewTables); Assert.AreEqual<int>(1, viewTables.Count); Assert.AreEqual<String>("Property", viewTables[0].Name); } using (View view2 = db.OpenView("INSERT INTO `Property` (`Property`, `Value`) VALUES ('TestViewTables', 1)")) { IList<TableInfo> viewTables = view2.Tables; Assert.IsNotNull(viewTables); Assert.AreEqual<int>(1, viewTables.Count); Assert.AreEqual<String>("Property", viewTables[0].Name); } using (View view3 = db.OpenView("UPDATE `Property` SET `Value` = 2 WHERE `Property` = 'TestViewTables'")) { IList<TableInfo> viewTables = view3.Tables; Assert.IsNotNull(viewTables); Assert.AreEqual<int>(1, viewTables.Count); Assert.AreEqual<String>("Property", viewTables[0].Name); } using (View view4 = db.OpenView("alter table Property hold")) { IList<TableInfo> viewTables = view4.Tables; Assert.IsNotNull(viewTables); Assert.AreEqual<int>(1, viewTables.Count); Assert.AreEqual<String>("Property", viewTables[0].Name); } } }
internal TableInfo(Database db, string name) { if (db == null) { throw new ArgumentNullException("db"); } if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } this.name = name; using (View columnsView = db.OpenView("SELECT * FROM `{0}`", name)) { this.columns = new ColumnCollection(columnsView); } this.primaryKeys = new ReadOnlyCollection<string>( TableInfo.GetTablePrimaryKeys(db, name)); }
/// <summary> /// Performs a quick peek inside an MSI to see if it has our two properties. /// Hopefully, this will speed up our scanning of files. /// </summary> /// <param name="path"></param> /// <returns></returns> internal static bool HasCoAppProperties(string localPackagePath) { lock (typeof (MSIBase)) { try { using (var database = new Database(localPackagePath, DatabaseOpenMode.ReadOnly)) { using (var view = database.OpenView("SELECT Value FROM Property WHERE Property='CoAppPackageFeed' OR Property='CoAppCompositionData'")) { view.Execute(); return view.Count() == 2; } } } catch { return false; } } }
private string GetUpgradeCode(string installSource) { if (File.Exists(installSource)) { try { using (var database = new Database(installSource, DatabaseOpenMode.ReadOnly)) { using (var view = database.OpenView(database.Tables["Property"].SqlSelectString)) { view.Execute(); foreach (var rec in view) { if ("UpgradeCode".Equals(rec.GetString("Property"), StringComparison.OrdinalIgnoreCase)) { return rec.GetString("Value"); } } } } } catch(Exception e) { Logger.Log(e); } } else { Logger.Log(string.Format("The {0} doesn't exist, cannot find upgrade code.", installSource)); } return string.Empty; }
public void RecordIsReadOnly() { var path = Path.Combine(this.TestContext.DeploymentDirectory, "Example.msi"); using (var db = new Database(path, DatabaseOpenMode.ReadOnly)) { var query = db.Tables["File"].SqlSelectString; using (var view = db.OpenView(query)) { view.Execute(); var columns = ViewManager.GetColumns(view); // Fetch and test a single record. using (var record = view.Fetch()) { Assert.IsNotNull(record, "No record was found."); var copy = new Record(record, columns); var adapter = new RecordPropertyAdapter(); var property = adapter.GetProperty(copy, "FileName"); Assert.IsFalse(adapter.IsSettable(property), "The FileName property is settable."); // Throws NotSupportedException. adapter.SetPropertyValue(property, "test.wxs"); } } } }
/// <summary> /// Query an MSI table for all records /// </summary> /// <param name="msi">The path to an MSI</param> /// <param name="sql">An MSI query</param> /// <returns>A list of records is returned</returns> /// <remarks>Uses DTF</remarks> public static List<DTF.Record> QueryAllRecords(string msi, string query) { List<DTF.Record> result = new List<DTF.Record>(); using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { using (DTF.View view = database.OpenView(query,null)) { view.Execute(); DTF.Record record = null; while (null != (record = view.Fetch())) { // Copy record created by Fetch to record created manually to remove View reference DTF.Record copyRecord = new DTF.Record(record.FieldCount); for (int i = 0; i <= record.FieldCount; i++) { copyRecord[i] = record[i]; } record.Close(); result.Add(copyRecord); } } } return result; }
protected bool GetSummaryInfoDiff(Database db1, Database db2, string[] options, TextWriter diffOutput, string linePrefix, IDiffEngineFactory diffFactory) { bool difference = false; SummaryInfo summInfo1 = db1.SummaryInfo; SummaryInfo summInfo2 = db2.SummaryInfo; if(summInfo1.Title != summInfo2.Title ) { diffOutput.WriteLine("{0}SummaryInformation.Title {{{1}}}->{{{2}}}", linePrefix, summInfo1.Title, summInfo2.Title); difference = true; } if(summInfo1.Subject != summInfo2.Subject ) { diffOutput.WriteLine("{0}SummaryInformation.Subject {{{1}}}->{{{2}}}", linePrefix, summInfo1.Subject, summInfo2.Subject); difference = true; } if(summInfo1.Author != summInfo2.Author ) { diffOutput.WriteLine("{0}SummaryInformation.Author {{{1}}}->{{{2}}}", linePrefix, summInfo1.Author, summInfo2.Author); difference = true; } if(summInfo1.Keywords != summInfo2.Keywords ) { diffOutput.WriteLine("{0}SummaryInformation.Keywords {{{1}}}->{{{2}}}", linePrefix, summInfo1.Keywords, summInfo2.Keywords); difference = true; } if(summInfo1.Comments != summInfo2.Comments ) { diffOutput.WriteLine("{0}SummaryInformation.Comments {{{1}}}->{{{2}}}", linePrefix, summInfo1.Comments, summInfo2.Comments); difference = true; } if(summInfo1.Template != summInfo2.Template ) { diffOutput.WriteLine("{0}SummaryInformation.Template {{{1}}}->{{{2}}}", linePrefix, summInfo1.Template, summInfo2.Template); difference = true; } if(summInfo1.LastSavedBy != summInfo2.LastSavedBy ) { diffOutput.WriteLine("{0}SummaryInformation.LastSavedBy {{{1}}}->{{{2}}}", linePrefix, summInfo1.LastSavedBy, summInfo2.LastSavedBy); difference = true; } if(summInfo1.RevisionNumber != summInfo2.RevisionNumber) { diffOutput.WriteLine("{0}SummaryInformation.RevisionNumber {{{1}}}->{{{2}}}", linePrefix, summInfo1.RevisionNumber, summInfo2.RevisionNumber); difference = true; } if(summInfo1.CreatingApp != summInfo2.CreatingApp ) { diffOutput.WriteLine("{0}SummaryInformation.CreatingApp {{{1}}}->{{{2}}}", linePrefix, summInfo1.CreatingApp, summInfo2.CreatingApp); difference = true; } if(summInfo1.LastPrintTime != summInfo2.LastPrintTime ) { diffOutput.WriteLine("{0}SummaryInformation.LastPrintTime {{{1}}}->{{{2}}}", linePrefix, summInfo1.LastPrintTime, summInfo2.LastPrintTime); difference = true; } if(summInfo1.CreateTime != summInfo2.CreateTime ) { diffOutput.WriteLine("{0}SummaryInformation.CreateTime {{{1}}}->{{{2}}}", linePrefix, summInfo1.CreateTime, summInfo2.CreateTime); difference = true; } if(summInfo1.LastSaveTime != summInfo2.LastSaveTime ) { diffOutput.WriteLine("{0}SummaryInformation.LastSaveTime {{{1}}}->{{{2}}}", linePrefix, summInfo1.LastSaveTime, summInfo2.LastSaveTime); difference = true; } if(summInfo1.CodePage != summInfo2.CodePage ) { diffOutput.WriteLine("{0}SummaryInformation.Codepage {{{1}}}->{{{2}}}", linePrefix, summInfo1.CodePage, summInfo2.CodePage); difference = true; } if(summInfo1.PageCount != summInfo2.PageCount ) { diffOutput.WriteLine("{0}SummaryInformation.PageCount {{{1}}}->{{{2}}}", linePrefix, summInfo1.PageCount, summInfo2.PageCount); difference = true; } if(summInfo1.WordCount != summInfo2.WordCount ) { diffOutput.WriteLine("{0}SummaryInformation.WordCount {{{1}}}->{{{2}}}", linePrefix, summInfo1.WordCount, summInfo2.WordCount); difference = true; } if(summInfo1.CharacterCount != summInfo2.CharacterCount) { diffOutput.WriteLine("{0}SummaryInformation.CharacterCount {{{1}}}->{{{2}}}", linePrefix, summInfo1.CharacterCount, summInfo2.CharacterCount); difference = true; } if(summInfo1.Security != summInfo2.Security ) { diffOutput.WriteLine("{0}SummaryInformation.Security {{{1}}}->{{{2}}}", linePrefix, summInfo1.Security, summInfo2.Security); difference = true; } summInfo1.Close(); summInfo2.Close(); return difference; }
public static void InitializeProductDatabase(Database db, bool sixtyFourBit) { db.SummaryInfo.CodePage = (short) Encoding.Default.CodePage; db.SummaryInfo.Title = "Windows Installer Test"; db.SummaryInfo.Subject = db.SummaryInfo.Title; db.SummaryInfo.Author = typeof(WindowsInstallerUtils).Assembly.FullName; db.SummaryInfo.CreatingApp = db.SummaryInfo.Author; db.SummaryInfo.Comments = typeof(WindowsInstallerUtils).FullName + ".CreateBasicDatabase()"; db.SummaryInfo.Keywords = "Installer,MSI,Database"; db.SummaryInfo.PageCount = 300; db.SummaryInfo.WordCount = 0; db.SummaryInfo.RevisionNumber = Guid.NewGuid().ToString("B").ToUpper(); db.SummaryInfo.Template = (sixtyFourBit ? "x64" : "Intel") + ";0"; foreach (TableInfo tableInfo in Schema.Tables) { db.Execute(tableInfo.SqlCreateString); } db.Execute("INSERT INTO `Directory` (`Directory`, `DefaultDir`) VALUES ('TARGETDIR', 'SourceDir')"); db.Execute("INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) VALUES ('ProgramFilesFolder', 'TARGETDIR', '.')"); foreach (Action action in Sequence.InstallExecute) { db.Execute("INSERT INTO `InstallExecuteSequence` (`Action`, `Sequence`) VALUES ('{0}', {1})", action.Name, action.Sequence); } }
public static void AddFileComponent(Database db, string featureName, string compName, string compId, string fileKey, string fileName) { db.Execute( "INSERT INTO `Component` " + "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " + "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')", compName, compId, "TestDir", (int) ComponentAttributes.None, fileKey); db.Execute( "INSERT INTO `File` " + "(`File`, `Component_`, `FileName`, `FileSize`, `Attributes`, `Sequence`) " + "VALUES ('{0}', '{1}', '{2}', 1, 0, 1)", fileKey, compName, fileName); db.Execute( "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')", featureName, compName); }
public static void AddRegistryComponent(Database db, string featureName, string compName, string compId, string keyName, string keyValueName, string value) { db.Execute( "INSERT INTO `Component` " + "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " + "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')", compName, compId, "TestDir", (int) ComponentAttributes.RegistryKeyPath, compName + "Reg1"); db.Execute( "INSERT INTO `Registry` (`Registry`, `Root`, `Key`, `Name`, `Value`, `Component_`) VALUES ('{0}', {1}, '{2}', '{3}', '{4}', '{5}')", compName + "Reg1", -1, @"Software\Microsoft\Windows Installer Test\" + keyName, keyValueName, value, compName); db.Execute( "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')", featureName, compName); }
/// <summary> /// Query an MSI table for all records /// </summary> /// <param name="msi">The path to an MSI</param> /// <param name="sql">An MSI query</param> /// <returns>A list of records is returned</returns> /// <remarks>Uses DTF</remarks> public static List <DTF.Record> QueryAllRecords(string msi, string query) { List <DTF.Record> result = new List <DTF.Record>(); using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { using (DTF.View view = database.OpenView(query, null)) { view.Execute(); DTF.Record record = null; while (null != (record = view.Fetch())) { // Copy record created by Fetch to record created manually to remove View reference DTF.Record copyRecord = new DTF.Record(record.FieldCount); for (int i = 0; i <= record.FieldCount; i++) { copyRecord[i] = record[i]; } record.Close(); result.Add(copyRecord); } } } return(result); }
public void CreateTransformSummaryInfo( Database referenceDatabase, string transformFile, TransformErrors errors, TransformValidations validations) { if (referenceDatabase == null) { throw new ArgumentNullException("referenceDatabase"); } if (String.IsNullOrEmpty(transformFile)) { throw new ArgumentNullException("transformFile"); } uint ret = NativeMethods.MsiCreateTransformSummaryInfo( (int) this.Handle, (int) referenceDatabase.Handle, transformFile, (int) errors, (int) validations); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
public void InstallerDatabaseSchema() { string dbFile = "InstallerDatabaseSchema.msi"; using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db); db.Commit(); } Assert.IsTrue(File.Exists(dbFile), "Checking whether created database file " + dbFile + " exists."); using (Database db = new Database(dbFile, DatabaseOpenMode.ReadOnly)) { TableCollection tables = db.Tables; Assert.AreEqual<int>(Schema.Tables.Count, tables.Count, "Counting tables."); Assert.AreEqual<int>(Schema.Property.Columns.Count, tables["Property"].Columns.Count, "Counting columns in Property table."); foreach (TableInfo tableInfo in tables) { Console.WriteLine(tableInfo.Name); foreach (ColumnInfo columnInfo in tableInfo.Columns) { Console.WriteLine("\t{0} {1}", columnInfo.Name, columnInfo.ColumnDefinitionString); } } } }
public static void AddFeature(Database db, string featureName) { db.Execute( "INSERT INTO `Feature` (`Feature`, `Title`, `Level`, `Attributes`) VALUES ('{0}', '{1}', {2}, {3})", featureName, featureName, 1, (int) FeatureAttributes.None); }
public string GetMsiProductCode(string msiFilePath) { if (string.IsNullOrEmpty(msiFilePath)) throw new ArgumentNullException("msiFilePath"); if (!File.Exists(msiFilePath)) throw new FileNotFoundException("msi file not found", msiFilePath); using (var database = new Database(msiFilePath, DatabaseOpenMode.ReadOnly)) { return GetMsiProperty(database, "ProductCode"); } }
/// <summary> /// Checks if a given table exists in the msi /// </summary> /// <param name="msi">The MSI to verify</param> /// <param name="tableName">The Name of the table to check for</param> /// <returns>True if the table exists in the msi, false otherwise</returns> public static bool CheckTableExists(string msi, string tableName) { bool tableExists = false; using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { tableExists = database.Tables.Contains(tableName); } return(tableExists); }
protected override void ProcessRecord() { #if USING_RESTABLE_CMDLET if(Remote) { ProcessRecordViaRest(); return; } #endif var wc = new WebClient(); var tmp = "coapp.tools.powershell.msi".GenerateTemporaryFilename(); if(Development) { wc.DownloadFile(@"http://downloads.coapp.org/files/Development.CoApp.Tools.Powershell.msi", tmp); } else if (Beta) { wc.DownloadFile(@"http://downloads.coapp.org/files/Beta.CoApp.Tools.Powershell.msi", tmp); } else { wc.DownloadFile(@"http://downloads.coapp.org/files/CoApp.Tools.Powershell.msi", tmp); } FourPartVersion ver = FileVersionInfo.GetVersionInfo(tmp); if (ver == 0) { using (Database db = new Database(tmp)) { ver = db.ExecuteScalar("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'") as string; } } FourPartVersion thisVer = this.Assembly().Version(); if (ver < thisVer) { WriteObject("The current version {0} is newer than the version on the web {1}.".format( thisVer, ver)); return; } if(ver == thisVer) { WriteObject("The current version {0} is the current version.".format(thisVer, ver)); return; } WriteObject("The current version {0} will be replaced with the newer than the version from the web {1}.".format(thisVer, ver)); using (dynamic ps = Runspace.DefaultRunspace.Dynamic()) { ps.InvokeExpression(@"msiexec.exe /i ""{0}""".format(tmp)); } if (!KillPowershells) { WriteObject("FYI, the installer can't actually update without killing all the powershell tasks."); WriteObject("If you are running as admin, you can do this automatically with the -KillPowershells switch on this command."); } else { using (var ps = Runspace.DefaultRunspace.Dynamic()) { ps.StopProcess(name: "powershell"); } } }
public virtual bool GetDiff(string diffInput1, string diffInput2, string[] options, TextWriter diffOutput, string linePrefix, IDiffEngineFactory diffFactory) { bool difference = false; Database db1 = new Database(diffInput1, DatabaseOpenMode.ReadOnly); Database db2 = new Database(diffInput2, DatabaseOpenMode.ReadOnly); if(GetSummaryInfoDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; if(GetDatabaseDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; if(GetStreamsDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; db1.Close(); db2.Close(); return difference; }
protected bool GetDatabaseDiff(Database db1, Database db2, string[] options, TextWriter diffOutput, string linePrefix, IDiffEngineFactory diffFactory) { bool difference = false; string tempFile = Path.GetTempFileName(); if(db2.GenerateTransform(db1, tempFile)) { difference = true; Database db = db1; db.ViewTransform(tempFile); string row, column, change; using (View view = db.OpenView("SELECT `Table`, `Column`, `Row`, `Data`, `Current` " + "FROM `_TransformView` ORDER BY `Table`, `Row`")) { view.Execute(); foreach (Record rec in view) using (rec) { column = String.Format("{0} {1}", rec[1], rec[2]); change = ""; if (rec.IsNull(3)) { row = "<DDL>"; if (!rec.IsNull(4)) { change = "[" + rec[5] + "]: " + DecodeColDef(rec.GetInteger(4)); } } else { row = "[" + String.Join(",", rec.GetString(3).Split('\t')) + "]"; if (rec.GetString(2) != "INSERT" && rec.GetString(2) != "DELETE") { column = String.Format("{0}.{1}", rec[1], rec[2]); change = "{" + rec[5] + "}->{" + rec[4] + "}"; } } diffOutput.WriteLine("{0}{1,-25} {2} {3}", linePrefix, column, row, change); } } } File.Delete(tempFile); return difference; }
public void DatabaseAsQueryable() { using (Database db = new Database("testlinq.msi", DatabaseOpenMode.Create)) { WindowsInstallerUtils.InitializeProductDatabase(db); WindowsInstallerUtils.CreateTestProduct(db); var comps = from c in db.AsQueryable().Components select c; int count = 0; foreach (var c in comps) { Console.WriteLine(c); count++; } Assert.AreEqual<int>(1, count); } }
public static DataSet GetMSIData(string localPackagePath) { localPackagePath = localPackagePath.ToLower(); if (MSIData.ContainsKey(localPackagePath)) { return MSIData[localPackagePath]; } try { using (var database = new Database(localPackagePath, DatabaseOpenMode.ReadOnly)) { var dataSet = new DataSet(localPackagePath) {EnforceConstraints = false}; foreach (var t in database.Tables) { try { if (!t.Columns[0].IsTemporary) { if (SignificantTables.Any(tn => t.Name.IsWildcardMatch(tn))) { using (var dr = new MSIDataReader(database, t)) { dataSet.Tables.Add(t.Name).Load(dr); } } } } catch (Exception) { // some tables not play nice. } } // GS01: this seems hinkey too... the local package is sometimes getting added twice. prollly a race condition somewhere. if (MSIData.ContainsKey(localPackagePath)) { return MSIData[localPackagePath]; } MSIData.Add(localPackagePath, dataSet); return dataSet; } } catch (InstallerException) { throw new InvalidPackageException(InvalidReason.NotValidMSI, localPackagePath); } }
public bool GenerateTransform(Database referenceDatabase, string transformFile) { if (referenceDatabase == null) { throw new ArgumentNullException("referenceDatabase"); } if (String.IsNullOrEmpty(transformFile)) { throw new ArgumentNullException("transformFile"); } uint ret = NativeMethods.MsiDatabaseGenerateTransform((int) this.Handle, (int) referenceDatabase.Handle, transformFile, 0, 0); if (ret == (uint) NativeMethods.Error.NO_DATA) { return false; } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return true; }
/// <summary> /// Gets a complete list of external cabs referenced by the given installer database file. /// </summary> /// <returns>True upon completion of the task execution.</returns> public override bool Execute() { string databaseFile = this.database.ItemSpec; Object []args = { }; System.Collections.Generic.List<ITaskItem> cabNames = new System.Collections.Generic.List<ITaskItem>(); // If the file doesn't exist, no cabs to return, so exit now if (!File.Exists(databaseFile)) { return true; } using (Database database = new Database(databaseFile)) { // If the media table doesn't exist, no cabs to return, so exit now if (null == database.Tables["Media"]) { return true; } System.Collections.IList records = database.ExecuteQuery("SELECT `Cabinet` FROM `Media`", args); foreach (string cabName in records) { if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal)) { continue; } cabNames.Add(new TaskItem(Path.Combine(Path.GetDirectoryName(databaseFile), cabName))); } } this.cabList = cabNames.ToArray(); return true; }
/// <summary> /// Prepares to extract a Windows Installer MSI package contained in a stream. /// </summary> /// <param name="path">The path of the Windows Installer MSI package to be extracted.</param> /// <param name="target">The path to the directory to extract into.</param> /// <exception cref="IOException">The package is damaged.</exception> internal MsiExtractor([NotNull] string path, [NotNull] string target) : base(target) { #region Sanity checks if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); #endregion try { _database = new Database(path, DatabaseOpenMode.ReadOnly); ReadDirectories(); ReadFiles(); ReadCabinets(); UnitsTotal = _files.Values.Sum(x => x.Size); } #region Error handling catch (InstallerException ex) { // Wrap exception since only certain exception types are allowed throw new IOException(Resources.ArchiveInvalid, ex); } #endregion }
/// <summary> /// Gets the weight of a package given its path. /// </summary> /// <param name="path">The path to the package.</param> /// <returns>The weight of a package given its path or 0 if the package is missing.</returns> internal static long GetWeightFromPath(string path) { if (File.Exists(path)) { var weight = 0L; using (var db = new Database(path, DatabaseOpenMode.ReadOnly)) { // Get the total size of all files in the package. if (null != db.Tables["File"]) { weight += db.ExecuteIntegerQuery(PackageInfo.FileSizeQuery).Sum(i => i); } // TODO: Should the weight of the registry be taken into account? // Storage isn't documented but it's probably a safe assumption value names and string data are double byte. // Sum up reserve costs for local installs (source installs are uncommon). if (null != db.Tables["ReserveCost"]) { weight += db.ExecuteIntegerQuery(PackageInfo.ReserveCostSizeQuery).Sum(i => i); } } // Use weight of package. May include just custom actions. if (0 >= weight) { var file = new FileInfo(path); weight = file.Length; } return weight; } return 0; }
public void InstallerTransactTwoProducts() { string dbFile1 = "InstallerTransactProduct1.msi"; string dbFile2 = "InstallerTransactProduct2.msi"; string productCode1; string productCode2; using (Database db1 = new Database(dbFile1, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db1); WindowsInstallerUtils.CreateTestProduct(db1); productCode1 = db1.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0]; db1.Commit(); } using (Database db2 = new Database(dbFile2, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db2); WindowsInstallerUtils.CreateTestProduct(db2); productCode2 = db2.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0]; db2.Commit(); } ProductInstallation installation1 = new ProductInstallation(productCode1); ProductInstallation installation2 = new ProductInstallation(productCode2); Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed before starting."); Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed before starting."); Installer.SetInternalUI(InstallUIOptions.Silent); ExternalUIHandler prevHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUILogger, InstallLogModes.FatalExit | InstallLogModes.Error | InstallLogModes.Warning | InstallLogModes.User | InstallLogModes.Info | InstallLogModes.ResolveSource | InstallLogModes.OutOfDiskSpace | InstallLogModes.ActionStart | InstallLogModes.ActionData | InstallLogModes.CommonData | InstallLogModes.Progress | InstallLogModes.Initialize | InstallLogModes.Terminate | InstallLogModes.ShowDialog); Assert.IsNull(prevHandler, "Checking that returned previous UI handler is null."); Transaction transaction = new Transaction("TestInstallTransaction", TransactionAttributes.None); Exception caughtEx = null; try { Installer.InstallProduct(dbFile1, String.Empty); } catch (Exception ex) { caughtEx = ex; } Assert.IsNull(caughtEx, "Exception thrown while installing product 1: " + caughtEx); Console.WriteLine(); Console.WriteLine("==================================================================="); Console.WriteLine(); try { Installer.InstallProduct(dbFile2, String.Empty); } catch (Exception ex) { caughtEx = ex; } Assert.IsNull(caughtEx, "Exception thrown while installing product 2: " + caughtEx); transaction.Commit(); transaction.Close(); prevHandler = Installer.SetExternalUI(prevHandler, InstallLogModes.None); Assert.AreEqual<ExternalUIHandler>(WindowsInstallerTest.ExternalUILogger, prevHandler, "Checking that previously-set UI handler is returned."); Assert.IsTrue(installation1.IsInstalled, "Checking that product 1 is installed."); Assert.IsTrue(installation2.IsInstalled, "Checking that product 2 is installed."); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("==================================================================="); Console.WriteLine("==================================================================="); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); ExternalUIRecordHandler prevRecHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUIRecordLogger, InstallLogModes.FatalExit | InstallLogModes.Error | InstallLogModes.Warning | InstallLogModes.User | InstallLogModes.Info | InstallLogModes.ResolveSource | InstallLogModes.OutOfDiskSpace | InstallLogModes.ActionStart | InstallLogModes.ActionData | InstallLogModes.CommonData | InstallLogModes.Progress | InstallLogModes.Initialize | InstallLogModes.Terminate | InstallLogModes.ShowDialog); Assert.IsNull(prevRecHandler, "Checking that returned previous UI record handler is null."); transaction = new Transaction("TestUninstallTransaction", TransactionAttributes.None); try { Installer.InstallProduct(dbFile1, "REMOVE=All"); } catch (Exception ex) { caughtEx = ex; } Assert.IsNull(caughtEx, "Exception thrown while removing product 1: " + caughtEx); try { Installer.InstallProduct(dbFile2, "REMOVE=All"); } catch (Exception ex) { caughtEx = ex; } Assert.IsNull(caughtEx, "Exception thrown while removing product 2: " + caughtEx); transaction.Commit(); transaction.Close(); Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed after removing."); Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed after removing."); prevRecHandler = Installer.SetExternalUI(prevRecHandler, InstallLogModes.None); Assert.AreEqual<ExternalUIRecordHandler>(WindowsInstallerTest.ExternalUIRecordLogger, prevRecHandler, "Checking that previously-set UI record handler is returned."); }
/// <summary> /// Checks if a given table exists in the msi /// </summary> /// <param name="msi">The MSI to verify</param> /// <param name="tableName">The Name of the table to check for</param> /// <returns>True if the table exists in the msi, false otherwise</returns> public static bool CheckTableExists(string msi, string tableName) { bool tableExists = false; using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { tableExists = database.Tables.Contains(tableName); } return tableExists; }
public static Session OpenPackage(Database database, bool ignoreMachineState) { if (database == null) { throw new ArgumentNullException("database"); } return Installer.OpenPackage( String.Format(CultureInfo.InvariantCulture, "#{0}", database.Handle), ignoreMachineState); }