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."); } }
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 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); } } }
/// <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."); } } } }
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)); }
public void InstanceUpgradeCode() { string sourceFile = Path.Combine(InstanceTransformTests.TestDataDirectory, @"InstanceUpgradeCode\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 upgrade code is the expected value Verifier.VerifyQuery(msi, "Select `Value` FROM `Property` WHERE `Property` = 'UpgradeCode'", "{F907C172-70B8-4654-8D23-49FB3AE2ECB7}"); // Verify that the transform changes the upgrade code using (Database msiDatabase = new Database(msi, DatabaseOpenMode.ReadOnly)) { msiDatabase.ApplyTransform(mst); string transformUpgradeCode = null; using (View view = msiDatabase.OpenView("Select `Value` FROM `Property` WHERE `Property` = 'UpgradeCode'")) { view.Execute(); using (var record = view.Fetch()) { if (null != record) { transformUpgradeCode = Convert.ToString(record.GetString(1)); } } } Assert.True("{E8441024-BBDA-4D08-B8B1-039C269CD374}".Equals(transformUpgradeCode), "The upgrade code was not transformed by the instance transform."); } }
public static void CreateTestProduct(Database db) { Guid productGuid = Guid.NewGuid(); string[] properties = new string[] { "ProductCode", productGuid.ToString("B").ToUpper(), "UpgradeCode", UpgradeCode, "ProductName", "Windows Installer Test Product " + productGuid.ToString("P").ToUpper(), "ProductVersion", "1.0.0.0000", }; using (View view = db.OpenView("INSERT INTO `Property` (`Property`, `Value`) VALUES (?, ?)")) { using (Record rec = new Record(2)) { for (int i = 0; i < properties.Length; i += 2) { rec[1] = properties[i]; rec[2] = properties[i + 1]; view.Execute(rec); } } } int randomId = new Random().Next(10000); string productDir = "TestDir" + randomId; db.Execute( "INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) " + "VALUES ('TestDir', 'ProgramFilesFolder', 'TestDir|{0}:.')", productDir); string compId = Guid.NewGuid().ToString("B").ToUpper(); db.Execute( "INSERT INTO `Component` " + "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " + "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')", "TestRegComp1", compId, "TestDir", (int) ComponentAttributes.RegistryKeyPath, "TestReg1"); string productReg = "TestReg" + randomId; db.Execute( "INSERT INTO `Registry` (`Registry`, `Root`, `Key`, `Component_`) VALUES ('{0}', {1}, '{2}', '{3}')", "TestReg1", -1, @"Software\Microsoft\Windows Installer Test\" + productReg, "TestRegComp1"); db.Execute( "INSERT INTO `Feature` (`Feature`, `Title`, `Level`, `Attributes`) VALUES ('{0}', '{1}', {2}, {3})", "TestFeature1", "Test Feature 1", 1, (int) FeatureAttributes.None); db.Execute( "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')", "TestFeature1", "TestRegComp1"); }
private static IList<SoftwareTag> CollectPackageTags(Output bundle) { List<SoftwareTag> tags = new List<SoftwareTag>(); Table packageTable = bundle.Tables["ChainPackageInfo"]; if (null != packageTable) { Table payloadTable = bundle.Tables["PayloadInfo"]; RowDictionary<PayloadInfoRow> payloads = new RowDictionary<PayloadInfoRow>(payloadTable); foreach (Row row in packageTable.Rows) { Compiler.ChainPackageType packageType = (Compiler.ChainPackageType)Enum.Parse(typeof(Compiler.ChainPackageType), (string)row[1], true); if (Compiler.ChainPackageType.Msi == packageType) { string packagePayloadId = (string)row[2]; PayloadInfoRow payload = (PayloadInfoRow)payloads[packagePayloadId]; using (Database db = new Database(payload.FullFileName)) { if (db.Tables.Contains("SoftwareIdentificationTag")) { using (View view = db.OpenView("SELECT `Regid`, `UniqueId`, `Type` FROM `SoftwareIdentificationTag`")) { view.Execute(); while (true) { using (Record record = view.Fetch()) { if (null == record) { break; } TagType type = String.IsNullOrEmpty(record.GetString(3)) ? TagType.Unknown : (TagType)Enum.Parse(typeof(TagType), record.GetString(3)); tags.Add(new SoftwareTag() { Regid = record.GetString(1), Id = record.GetString(2), Type = type }); } } } } } } } } return tags; }
public MSIDataReader(Database msiDatabase, TableInfo tableInfo) { _database = msiDatabase; _tableInfo = tableInfo; _tableView = _database.OpenView(tableInfo.SqlSelectString); _tableView.Execute(); _enumerator = _tableView.GetEnumerator(); _columnCount = tableInfo.Columns.Count; }
public void SeekRecordThenTryFormatString() { string dbFile = "SeekRecordThenTryFormatString.msi"; using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db); WindowsInstallerUtils.CreateTestProduct(db); string parameterFormatString = "[1]"; string[] properties = new string[] { "SonGoku", "Over 9000", }; string query = "SELECT `Property`, `Value` FROM `Property`"; using (View view = db.OpenView(query)) { using (Record rec = new Record(2)) { rec[1] = properties[0]; rec[2] = properties[1]; rec.FormatString = parameterFormatString; Console.WriteLine("Record fields before seeking: " + rec[0] + " " + rec[1] + " " + rec[2]); view.Seek(rec); //TODO: Why does view.Seek remove the record fields? Console.WriteLine("Record fields after seeking: " + rec[0] + " " + rec[1] + " " + rec[2]); // After inserting, the format string is invalid. Assert.AreEqual(String.Empty, rec.ToString()); } } } }
public void InsertRecordThenTryFormatString() { string dbFile = "InsertRecordThenTryFormatString.msi"; using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect)) { WindowsInstallerUtils.InitializeProductDatabase(db); WindowsInstallerUtils.CreateTestProduct(db); string parameterFormatString = "[1]"; string[] properties = new string[] { "SonGoku", "Over 9000", }; string query = "SELECT `Property`, `Value` FROM `Property`"; using (View view = db.OpenView(query)) { using (Record rec = new Record(2)) { rec[1] = properties[0]; rec[2] = properties[1]; rec.FormatString = parameterFormatString; Console.WriteLine("Format String before inserting: " + rec.FormatString); view.Insert(rec); Console.WriteLine("Format String after inserting: " + rec.FormatString); // After inserting, the format string is invalid. Assert.AreEqual(String.Empty, rec.ToString()); // Setting the format string manually makes it valid again. rec.FormatString = parameterFormatString; Assert.AreEqual(properties[0], rec.ToString()); } } } }
/// <summary> /// Extracts a transform from an MSI /// </summary> /// <param name="msi">The MSI to extract from</param> /// <param name="transform">The name of the transform to extract</param> /// <param name="extractFile">The location to extract to</param> /// <remarks> /// Most of this code was copied from DTF's Microsoft.Deployment.WindowsInstaller.Package.PatchPackage class. /// </remarks> private static void ExtractTransform(string msi, string transform, string extractFile) { Database msiDatabase = new Database(msi, DatabaseOpenMode.ReadOnly); using (View view = msiDatabase.OpenView("SELECT `Name`, `Data` FROM `_Storages` WHERE `Name` = '{0}'", transform)) { view.Execute(); var record = view.Fetch(); if (record == null) { Assert.True(false, String.Format("Transform {0} not found in {1}", transform, msi)); } using (record) { Console.WriteLine("Extracting transform {0} to {1}", transform, extractFile); record.GetStream("Data", extractFile); } } }
/// <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 void WriteRecords(Database db, string path) { TransformView transform = null; if (db.Tables.Contains(TransformView.TableName)) { transform = new TransformView(db); } string query = null; try { query = this.GetQuery(db, path); } catch (PSArgumentException ex) { base.WriteError(ex.ErrorRecord); return; } if (!string.IsNullOrEmpty(query)) { 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) { // Create a locally cached copy of the record. var copy = new Record(record, columns, transform, path); var obj = PSObject.AsPSObject(copy); // Show only column properties by default. var memberSet = ViewManager.GetMemberSet(view); obj.Members.Add(memberSet, true); this.WriteObject(obj); } record = view.Fetch(); } } } else { foreach (var table in db.Tables) { if (db.IsTablePersistent(table.Name)) { var info = new TableInfo(table.Name, path, transform, this.Patch, this.Transform); var obj = PSObject.AsPSObject(info); this.WriteObject(obj); } } } }
/// <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; }
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"); } } } }
internal MergeException(Database db, string conflictsTableName) : base("Merge failed.") { if (conflictsTableName != null) { IList<string> conflictTableList = new List<string>(); IList<int> conflictCountList = new List<int>(); using (View view = db.OpenView("SELECT `Table`, `NumRowMergeConflicts` FROM `" + conflictsTableName + "`")) { view.Execute(); foreach (Record rec in view) using (rec) { conflictTableList.Add(rec.GetString(1)); conflictCountList.Add((int) rec.GetInteger(2)); } } this.conflictTables = conflictTableList; this.conflictCounts = conflictCountList; } }
protected bool GetStreamsDiff(Database db1, Database db2, string[] options, TextWriter diffOutput, string linePrefix, IDiffEngineFactory diffFactory) { bool difference = false; IList<string> streams1List = db1.ExecuteStringQuery("SELECT `Name` FROM `_Streams`"); IList<string> streams2List = db2.ExecuteStringQuery("SELECT `Name` FROM `_Streams`"); string[] streams1 = new string[streams1List.Count]; string[] streams2 = new string[streams2List.Count]; streams1List.CopyTo(streams1, 0); streams2List.CopyTo(streams2, 0); IComparer caseInsComp = CaseInsensitiveComparer.Default; Array.Sort(streams1, caseInsComp); Array.Sort(streams2, caseInsComp); for (int i1 = 0, i2 = 0; i1 < streams1.Length || i2 < streams2.Length; ) { int comp; if (i1 == streams1.Length) { comp = 1; } else if (i2 == streams2.Length) { comp = -1; } else { comp = caseInsComp.Compare(streams1[i1], streams2[i2]); } if(comp < 0) { diffOutput.WriteLine("{0}< {1}", linePrefix, streams1[i1]); i1++; difference = true; } else if(comp > 0) { diffOutput.WriteLine("{0}> {1}", linePrefix, streams2[i2]); i2++; difference = true; } else { if(streams1[i1] != ("" + ((char)5) + "SummaryInformation")) { string tempFile1 = Path.GetTempFileName(); string tempFile2 = Path.GetTempFileName(); using (View view = db1.OpenView(String.Format("SELECT `Data` FROM `_Streams` WHERE `Name` = '{0}'", streams1[i1]))) { view.Execute(); using (Record rec = view.Fetch()) { rec.GetStream(1, tempFile1); } } using (View view = db2.OpenView(String.Format("SELECT `Data` FROM `_Streams` WHERE `Name` = '{0}'", streams2[i2]))) { view.Execute(); using (Record rec = view.Fetch()) { rec.GetStream(1, tempFile2); } } IDiffEngine diffEngine = diffFactory.GetDiffEngine(tempFile1, tempFile2, options); StringWriter sw = new StringWriter(); if(diffEngine.GetDiff(tempFile1, tempFile2, options, sw, linePrefix + " ", diffFactory)) { diffOutput.WriteLine("{0}{1}", linePrefix, streams1[i1]); diffOutput.Write(sw.ToString()); difference = true; } File.Delete(tempFile1); File.Delete(tempFile2); } i1++; i2++; } } return difference; }
public static string GetProperty(Database db, string property) { string retval = ""; using (View view = db.OpenView("SELECT Property, Value FROM Property WHERE Property = '{0}'", property)) { view.Execute(); Record rec; if ((rec = view.Fetch()) != null) { retval = (string)rec["Value"]; } else { throw new Exception("Property '" + property + "' was not found in: " + db.FilePath); } } return retval; }
/// <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); }
internal MergeException(Database db, string conflictsTableName) : base("Merge failed.") { if (conflictsTableName != null) { IList <string> conflictTableList = new List <string>(); IList <int> conflictCountList = new List <int>(); using (View view = db.OpenView("SELECT `Table`, `NumRowMergeConflicts` FROM `" + conflictsTableName + "`")) { view.Execute(); foreach (Record rec in view) { using (rec) { conflictTableList.Add(rec.GetString(1)); conflictCountList.Add((int)rec.GetInteger(2)); } } } this.conflictTables = conflictTableList; this.conflictCounts = conflictCountList; } }
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)); }