public MapEntry(Record rec) { Id = rec[0]; InternalName = rec.GetString(1); Name = rec.GetString(5); Type = (MapType) rec[2]; PhaseParent = rec[18]; }
/// <summary> /// 获取当前数据库连接串 /// </summary> /// <returns></returns> public (bool b, string con) connetStr() { var du = new StringBuilder(); connection = Configs.getManger(database).ToRecord(); if (connection.Count == 0) { return(false, ""); } du.Append($"Server={connection.GetString("server")};"); du.Append($"userid={connection.GetString("username")};"); du.Append($"password={connection.GetString("password")};"); du.Append($"Database={connection.GetString("database")};"); du.Append($"port={connection.GetString("port")};"); du.Append(connection.GetString("connection")); return(true, du.ToString()); }
private void CreateColumnInfos() { const int MSICOLINFONAMES = 0; const int MSICOLINFOTYPES = 1; var colList = new List <ColumnInfo>(); Record namesRecord = null; Record typesRecord = null; try { _underlyingView.GetColumnInfo(MSICOLINFONAMES, out namesRecord); _underlyingView.GetColumnInfo(MSICOLINFOTYPES, out typesRecord); int fieldCount = namesRecord.GetFieldCount(); Debug.Assert(typesRecord.GetFieldCount() == fieldCount); for (int colIndex = 1; colIndex <= fieldCount; colIndex++) { colList.Add(new ColumnInfo(namesRecord.GetString(colIndex), typesRecord.GetString(colIndex))); } } finally { if (namesRecord != null) { namesRecord.Close(); } if (typesRecord != null) { typesRecord.Close(); } } _columns = colList.ToArray(); }
public void GetString() { Record record = Record.Of("foo", "bar"); Assert.Equal("bar", record.GetString("foo")); }
/// <summary> /// Unbind an MSI database file. /// </summary> /// <param name="databaseFile">The database file.</param> /// <param name="database">The opened database.</param> /// <param name="outputType">The type of output to create.</param> /// <param name="exportBasePath">The path where files should be exported.</param> /// <returns>The output representing the database.</returns> private Output UnbindDatabase(string databaseFile, Database database, OutputType outputType, string exportBasePath) { string modularizationGuid = null; Output output = new Output(SourceLineNumberCollection.FromFileName(databaseFile)); View validationView = null; // set the output type output.Type = outputType; // get the codepage database.Export("_ForceCodepage", this.TempFilesLocation, "_ForceCodepage.idt"); using (StreamReader sr = File.OpenText(Path.Combine(this.TempFilesLocation, "_ForceCodepage.idt"))) { string line; while (null != (line = sr.ReadLine())) { string[] data = line.Split('\t'); if (2 == data.Length) { output.Codepage = Convert.ToInt32(data[0], CultureInfo.InvariantCulture); } } } // get the summary information table using (SummaryInformation summaryInformation = new SummaryInformation(database)) { Table table = new Table(null, this.tableDefinitions["_SummaryInformation"]); for (int i = 1; 19 >= i; i++) { string value = summaryInformation.GetProperty(i); if (0 < value.Length) { Row row = table.CreateRow(output.SourceLineNumbers); row[0] = i; row[1] = value; } } output.Tables.Add(table); } try { // open a view on the validation table if it exists if (database.TableExists("_Validation")) { validationView = database.OpenView("SELECT * FROM `_Validation` WHERE `Table` = ? AND `Column` = ?"); } // get the normal tables using (View tablesView = database.OpenExecuteView("SELECT * FROM _Tables")) { Record tableRecord; while (null != (tableRecord = tablesView.Fetch())) { string tableName = tableRecord.GetString(1); using (View tableView = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName))) { Record rowRecord; Table table; TableDefinition tableDefinition; if (this.tableDefinitions.Contains(tableName)) { tableDefinition = this.tableDefinitions[tableName]; // TODO: verify table definitions // - error for different column name or data type // - warn for additional columns // - need extra info for new columns in standard tables (MSI 4.0 changes) } else // custom table { TableDefinition customTableDefinition = new TableDefinition(tableName, false, false); Hashtable customTablePrimaryKeys = new Hashtable(); Record customColumnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES); Record customColumnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES); int customColumnCount = customColumnNameRecord.GetFieldCount(); // index the primary keys using (Record primaryKeysRecord = database.PrimaryKeys(tableName)) { int primaryKeysFieldCount = primaryKeysRecord.GetFieldCount(); for (int i = 1; i <= primaryKeysFieldCount; i++) { customTablePrimaryKeys[primaryKeysRecord.GetString(i)] = null; } } for (int i = 1; i <= customColumnCount; i++) { string columnName = customColumnNameRecord.GetString(i); string idtType = customColumnTypeRecord.GetString(i); ColumnType columnType; int length; bool nullable; ColumnCategory columnCategory = ColumnCategory.Unknown; ColumnModularizeType columnModularizeType = ColumnModularizeType.None; bool primary = customTablePrimaryKeys.Contains(columnName); bool minValueSet = false; int minValue = -1; bool maxValueSet = false; int maxValue = -1; string keyTable = null; bool keyColumnSet = false; int keyColumn = -1; string category = null; string set = null; string description = null; // get the column type, length, and whether its nullable switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture)) { case 'i': columnType = ColumnType.Number; break; case 'l': columnType = ColumnType.Localized; break; case 's': columnType = ColumnType.String; break; case 'v': columnType = ColumnType.Object; break; default: // TODO: error columnType = ColumnType.Unknown; break; } length = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture); nullable = Char.IsUpper(idtType[0]); // try to get validation information if (null != validationView) { Record validationRecord = new Record(2); validationRecord.SetString(1, tableName); validationRecord.SetString(2, columnName); validationView.Execute(validationRecord); validationRecord.Close(); if (null != (validationRecord = validationView.Fetch())) { string validationNullable = validationRecord.GetString(3); minValueSet = !validationRecord.IsNull(4); minValue = (minValueSet ? validationRecord.GetInteger(4) : -1); maxValueSet = !validationRecord.IsNull(5); maxValue = (maxValueSet ? validationRecord.GetInteger(5) : -1); keyTable = (!validationRecord.IsNull(6) ? validationRecord.GetString(6) : null); keyColumnSet = !validationRecord.IsNull(7); keyColumn = (keyColumnSet ? validationRecord.GetInteger(7) : -1); category = (!validationRecord.IsNull(8) ? validationRecord.GetString(8) : null); set = (!validationRecord.IsNull(9) ? validationRecord.GetString(9) : null); description = (!validationRecord.IsNull(10) ? validationRecord.GetString(10) : null); // check the validation nullable value against the column definition if (null == validationNullable) { // TODO: warn for illegal validation nullable column } else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable)) { // TODO: warn for mismatch between column definition and validation nullable } // convert category to ColumnCategory if (null != category) { try { columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true); } catch (ArgumentException) { columnCategory = ColumnCategory.Unknown; } } validationRecord.Close(); } else { // TODO: warn about no validation information } } // guess the modularization type if ("Icon" == keyTable && 1 == keyColumn) { columnModularizeType = ColumnModularizeType.Icon; } else if ("Condition" == columnName) { columnModularizeType = ColumnModularizeType.Condition; } else if (ColumnCategory.Formatted == columnCategory) { columnModularizeType = ColumnModularizeType.Property; } else if (ColumnCategory.Identifier == columnCategory) { columnModularizeType = ColumnModularizeType.Column; } customTableDefinition.Columns.Add(new ColumnDefinition(columnName, columnType, length, primary, nullable, columnModularizeType, (ColumnType.Localized == columnType), minValueSet, minValue, maxValueSet, maxValue, keyTable, keyColumnSet, keyColumn, columnCategory, set, description, true, true)); } tableDefinition = customTableDefinition; customColumnNameRecord.Close(); customColumnTypeRecord.Close(); } table = new Table(null, tableDefinition); while (null != (rowRecord = tableView.Fetch())) { int recordCount = rowRecord.GetFieldCount(); Row row = table.CreateRow(output.SourceLineNumbers); for (int i = 0; recordCount > i && row.Fields.Length > i; i++) { if (rowRecord.IsNull(i + 1)) { if (!row.Fields[i].Column.IsNullable) { // TODO: display an error for a null value in a non-nullable field OR // display a warning and put an empty string in the value to let the compiler handle it // (the second option is risky because the later code may make certain assumptions about // the contents of a row value) } } else { switch (row.Fields[i].Column.Type) { case ColumnType.Number: if (row.Fields[i].Column.IsLocalizable) { row[i] = Convert.ToString(rowRecord.GetInteger(i + 1), CultureInfo.InvariantCulture); } else { row[i] = rowRecord.GetInteger(i + 1); } break; case ColumnType.Object: string sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES"; if (null != exportBasePath) { string relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.')); sourceFile = Path.Combine(exportBasePath, relativeSourceFile); // ensure the parent directory exists System.IO.Directory.CreateDirectory(Path.Combine(exportBasePath, tableName)); using (FileStream fs = System.IO.File.Create(sourceFile)) { int bytesRead; byte[] buffer = new byte[512]; while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length))) { fs.Write(buffer, 0, bytesRead); } } } row[i] = sourceFile; break; default: string value = rowRecord.GetString(i + 1); switch (row.Fields[i].Column.Category) { case ColumnCategory.Guid: value = value.ToUpper(CultureInfo.InvariantCulture); break; } // de-modularize if (!this.suppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType) { Regex modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}"); if (null == modularizationGuid) { Match match = modularization.Match(value); if (match.Success) { modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}'); } } value = modularization.Replace(value, String.Empty); } // escape "$(" for the preprocessor value = value.Replace("$(", "$$("); // escape things that look like wix variables MatchCollection matches = Common.WixVariableRegex.Matches(value); for (int j = matches.Count - 1; 0 <= j; j--) { value = value.Insert(matches[j].Index, "!"); } row[i] = value; break; } } } rowRecord.Close(); } output.Tables.Add(table); } tableRecord.Close(); } } } finally { if (null != validationView) { validationView.Close(); } } // set the modularization guid as the PackageCode if (null != modularizationGuid) { Table table = output.Tables["_SummaryInformation"]; foreach (Row row in table.Rows) { if (9 == (int)row[0]) // PID_REVNUMBER { row[1] = modularizationGuid; } } } return(output); }
private T GetResult(Record resultRec) { object[] results = new object[this.tables.Count]; for (int i = 0; i < this.tables.Count; i++) { string[] values = new string[this.tables[i].Columns.Count]; for (int j = 0; j < this.selectColumns.Count; j++) { TableColumn col = this.selectColumns[j]; if (col.Table.Name == this.tables[i].Name) { int index = this.tables[i].Columns.IndexOf( col.Column.Name); if (index >= 0) { if (col.Column.Type == typeof(Stream)) { values[index] = "[Binary Data]"; } else { values[index] = resultRec.GetString(j + 1); } } } } QRecord result = (QRecord)this.recordTypes[i] .GetConstructor(Type.EmptyTypes).Invoke(null); result.Database = this.db; result.TableInfo = this.tables[i]; result.Values = values; result.Exists = true; results[i] = result; } if (this.projectionDelegates.Count > 0) { object resultsProjection = results[0]; for (int i = 1; i <= results.Length; i++) { if (i < results.Length) { resultsProjection = this.projectionDelegates[i - 1] .DynamicInvoke(new object[] { resultsProjection, results[i] }); } else { resultsProjection = this.projectionDelegates[i - 1] .DynamicInvoke(resultsProjection); } } return((T)resultsProjection); } else { return((T)(object)results[0]); } }
private void FormatField(Record record, int column) { var value = record.GetString(column); record.SetString(column, m_session.Format(value)); }
/// <summary> /// Validate a database. /// </summary> /// <param name="databaseFile">The database to validate.</param> /// <returns>true if validation succeeded; false otherwise.</returns> public void Validate(string databaseFile) { Dictionary <string, string> indexedICEs = new Dictionary <string, string>(); Dictionary <string, string> indexedSuppressedICEs = new Dictionary <string, string>(); int previousUILevel = (int)InstallUILevels.Basic; IntPtr previousHwnd = IntPtr.Zero; InstallUIHandler previousUIHandler = null; if (null == databaseFile) { throw new ArgumentNullException("databaseFile"); } // initialize the validator extension this.extension.DatabaseFile = databaseFile; this.extension.Output = this.output; this.extension.InitializeValidator(); // if we don't have the temporary files object yet, get one if (null == this.tempFiles) { this.tempFiles = new TempFileCollection(); } Directory.CreateDirectory(this.TempFilesLocation); // ensure the base path is there // index the ICEs if (null != this.ices) { foreach (string ice in this.ices) { indexedICEs[ice] = null; } } // index the suppressed ICEs if (null != this.suppressedICEs) { foreach (string suppressedICE in this.suppressedICEs) { indexedSuppressedICEs[suppressedICE] = null; } } // copy the database to a temporary location so it can be manipulated string tempDatabaseFile = Path.Combine(this.TempFilesLocation, Path.GetFileName(databaseFile)); File.Copy(databaseFile, tempDatabaseFile); // remove the read-only property from the temporary database FileAttributes attributes = File.GetAttributes(tempDatabaseFile); File.SetAttributes(tempDatabaseFile, attributes & ~FileAttributes.ReadOnly); Mutex mutex = new Mutex(false, "WixValidator"); try { if (!mutex.WaitOne(0, false)) { this.OnMessage(WixVerboses.ValidationSerialized()); mutex.WaitOne(); } using (Database database = new Database(tempDatabaseFile, OpenDatabase.Direct)) { bool propertyTableExists = database.TableExists("Property"); string productCode = null; // remove the product code from the database before opening a session to prevent opening an installed product if (propertyTableExists) { using (View view = database.OpenExecuteView("SELECT `Value` FROM `Property` WHERE Property = 'ProductCode'")) { using (Record record = view.Fetch()) { if (null != record) { productCode = record.GetString(1); using (View dropProductCodeView = database.OpenExecuteView("DELETE FROM `Property` WHERE `Property` = 'ProductCode'")) { } } } } } // merge in the cube databases foreach (string cubeFile in this.cubeFiles) { try { using (Database cubeDatabase = new Database(cubeFile, OpenDatabase.ReadOnly)) { try { database.Merge(cubeDatabase, "MergeConflicts"); } catch { // ignore merge errors since they are expected in the _Validation table } } } catch (Win32Exception e) { if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED { throw new WixException(WixErrors.CubeFileNotFound(cubeFile)); } throw; } } // commit the database before proceeding to ensure the streams don't get confused database.Commit(); // the property table may have been added to the database // from a cub database without the proper validation rows if (!propertyTableExists) { using (View view = database.OpenExecuteView("DROP table `Property`")) { } } // get all the action names for ICEs which have not been suppressed List <string> actions = new List <string>(); using (View view = database.OpenExecuteView("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) { while (true) { using (Record record = view.Fetch()) { if (null == record) { break; } string action = record.GetString(1); if (!indexedSuppressedICEs.ContainsKey(action)) { actions.Add(action); } } } } if (0 != indexedICEs.Count) { // Walk backwards and remove those that arent in the list for (int i = actions.Count - 1; 0 <= i; i--) { if (!indexedICEs.ContainsKey(actions[i])) { actions.RemoveAt(i); } } } // disable the internal UI handler and set an external UI handler previousUILevel = Installer.SetInternalUI((int)InstallUILevels.None, ref previousHwnd); previousUIHandler = Installer.SetExternalUI(this.validationUIHandler, (int)InstallLogModes.Error | (int)InstallLogModes.Warning | (int)InstallLogModes.User, IntPtr.Zero); // create a session for running the ICEs this.validationSessionComplete = false; using (Session session = new Session(database)) { // add the product code back into the database if (null != productCode) { // some CUBs erroneously have a ProductCode property, so delete it if we just picked one up using (View dropProductCodeView = database.OpenExecuteView("DELETE FROM `Property` WHERE `Property` = 'ProductCode'")) { } using (View view = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "INSERT INTO `Property` (`Property`, `Value`) VALUES ('ProductCode', '{0}')", productCode))) { } } foreach (string action in actions) { this.actionName = action; try { session.DoAction(action); } catch (Win32Exception e) { if (!Messaging.Instance.EncounteredError) { throw e; } // TODO: Review why this was clearing the error state when an exception had happened but an error was already encountered. That's weird. //else //{ // this.encounteredError = false; //} } this.actionName = null; } // Mark the validation session complete so we ignore any messages that MSI may fire // during session clean-up. this.validationSessionComplete = true; } } } catch (Win32Exception e) { // avoid displaying errors twice since one may have already occurred in the UI handler if (!Messaging.Instance.EncounteredError) { if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED { // databaseFile is not passed since during light // this would be the temporary copy and there would be // no final output since the error occured; during smoke // they should know the path passed into smoke this.OnMessage(WixErrors.ValidationFailedToOpenDatabase()); } else if (0x64D == e.NativeErrorCode) { this.OnMessage(WixErrors.ValidationFailedDueToLowMsiEngine()); } else if (0x654 == e.NativeErrorCode) { this.OnMessage(WixErrors.ValidationFailedDueToInvalidPackage()); } else if (0x658 == e.NativeErrorCode) { this.OnMessage(WixErrors.ValidationFailedDueToMultilanguageMergeModule()); } else if (0x659 == e.NativeErrorCode) { this.OnMessage(WixWarnings.ValidationFailedDueToSystemPolicy()); } else { string msgTemp = e.Message; if (null != this.actionName) { msgTemp = String.Concat("Action - '", this.actionName, "' ", e.Message); } this.OnMessage(WixErrors.Win32Exception(e.NativeErrorCode, msgTemp)); } } } finally { Installer.SetExternalUI(previousUIHandler, 0, IntPtr.Zero); Installer.SetInternalUI(previousUILevel, ref previousHwnd); this.validationSessionComplete = false; // no validation session at this point, so reset the completion flag. mutex.ReleaseMutex(); this.cubeFiles.Clear(); this.extension.FinalizeValidator(); } }
/// <summary> /// Update multiple fields in the record (and the database). /// </summary> /// <param name="indexes">column indexes of fields to update</param> /// <param name="values">new values for each field being updated</param> /// <remarks> /// The record (primary keys) must already exist in the table. /// <para>Updating primary key fields is not yet implemented; use Delete() /// and Insert() instead.</para> /// </remarks> public void Update(IList <int> indexes, IList <string> values) { if (indexes == null) { throw new ArgumentNullException("indexes"); } if (values == null) { throw new ArgumentNullException("values"); } if (indexes.Count == 0 || values.Count == 0 || indexes.Count > this.FieldCount || values.Count != indexes.Count) { throw new ArgumentOutOfRangeException("indexes"); } bool primaryKeyChanged = false; for (int i = 0; i < indexes.Count; i++) { int index = indexes[i]; if (index < 0 || index >= this.FieldCount) { throw new ArgumentOutOfRangeException("index[" + i + "]"); } ColumnInfo col = this.TableInfo.Columns[index]; if (this.TableInfo.PrimaryKeys.Contains(col.Name)) { if (values[i] == null) { throw new ArgumentNullException("values[" + i + "]"); } primaryKeyChanged = true; } else if (values[i] == null) { if (col.IsRequired) { throw new ArgumentNullException("values[" + i + "]"); } } this.Values[index] = values[i]; } if (this.Exists) { if (!primaryKeyChanged) { int updateRecSize = indexes.Count + this.TableInfo.PrimaryKeys.Count; using (Record updateRec = this.Database.CreateRecord(updateRecSize)) { StringBuilder s = new StringBuilder("UPDATE `"); s.Append(this.TableInfo.Name); s.Append("` SET"); for (int i = 0; i < indexes.Count; i++) { ColumnInfo col = this.TableInfo.Columns[indexes[i]]; if (col.Type == typeof(Stream)) { throw new NotSupportedException( "Cannot update stream columns via QRecord."); } int index = indexes[i]; s.AppendFormat("{0} `{1}` = ?", (i > 0 ? "," : String.Empty), col.Name); if (values[i] != null) { updateRec[i + 1] = values[i]; } } for (int i = 0; i < this.TableInfo.PrimaryKeys.Count; i++) { string key = this.TableInfo.PrimaryKeys[i]; s.AppendFormat(" {0} `{1}` = ?", (i == 0 ? "WHERE" : "AND"), key); int index = this.TableInfo.Columns.IndexOf(key); updateRec[indexes.Count + i + 1] = this.Values[index]; } string updateSql = s.ToString(); TextWriter log = this.Database.Log; if (log != null) { log.WriteLine(); log.WriteLine(updateSql); for (int field = 1; field <= updateRecSize; field++) { log.WriteLine(" ? = " + updateRec.GetString(field)); } } this.Database.Execute(updateSql, updateRec); } } else { throw new NotImplementedException( "Update() cannot handle changed primary keys yet."); // TODO: // query using old values // update values // View.Replace } } }
public sealed override void SetData() { Id = Record.GetInt("id"); Name = Record.GetString("name"); GenerateInsertQuery(); }
User ToSession(Record r) { var user = new User(); user.Id = r.GetInt("id"); user.SessionId = r.GetString("sessionId"); user.Name = r.GetString("name"); user.IdAdmin = r.GetInt("idAdmin"); user.IdSuperAdmin = r.GetInt("idSuperAdmin"); user.IdCustomer = r.GetInt("idCustomer"); var tenant = LoadTenant(r.GetString("tenant")); user.Tenant = tenant; user.Culture = GetCulture(r.GetString("culture"), tenant); user.TimeZone = GetTimeZone(tenant); user.CreateDate = r.GetDateTime("createdate"); var items = r.GetString("items"); user.Items = !string.IsNullOrEmpty(items) ? Json.Deserialize<Map>(items) : new Map(); return user; }
Tenant ToTenant(Record r) { var tenant = new Tenant(); tenant.Name = r.GetString("name"); tenant.DisplayName = r.GetString("displayName"); var cultureName = r.GetString("culture"); tenant.Culture = cultureName != null ? new CultureInfo(cultureName) : CultureInfo.CurrentCulture; var timeZone = r.GetString("timeZone"); tenant.TimeZone = timeZone != null ? TimeZoneInfo.FindSystemTimeZoneById(timeZone) : TimeZoneInfo.Local; var items = r.GetString("items"); tenant.Items = !string.IsNullOrEmpty(items) ? Json.Deserialize<Map>(items) : new Map(); return tenant; }
/// <summary> /// Validate a database. /// </summary> /// <param name="databaseFile">The database to validate.</param> /// <returns>true if validation succeeded; false otherwise.</returns> public bool Validate(string databaseFile) { InstallUIHandler currentUIHandler = null; Hashtable indexedSuppressedICEs = new Hashtable(); int previousUILevel = (int)InstallUILevels.Basic; IntPtr previousHwnd = IntPtr.Zero; InstallUIHandler previousUIHandler = null; if (null == databaseFile) { throw new ArgumentNullException("databaseFile"); } // initialize the validator extension this.extension.DatabaseFile = databaseFile; this.extension.Output = this.output; this.extension.InitializeValidator(); // if we don't have the temporary files object yet, get one if (null == this.tempFiles) { this.tempFiles = new TempFileCollection(); } Directory.CreateDirectory(this.TempFilesLocation); // ensure the base path is there // index the suppressed ICEs if (null != this.suppressedICEs) { foreach (string suppressedICE in this.suppressedICEs) { indexedSuppressedICEs[suppressedICE] = null; } } // copy the database to a temporary location so it can be manipulated string tempDatabaseFile = Path.Combine(this.TempFilesLocation, Path.GetFileName(databaseFile)); File.Copy(databaseFile, tempDatabaseFile); // remove the read-only property from the temporary database FileAttributes attributes = File.GetAttributes(tempDatabaseFile); File.SetAttributes(tempDatabaseFile, attributes & ~FileAttributes.ReadOnly); try { using (Database database = new Database(tempDatabaseFile, OpenDatabase.Direct)) { bool propertyTableExists = database.TableExists("Property"); string productCode = null; // remove the product code from the database before opening a session to prevent opening an installed product if (propertyTableExists) { using (View view = database.OpenExecuteView("SELECT `Value` FROM `Property` WHERE Property = 'ProductCode'")) { Record record = null; try { if (null != (record = view.Fetch())) { productCode = record.GetString(1); using (View dropProductCodeView = database.OpenExecuteView("DELETE FROM `Property` WHERE `Property` = 'ProductCode'")) { } } } finally { if (null != record) { record.Close(); } } } } // merge in the cube databases foreach (string cubeFile in this.cubeFiles) { try { using (Database cubeDatabase = new Database(cubeFile, OpenDatabase.ReadOnly)) { try { database.Merge(cubeDatabase, "MergeConflicts"); } catch { // ignore merge errors since they are expected in the _Validation table } } } catch (Win32Exception e) { if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED { throw new WixException(WixErrors.CubeFileNotFound(cubeFile)); } throw; } } // commit the database before proceeding to ensure the streams don't get confused database.Commit(); // the property table may have been added to the database // from a cub database without the proper validation rows if (!propertyTableExists) { using (View view = database.OpenExecuteView("DROP table `Property`")) { } } // get all the action names for ICEs which have not been suppressed ArrayList actions = new ArrayList(); using (View view = database.OpenExecuteView("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) { Record record; while (null != (record = view.Fetch())) { string action = record.GetString(1); if (!indexedSuppressedICEs.Contains(action)) { actions.Add(action); } record.Close(); } } // disable the internal UI handler and set an external UI handler previousUILevel = Installer.SetInternalUI((int)InstallUILevels.None, ref previousHwnd); currentUIHandler = new InstallUIHandler(this.ValidationUIHandler); previousUIHandler = Installer.SetExternalUI(currentUIHandler, (int)InstallLogModes.Error | (int)InstallLogModes.Warning | (int)InstallLogModes.User, IntPtr.Zero); // create a session for running the ICEs using (Session session = new Session(database)) { // add the product code back into the database if (null != productCode) { using (View view = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "INSERT INTO `Property` (`Property`, `Value`) VALUES ('ProductCode', '{0}')", productCode))) { } } foreach (string action in actions) { session.DoAction(action); } } } } catch (Win32Exception e) { // avoid displaying errors twice since one may have already occurred in the UI handler if (!this.encounteredError) { this.OnMessage(WixErrors.Win32Exception(e.NativeErrorCode, e.Message)); } } finally { Installer.SetExternalUI(previousUIHandler, 0, IntPtr.Zero); Installer.SetInternalUI(previousUILevel, ref previousHwnd); // very important - this prevents the external UI delegate from being garbage collected too early GC.KeepAlive(currentUIHandler); this.cubeFiles.Clear(); this.extension.FinalizeValidator(); } return(!this.encounteredError); }
private static List <FeactureInstallTO> GetFeactureScriptDataBase(Session session, List <string> listFeactureNames) { string sFileName = string.Empty; try { List <FeactureInstallTO> listF; string sLevel = session["INSTALLLEVEL"]; listF = new List <FeactureInstallTO>(); FeactureInstallTO f; int i; string sQuery = "SELECT `Feature`.`Feature`, `Feature`.`Title`, `Feature`.`Display`, " + " `Component`.`Directory_`, `File`.`FileName` " + " FROM `FeatureComponents`, `Feature`, `Component`, `File` " + " WHERE `FeatureComponents`.`Feature_` = `Feature`.`Feature` " + " AND `FeatureComponents`.`Component_` = `Component`.`Component` " + " AND `File`.`Component_` = `Component`.`Component` " + " AND `Feature`.`RuntimeLevel` > 0 AND `Feature`.`Level` > 0 " + // " AND `Feature`.`Level` <= " + sLevel + " ORDER BY `Feature`.`Display`"; using (Microsoft.Deployment.WindowsInstaller.View v = session.Database.OpenView(sQuery)) { if (v != null) { v.Execute(); //var str = string.Empty; //foreach (var fea in listFeactureNames) // str += fea.ToString(); //MessageBox.Show(str); //str = string.Empty ; //var frm = new FeatureList( session,v,listFeactureNames); //frm.ShowDialog(); for (Record r = v.Fetch(); r != null; r = v.Fetch()) { if (listFeactureNames.Contains(r.GetString("Feature")) && r.GetString("FileName").ToUpper().EndsWith(".SQL")) { i = r.GetString("FileName").IndexOf("|"); if (i > 0) { sFileName = r.GetString("FileName").Substring(i + 1); } else { sFileName = r.GetString("FileName"); } f = new FeactureInstallTO() { Feature = r.GetString("Feature"), Title = r.GetString("Title"), DisplayOrder = r.GetInteger("Display"), FileName = sFileName, DirectoryPath = session.GetTargetPath(r.GetString("Directory_")) }; listF.Add(f); } r.Dispose(); } } } return(listF); } catch (Exception ex) { InstallUtilities.WriteLogInstall(session, "Fail to Read Feature Script", ex, true); throw; } }
public bool Execute() { // Keeps track of whether we've encountered at least one signed cab or not - we'll throw a warning if no signed cabs were encountered bool foundUnsignedExternals = false; bool shouldCommit = false; FileAttributes attributes = File.GetAttributes(this.Context.InputFilePath); if (FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly)) { this.Messaging.Write(ErrorMessages.ReadOnlyOutputFile(this.Context.InputFilePath)); return(shouldCommit); } using (Database database = new Database(this.Context.InputFilePath, OpenDatabase.Transact)) { // Just use the English codepage, because the tables we're importing only have binary streams / MSI identifiers / other non-localizable content int codepage = 1252; // list of certificates for this database (hash/identifier) Dictionary <string, string> certificates = new Dictionary <string, string>(); // Reset the in-memory tables for this new database Table digitalSignatureTable = new Table(this.TableDefinitions["MsiDigitalSignature"]); Table digitalCertificateTable = new Table(this.TableDefinitions["MsiDigitalCertificate"]); // If any digital signature records exist that are not of the media type, preserve them if (database.TableExists("MsiDigitalSignature")) { using (View digitalSignatureView = database.OpenExecuteView("SELECT `Table`, `SignObject`, `DigitalCertificate_`, `Hash` FROM `MsiDigitalSignature` WHERE `Table` <> 'Media'")) { while (true) { using (Record digitalSignatureRecord = digitalSignatureView.Fetch()) { if (null == digitalSignatureRecord) { break; } Row digitalSignatureRow = null; digitalSignatureRow = digitalSignatureTable.CreateRow(null); string table = digitalSignatureRecord.GetString(0); string signObject = digitalSignatureRecord.GetString(1); digitalSignatureRow[0] = table; digitalSignatureRow[1] = signObject; digitalSignatureRow[2] = digitalSignatureRecord.GetString(2); if (false == digitalSignatureRecord.IsNull(3)) { // Export to a file, because the MSI API's require us to provide a file path on disk string hashPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalSignature"); string hashFileName = string.Concat(table, ".", signObject, ".bin"); Directory.CreateDirectory(hashPath); hashPath = Path.Combine(hashPath, hashFileName); using (FileStream fs = File.Create(hashPath)) { int bytesRead; byte[] buffer = new byte[1024 * 4]; while (0 != (bytesRead = digitalSignatureRecord.GetStream(3, buffer, buffer.Length))) { fs.Write(buffer, 0, bytesRead); } } digitalSignatureRow[3] = hashFileName; } } } } } // If any digital certificates exist, extract and preserve them if (database.TableExists("MsiDigitalCertificate")) { using (View digitalCertificateView = database.OpenExecuteView("SELECT * FROM `MsiDigitalCertificate`")) { while (true) { using (Record digitalCertificateRecord = digitalCertificateView.Fetch()) { if (null == digitalCertificateRecord) { break; } string certificateId = digitalCertificateRecord.GetString(1); // get the identifier of the certificate // Export to a file, because the MSI API's require us to provide a file path on disk string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); Directory.CreateDirectory(certPath); certPath = Path.Combine(certPath, string.Concat(certificateId, ".cer")); using (FileStream fs = File.Create(certPath)) { int bytesRead; byte[] buffer = new byte[1024 * 4]; while (0 != (bytesRead = digitalCertificateRecord.GetStream(2, buffer, buffer.Length))) { fs.Write(buffer, 0, bytesRead); } } // Add it to our "add to MsiDigitalCertificate" table dictionary Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); digitalCertificateRow[0] = certificateId; // Now set the file path on disk where this binary stream will be picked up at import time digitalCertificateRow[1] = string.Concat(certificateId, ".cer"); // Load the cert to get it's thumbprint X509Certificate cert = X509Certificate.CreateFromCertFile(certPath); X509Certificate2 cert2 = new X509Certificate2(cert); certificates.Add(cert2.Thumbprint, certificateId); } } } } using (View mediaView = database.OpenExecuteView("SELECT * FROM `Media`")) { while (true) { using (Record mediaRecord = mediaView.Fetch()) { if (null == mediaRecord) { break; } X509Certificate2 cert2 = null; Row digitalSignatureRow = null; string cabName = mediaRecord.GetString(4); // get the name of the cab // If there is no cabinet or it's an internal cab, skip it. if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal)) { continue; } string cabId = mediaRecord.GetString(1); // get the ID of the cab string cabPath = Path.Combine(Path.GetDirectoryName(this.Context.InputFilePath), cabName); // If the cabs aren't there, throw an error but continue to catch the other errors if (!File.Exists(cabPath)) { this.Messaging.Write(ErrorMessages.WixFileNotFound(cabPath)); continue; } try { // Get the certificate from the cab X509Certificate signedFileCert = X509Certificate.CreateFromSignedFile(cabPath); cert2 = new X509Certificate2(signedFileCert); } catch (System.Security.Cryptography.CryptographicException e) { uint HResult = unchecked ((uint)Marshal.GetHRForException(e)); // If the file has no cert, continue, but flag that we found at least one so we can later give a warning if (0x80092009 == HResult) // CRYPT_E_NO_MATCH { foundUnsignedExternals = true; continue; } // todo: exactly which HRESULT corresponds to this issue? // If it's one of these exact platforms, warn the user that it may be due to their OS. if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3 (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP { this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); } else // otherwise, generic error { this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); } } // If we haven't added this cert to the MsiDigitalCertificate table, set it up to be added if (!certificates.ContainsKey(cert2.Thumbprint)) { // generate a stable identifier string certificateGeneratedId = Common.GenerateIdentifier("cer", cert2.Thumbprint); // Add it to our "add to MsiDigitalCertificate" table dictionary Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); digitalCertificateRow[0] = certificateGeneratedId; // Export to a file, because the MSI API's require us to provide a file path on disk string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); Directory.CreateDirectory(certPath); certPath = Path.Combine(certPath, string.Concat(cert2.Thumbprint, ".cer")); File.Delete(certPath); using (BinaryWriter writer = new BinaryWriter(File.Open(certPath, FileMode.Create))) { writer.Write(cert2.RawData); writer.Close(); } // Now set the file path on disk where this binary stream will be picked up at import time digitalCertificateRow[1] = string.Concat(cert2.Thumbprint, ".cer"); certificates.Add(cert2.Thumbprint, certificateGeneratedId); } digitalSignatureRow = digitalSignatureTable.CreateRow(null); digitalSignatureRow[0] = "Media"; digitalSignatureRow[1] = cabId; digitalSignatureRow[2] = certificates[cert2.Thumbprint]; } } } if (digitalCertificateTable.Rows.Count > 0) { var command = new CreateIdtFileCommand(this.Messaging, digitalCertificateTable, codepage, this.Context.IntermediateFolder, true); command.Execute(); database.Import(command.IdtPath); shouldCommit = true; } if (digitalSignatureTable.Rows.Count > 0) { var command = new CreateIdtFileCommand(this.Messaging, digitalSignatureTable, codepage, this.Context.IntermediateFolder, true); command.Execute(); database.Import(command.IdtPath); shouldCommit = true; } // TODO: if we created the table(s), then we should add the _Validation records for them. certificates = null; // If we did find external cabs but none of them were signed, give a warning if (foundUnsignedExternals) { this.Messaging.Write(WarningMessages.ExternalCabsAreNotSigned(this.Context.InputFilePath)); } if (shouldCommit) { database.Commit(); } } return(shouldCommit); }
public FileDataEntry(Record rec) { DataId = rec[0]; FileName = rec.GetString(1); FilePath = rec.GetString(2); }
public void GetNullString() { Record record = Record.Of("foo", null); Assert.Null(record.GetString("foo")); }
public void GetMissingString() { Record record = Record.Of(); Assert.Null(record.GetString("foo")); }
public sealed override void SetData() { Barcode = Record.GetString("barcode"); Name = Record.GetString("name"); GenerateInsertQuery(); }
public ProgressIndicator ProcessMessage(InstallMessage messageType, Record messageRecord) { switch (messageType) { case InstallMessage.ActionStart: if (this._enableActionData) { this._enableActionData = false; } // get the ActionStart message if (messageRecord.FieldCount > 1) { var message = messageRecord.GetString(2); if (!string.IsNullOrEmpty(message)) { this._lastMessage = message; } } return(new ProgressIndicator(this.Progress, this._lastMessage)); case InstallMessage.ActionData: if (this._enableActionData) { if (this._moveForward) { this._completed += this._step; } else { this._completed -= this._step; } } this.UpdateProgress(); if (messageRecord.FieldCount > 0) { // template is prefixed with the action name in double delimited braces var actionData = Regex.Replace(messageRecord.GetString(0), "{{.*}}", string.Empty); if (!string.IsNullOrEmpty(actionData)) { // Get the Actiondata fields and replace each placeholder in the ActionStart template // with the ActionData field value. The try/catch is needed here as the template may contain // a placeholder for an ActionData field value that does not exist. actionData = Regex.Replace(actionData, @"\[(?<num>\d+)\]", m => { var number = int.Parse(m.Groups["num"].Value); try { var value = messageRecord[number]; return(value?.ToString() ?? string.Empty); } catch { return(string.Empty); } }); this._lastMessage = actionData; } } return(new ProgressIndicator(this.Progress, this._lastMessage)); case InstallMessage.Progress: return(this.ProcessProgressMessage(messageRecord)); default: return(new ProgressIndicator(this.Progress, _lastMessage)); } }
public void Execute() { var fileTransfers = new List <FileTransfer>(); var directories = new Dictionary <string, ResolvedDirectory>(); var mediaRows = this.Section.Tuples.OfType <MediaTuple>().ToDictionary(t => t.DiskId); var wixMediaRows = this.Section.Tuples.OfType <WixMediaTuple>().ToDictionary(t => t.DiskId_); using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) { using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) { while (true) { using (Record directoryRecord = directoryView.Fetch()) { if (null == directoryRecord) { break; } string sourceName = Common.GetName(directoryRecord.GetString(3), true, this.LongNamesInImage); directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName)); } } } using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?")) { using (Record fileQueryRecord = new Record(1)) { // for each file in the array of uncompressed files foreach (FileFacade facade in this.FileFacades) { var mediaTuple = mediaRows[facade.WixFile.DiskId]; string relativeFileLayoutPath = null; string mediaLayoutFolder = null; if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; } var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); // setup up the query record and find the appropriate file in the // previously executed file view fileQueryRecord[1] = facade.File.File; fileView.Execute(fileQueryRecord); using (Record fileRecord = fileView.Fetch()) { if (null == fileRecord) { throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); } relativeFileLayoutPath = PathResolver.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); } // finally put together the base media layout path and the relative file layout path string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); if (FileTransfer.TryCreate(facade.WixFile.Source.Path, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out var transfer)) { fileTransfers.Add(transfer); } } } } } this.FileTransfers = fileTransfers; }
public Output Execute() { string modularizationGuid = null; Output output = new Output(new SourceLineNumber(this.DatabasePath)); View validationView = null; // set the output type output.Type = this.OutputType; // get the codepage this.Database.Export("_ForceCodepage", this.IntermediateFolder, "_ForceCodepage.idt"); using (StreamReader sr = File.OpenText(Path.Combine(this.IntermediateFolder, "_ForceCodepage.idt"))) { string line; while (null != (line = sr.ReadLine())) { string[] data = line.Split('\t'); if (2 == data.Length) { output.Codepage = Convert.ToInt32(data[0], CultureInfo.InvariantCulture); } } } // get the summary information table if it exists; it won't if unbinding a transform if (!this.SkipSummaryInfo) { using (SummaryInformation summaryInformation = new SummaryInformation(this.Database)) { Table table = new Table(this.TableDefinitions["_SummaryInformation"]); for (int i = 1; 19 >= i; i++) { string value = summaryInformation.GetProperty(i); if (0 < value.Length) { Row row = table.CreateRow(output.SourceLineNumbers); row[0] = i; row[1] = value; } } output.Tables.Add(table); } } try { // open a view on the validation table if it exists if (this.Database.TableExists("_Validation")) { validationView = this.Database.OpenView("SELECT * FROM `_Validation` WHERE `Table` = ? AND `Column` = ?"); } // get the normal tables using (View tablesView = this.Database.OpenExecuteView("SELECT * FROM _Tables")) { while (true) { using (Record tableRecord = tablesView.Fetch()) { if (null == tableRecord) { break; } string tableName = tableRecord.GetString(1); using (View tableView = this.Database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName))) { ColumnDefinition[] columns; using (Record columnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES), columnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES)) { // index the primary keys HashSet <string> tablePrimaryKeys = new HashSet <string>(); using (Record primaryKeysRecord = this.Database.PrimaryKeys(tableName)) { int primaryKeysFieldCount = primaryKeysRecord.GetFieldCount(); for (int i = 1; i <= primaryKeysFieldCount; i++) { tablePrimaryKeys.Add(primaryKeysRecord.GetString(i)); } } int columnCount = columnNameRecord.GetFieldCount(); columns = new ColumnDefinition[columnCount]; for (int i = 1; i <= columnCount; i++) { string columnName = columnNameRecord.GetString(i); string idtType = columnTypeRecord.GetString(i); ColumnType columnType; int length; bool nullable; ColumnCategory columnCategory = ColumnCategory.Unknown; ColumnModularizeType columnModularizeType = ColumnModularizeType.None; bool primary = tablePrimaryKeys.Contains(columnName); int? minValue = null; int? maxValue = null; string keyTable = null; int? keyColumn = null; string category = null; string set = null; string description = null; // get the column type, length, and whether its nullable switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture)) { case 'i': columnType = ColumnType.Number; break; case 'l': columnType = ColumnType.Localized; break; case 's': columnType = ColumnType.String; break; case 'v': columnType = ColumnType.Object; break; default: // TODO: error columnType = ColumnType.Unknown; break; } length = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture); nullable = Char.IsUpper(idtType[0]); // try to get validation information if (null != validationView) { using (Record validationRecord = new Record(2)) { validationRecord.SetString(1, tableName); validationRecord.SetString(2, columnName); validationView.Execute(validationRecord); } using (Record validationRecord = validationView.Fetch()) { if (null != validationRecord) { string validationNullable = validationRecord.GetString(3); minValue = validationRecord.IsNull(4) ? null : (int?)validationRecord.GetInteger(4); maxValue = validationRecord.IsNull(5) ? null : (int?)validationRecord.GetInteger(5); keyTable = validationRecord.IsNull(6) ? null : validationRecord.GetString(6); keyColumn = validationRecord.IsNull(7) ? null : (int?)validationRecord.GetInteger(7); category = validationRecord.IsNull(8) ? null : validationRecord.GetString(8); set = validationRecord.IsNull(9) ? null : validationRecord.GetString(9); description = validationRecord.IsNull(10) ? null : validationRecord.GetString(10); // check the validation nullable value against the column definition if (null == validationNullable) { // TODO: warn for illegal validation nullable column } else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable)) { // TODO: warn for mismatch between column definition and validation nullable } // convert category to ColumnCategory if (null != category) { try { columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true); } catch (ArgumentException) { columnCategory = ColumnCategory.Unknown; } } } else { // TODO: warn about no validation information } } } // guess the modularization type if ("Icon" == keyTable && 1 == keyColumn) { columnModularizeType = ColumnModularizeType.Icon; } else if ("Condition" == columnName) { columnModularizeType = ColumnModularizeType.Condition; } else if (ColumnCategory.Formatted == columnCategory || ColumnCategory.FormattedSDDLText == columnCategory) { columnModularizeType = ColumnModularizeType.Property; } else if (ColumnCategory.Identifier == columnCategory) { columnModularizeType = ColumnModularizeType.Column; } columns[i - 1] = new ColumnDefinition(columnName, columnType, length, primary, nullable, columnCategory, minValue, maxValue, keyTable, keyColumn, set, description, columnModularizeType, (ColumnType.Localized == columnType), true); } } TableDefinition tableDefinition = new TableDefinition(tableName, columns, false, false); // use our table definitions if core properties are the same; this allows us to take advantage // of wix concepts like localizable columns which current code assumes if (this.TableDefinitions.Contains(tableName) && 0 == tableDefinition.CompareTo(this.TableDefinitions[tableName])) { tableDefinition = this.TableDefinitions[tableName]; } Table table = new Table(tableDefinition); while (true) { using (Record rowRecord = tableView.Fetch()) { if (null == rowRecord) { break; } int recordCount = rowRecord.GetFieldCount(); Row row = table.CreateRow(output.SourceLineNumbers); for (int i = 0; recordCount > i && row.Fields.Length > i; i++) { if (rowRecord.IsNull(i + 1)) { if (!row.Fields[i].Column.Nullable) { // TODO: display an error for a null value in a non-nullable field OR // display a warning and put an empty string in the value to let the compiler handle it // (the second option is risky because the later code may make certain assumptions about // the contents of a row value) } } else { switch (row.Fields[i].Column.Type) { case ColumnType.Number: bool success = false; int intValue = rowRecord.GetInteger(i + 1); if (row.Fields[i].Column.IsLocalizable) { success = row.BestEffortSetField(i, Convert.ToString(intValue, CultureInfo.InvariantCulture)); } else { success = row.BestEffortSetField(i, intValue); } if (!success) { this.Messaging.Write(WarningMessages.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name)); } break; case ColumnType.Object: string sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES"; if (null != this.ExportBasePath) { string relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.')); sourceFile = Path.Combine(this.ExportBasePath, relativeSourceFile); // ensure the parent directory exists System.IO.Directory.CreateDirectory(Path.Combine(this.ExportBasePath, tableName)); using (FileStream fs = System.IO.File.Create(sourceFile)) { int bytesRead; byte[] buffer = new byte[512]; while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length))) { fs.Write(buffer, 0, bytesRead); } } } row[i] = sourceFile; break; default: string value = rowRecord.GetString(i + 1); switch (row.Fields[i].Column.Category) { case ColumnCategory.Guid: value = value.ToUpper(CultureInfo.InvariantCulture); break; } // de-modularize if (!this.SuppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType) { Regex modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}"); if (null == modularizationGuid) { Match match = modularization.Match(value); if (match.Success) { modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}'); } } value = modularization.Replace(value, String.Empty); } // escape "$(" for the preprocessor value = value.Replace("$(", "$$("); // escape things that look like wix variables MatchCollection matches = Common.WixVariableRegex.Matches(value); for (int j = matches.Count - 1; 0 <= j; j--) { value = value.Insert(matches[j].Index, "!"); } row[i] = value; break; } } } } } output.Tables.Add(table); } } } } } finally { if (null != validationView) { validationView.Close(); } } // set the modularization guid as the PackageCode if (null != modularizationGuid) { Table table = output.Tables["_SummaryInformation"]; foreach (Row row in table.Rows) { if (9 == (int)row[0]) // PID_REVNUMBER { row[1] = modularizationGuid; } } } if (this.IsAdminImage) { GenerateWixFileTable(this.DatabasePath, output); GenerateSectionIds(output); } return(output); }
/// <summary> /// Updates database with signatures from external cabinets. /// </summary> /// <param name="databaseFile">Path to MSI database.</param> /// <param name="outputFile">Ouput for updated MSI database.</param> /// <param name="tidy">Clean up files.</param> /// <returns>True if database is updated.</returns> public bool InscribeDatabase(string databaseFile, string outputFile, bool tidy) { // Keeps track of whether we've encountered at least one signed cab or not - we'll throw a warning if no signed cabs were encountered bool foundUnsignedExternals = false; bool shouldCommit = false; FileAttributes attributes = File.GetAttributes(databaseFile); if (FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly)) { this.OnMessage(WixErrors.ReadOnlyOutputFile(databaseFile)); return(shouldCommit); } using (Database database = new Database(databaseFile, OpenDatabase.Transact)) { // Just use the English codepage, because the tables we're importing only have binary streams / MSI identifiers / other non-localizable content int codepage = 1252; // reset list of certificates seen for this database Dictionary <string, object> certificates = new Dictionary <string, object>(); // Reset the in-memory tables for this new database Table digitalSignatureTable = new Table(null, this.tableDefinitions["MsiDigitalSignature"]); Table digitalCertificateTable = new Table(null, this.tableDefinitions["MsiDigitalCertificate"]); using (View mediaView = database.OpenExecuteView("SELECT * FROM Media")) { while (true) { using (Record mediaRecord = mediaView.Fetch()) { if (null == mediaRecord) { break; } X509Certificate2 cert2 = null; Row digitalSignatureRow = null; string cabName = mediaRecord.GetString(4); // get the name of the cab // If there is no cabinet or it's an internal cab, skip it. if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal)) { continue; } string cabId = mediaRecord.GetString(1); // get the ID of the cab string cabPath = Path.Combine(Path.GetDirectoryName(databaseFile), cabName); // If the cabs aren't there, throw an error but continue to catch the other errors if (!File.Exists(cabPath)) { this.OnMessage(WixErrors.WixFileNotFound(cabPath)); continue; } try { // Get the certificate from the cab X509Certificate signedFileCert = X509Certificate.CreateFromSignedFile(cabPath); cert2 = new X509Certificate2(signedFileCert); } catch (System.Security.Cryptography.CryptographicException e) { uint HResult = unchecked ((uint)Marshal.GetHRForException(e)); // If the file has no cert, continue, but flag that we found at least one so we can later give a warning if (0x80092009 == HResult) // CRYPT_E_NO_MATCH { foundUnsignedExternals = true; continue; } // todo: exactly which HRESULT corresponds to this issue? // If it's one of these exact platforms, warn the user that it may be due to their OS. if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3 (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP { this.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); } else // otherwise, generic error { this.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); } } // If we haven't added this cert to the MsiDigitalCertificate table, set it up to be added if (!certificates.ContainsKey(cert2.Thumbprint)) { // Add it to our "add to MsiDigitalCertificate" table dictionary Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); digitalCertificateRow[0] = cert2.Thumbprint; // Export to a file, because the MSI API's require us to provide a file path on disk string certPath = Path.Combine(this.TempFilesLocation, "MsiDigitalCertificate"); Directory.CreateDirectory(certPath); certPath = Path.Combine(certPath, cert2.Thumbprint + ".cer"); File.Delete(certPath); using (BinaryWriter writer = new BinaryWriter(File.Open(certPath, FileMode.Create))) { writer.Write(cert2.RawData); writer.Close(); } // Now set the file path on disk where this binary stream will be picked up at import time digitalCertificateRow[1] = cert2.Thumbprint + ".cer"; certificates.Add(cert2.Thumbprint, certPath); } digitalSignatureRow = digitalSignatureTable.CreateRow(null); digitalSignatureRow[0] = "Media"; digitalSignatureRow[1] = cabId; digitalSignatureRow[2] = cert2.Thumbprint; } } } if (digitalSignatureTable.Rows.Count > 0) { database.ImportTable(codepage, (IMessageHandler)this, digitalSignatureTable, this.TempFilesLocation, true); shouldCommit = true; } if (digitalCertificateTable.Rows.Count > 0) { database.ImportTable(codepage, (IMessageHandler)this, digitalCertificateTable, this.TempFilesLocation, true); shouldCommit = true; } certificates = null; // If we did find external cabs but none of them were signed, give a warning if (foundUnsignedExternals) { this.OnMessage(WixWarnings.ExternalCabsAreNotSigned(databaseFile)); } if (shouldCommit) { database.Commit(); } } return(shouldCommit); }
public void Execute() { Table wixMergeTable = this.Output.Tables["WixMerge"]; Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; // check for merge rows to see if there is any work to do if (null == wixMergeTable || 0 == wixMergeTable.Rows.Count) { return; } IMsmMerge2 merge = null; bool commit = true; bool logOpen = false; bool databaseOpen = false; string logPath = null; try { merge = MsmInterop.GetMsmMerge(); logPath = Path.Combine(this.IntermediateFolder, "merge.log"); merge.OpenLog(logPath); logOpen = true; merge.OpenDatabase(this.OutputPath); databaseOpen = true; // process all the merge rows foreach (WixMergeRow wixMergeRow in wixMergeTable.Rows) { bool moduleOpen = false; try { short mergeLanguage; try { mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); } catch (FormatException) { this.Messaging.Write(ErrorMessages.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); continue; } this.Messaging.Write(VerboseMessages.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage)); merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); moduleOpen = true; // If there is merge configuration data, create a callback object to contain it all. ConfigurationCallback callback = null; if (!String.IsNullOrEmpty(wixMergeRow.ConfigurationData)) { callback = new ConfigurationCallback(wixMergeRow.ConfigurationData); } // merge the module into the database that's being built this.Messaging.Write(VerboseMessages.MergingMergeModule(wixMergeRow.SourceFile)); merge.MergeEx(wixMergeRow.Feature, wixMergeRow.Directory, callback); // connect any non-primary features if (null != wixFeatureModulesTable) { foreach (Row row in wixFeatureModulesTable.Rows) { if (wixMergeRow.Id == (string)row[1]) { this.Messaging.Write(VerboseMessages.ConnectingMergeModule(wixMergeRow.SourceFile, (string)row[0])); merge.Connect((string)row[0]); } } } } catch (COMException) { commit = false; } finally { IMsmErrors mergeErrors = merge.Errors; // display all the errors encountered during the merge operations for this module for (int i = 1; i <= mergeErrors.Count; i++) { IMsmError mergeError = mergeErrors[i]; StringBuilder databaseKeys = new StringBuilder(); StringBuilder moduleKeys = new StringBuilder(); // build a string of the database keys for (int j = 1; j <= mergeError.DatabaseKeys.Count; j++) { if (1 != j) { databaseKeys.Append(';'); } databaseKeys.Append(mergeError.DatabaseKeys[j]); } // build a string of the module keys for (int j = 1; j <= mergeError.ModuleKeys.Count; j++) { if (1 != j) { moduleKeys.Append(';'); } moduleKeys.Append(mergeError.ModuleKeys[j]); } // display the merge error based on the msm error type switch (mergeError.Type) { case MsmErrorType.msmErrorExclusion: this.Messaging.Write(ErrorMessages.MergeExcludedModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleKeys.ToString())); break; case MsmErrorType.msmErrorFeatureRequired: this.Messaging.Write(ErrorMessages.MergeFeatureRequired(wixMergeRow.SourceLineNumbers, mergeError.ModuleTable, moduleKeys.ToString(), wixMergeRow.SourceFile, wixMergeRow.Id)); break; case MsmErrorType.msmErrorLanguageFailed: this.Messaging.Write(ErrorMessages.MergeLanguageFailed(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile)); break; case MsmErrorType.msmErrorLanguageUnsupported: this.Messaging.Write(ErrorMessages.MergeLanguageUnsupported(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile)); break; case MsmErrorType.msmErrorResequenceMerge: this.Messaging.Write(WarningMessages.MergeRescheduledAction(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile)); break; case MsmErrorType.msmErrorTableMerge: if ("_Validation" != mergeError.DatabaseTable) // ignore merge errors in the _Validation table { this.Messaging.Write(WarningMessages.MergeTableFailed(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile)); } break; case MsmErrorType.msmErrorPlatformMismatch: this.Messaging.Write(ErrorMessages.MergePlatformMismatch(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile)); break; default: this.Messaging.Write(ErrorMessages.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorWithType, Enum.GetName(typeof(MsmErrorType), mergeError.Type), logPath), "InvalidOperationException", Environment.StackTrace)); break; } } if (0 >= mergeErrors.Count && !commit) { this.Messaging.Write(ErrorMessages.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorInSourceFile, wixMergeRow.SourceFile, logPath), "InvalidOperationException", Environment.StackTrace)); } if (moduleOpen) { merge.CloseModule(); } } } } finally { if (databaseOpen) { merge.CloseDatabase(commit); } if (logOpen) { merge.CloseLog(); } } // stop processing if an error previously occurred if (this.Messaging.EncounteredError) { return; } using (Database db = new Database(this.OutputPath, OpenDatabase.Direct)) { Table suppressActionTable = this.Output.Tables["WixSuppressAction"]; // suppress individual actions if (null != suppressActionTable) { foreach (Row row in suppressActionTable.Rows) { if (db.TableExists((string)row[0])) { string query = String.Format(CultureInfo.InvariantCulture, "SELECT * FROM {0} WHERE `Action` = '{1}'", row[0].ToString(), (string)row[1]); using (View view = db.OpenExecuteView(query)) { using (Record record = view.Fetch()) { if (null != record) { this.Messaging.Write(WarningMessages.SuppressMergedAction((string)row[1], row[0].ToString())); view.Modify(ModifyView.Delete, record); } } } } } } // query for merge module actions in suppressed sequences and drop them foreach (string tableName in this.SuppressedTableNames) { if (!db.TableExists(tableName)) { continue; } using (View view = db.OpenExecuteView(String.Concat("SELECT `Action` FROM ", tableName))) { while (true) { using (Record resultRecord = view.Fetch()) { if (null == resultRecord) { break; } this.Messaging.Write(WarningMessages.SuppressMergedAction(resultRecord.GetString(1), tableName)); } } } // drop suppressed sequences using (View view = db.OpenExecuteView(String.Concat("DROP TABLE ", tableName))) { } // delete the validation rows using (View view = db.OpenView(String.Concat("DELETE FROM _Validation WHERE `Table` = ?"))) { using (Record record = new Record(1)) { record.SetString(1, tableName); view.Execute(record); } } } // now update the Attributes column for the files from the Merge Modules this.Messaging.Write(VerboseMessages.ResequencingMergeModuleFiles()); using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) { foreach (var file in this.FileFacades) { if (!file.FromModule) { continue; } using (Record record = new Record(1)) { record.SetString(1, file.File.File); view.Execute(record); } using (Record recordUpdate = view.Fetch()) { if (null == recordUpdate) { throw new InvalidOperationException("Failed to fetch a File row from the database that was merged in from a module."); } //recordUpdate.SetInteger(1, file.File.Sequence); throw new NotImplementedException(); // Update the file attributes to match the compression specified // on the Merge element or on the Package element. var attributes = 0; // Get the current value if its not null. if (!recordUpdate.IsNull(2)) { attributes = recordUpdate.GetInteger(2); } if (!file.File.Compressed.HasValue) { // Clear all compression bits. attributes &= ~MsiInterop.MsidbFileAttributesCompressed; attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; } else if (file.File.Compressed.Value) { attributes |= MsiInterop.MsidbFileAttributesCompressed; attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; } else if (!file.File.Compressed.Value) { attributes |= MsiInterop.MsidbFileAttributesNoncompressed; attributes &= ~MsiInterop.MsidbFileAttributesCompressed; } recordUpdate.SetInteger(2, attributes); view.Modify(ModifyView.Update, recordUpdate); } } } db.Commit(); } }
protected override string Get(string key, string defVal) { return(Record.GetString(key, defVal)); }
private TableDefinition GetTableDefinition(string tableName, View tableView, View validationView) { // Use our table definitions whenever possible since they will be used when compiling the source code anyway. // This also allows us to take advantage of WiX concepts like localizable columns which current code assumes. if (this.TableDefinitions.Contains(tableName)) { return(this.TableDefinitions[tableName]); } ColumnDefinition[] columns; using (Record columnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES), columnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES)) { // index the primary keys var tablePrimaryKeys = new HashSet <string>(); using (var primaryKeysRecord = this.Database.PrimaryKeys(tableName)) { var primaryKeysFieldCount = primaryKeysRecord.GetFieldCount(); for (var i = 1; i <= primaryKeysFieldCount; i++) { tablePrimaryKeys.Add(primaryKeysRecord.GetString(i)); } } var columnCount = columnNameRecord.GetFieldCount(); columns = new ColumnDefinition[columnCount]; for (var i = 1; i <= columnCount; i++) { var columnName = columnNameRecord.GetString(i); var idtType = columnTypeRecord.GetString(i); ColumnType columnType; int length; bool nullable; var columnCategory = ColumnCategory.Unknown; var columnModularizeType = ColumnModularizeType.None; var primary = tablePrimaryKeys.Contains(columnName); int? minValue = null; int? maxValue = null; string keyTable = null; int? keyColumn = null; string category = null; string set = null; string description = null; // get the column type, length, and whether its nullable switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture)) { case 'i': columnType = ColumnType.Number; break; case 'l': columnType = ColumnType.Localized; break; case 's': columnType = ColumnType.String; break; case 'v': columnType = ColumnType.Object; break; default: // TODO: error columnType = ColumnType.Unknown; break; } length = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture); nullable = Char.IsUpper(idtType[0]); // try to get validation information if (null != validationView) { using (var validationRecord = new Record(2)) { validationRecord.SetString(1, tableName); validationRecord.SetString(2, columnName); validationView.Execute(validationRecord); } using (var validationRecord = validationView.Fetch()) { if (null != validationRecord) { var validationNullable = validationRecord.GetString(3); minValue = validationRecord.IsNull(4) ? null : (int?)validationRecord.GetInteger(4); maxValue = validationRecord.IsNull(5) ? null : (int?)validationRecord.GetInteger(5); keyTable = validationRecord.IsNull(6) ? null : validationRecord.GetString(6); keyColumn = validationRecord.IsNull(7) ? null : (int?)validationRecord.GetInteger(7); category = validationRecord.IsNull(8) ? null : validationRecord.GetString(8); set = validationRecord.IsNull(9) ? null : validationRecord.GetString(9); description = validationRecord.IsNull(10) ? null : validationRecord.GetString(10); // check the validation nullable value against the column definition if (null == validationNullable) { // TODO: warn for illegal validation nullable column } else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable)) { // TODO: warn for mismatch between column definition and validation nullable } // convert category to ColumnCategory if (null != category) { try { columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true); } catch (ArgumentException) { columnCategory = ColumnCategory.Unknown; } } } else { // TODO: warn about no validation information } } } // guess the modularization type if ("Icon" == keyTable && 1 == keyColumn) { columnModularizeType = ColumnModularizeType.Icon; } else if ("Condition" == columnName) { columnModularizeType = ColumnModularizeType.Condition; } else if (ColumnCategory.Formatted == columnCategory || ColumnCategory.FormattedSDDLText == columnCategory) { columnModularizeType = ColumnModularizeType.Property; } else if (ColumnCategory.Identifier == columnCategory) { columnModularizeType = ColumnModularizeType.Column; } columns[i - 1] = new ColumnDefinition(columnName, columnType, length, primary, nullable, columnCategory, minValue, maxValue, keyTable, keyColumn, set, description, columnModularizeType, (ColumnType.Localized == columnType), true); } } return(new TableDefinition(tableName, null, columns, false)); }
public void TestRecord() { string name = "roi"; int age = 32; double doubleValue = 3.14; bool boolValue = true; string place = "TLV"; int since = 2000; Node expectedNode = new Node(); expectedNode.AddLabel("person"); expectedNode.Properties.Add("name", name); expectedNode.Properties.Add("doubleValue", name); expectedNode.Properties.Add("boolValue", true); expectedNode.Properties.Add("nullValue", null); expectedNode.Properties.Add("place", place); expectedNode.Properties.Add("since", since); Assert.Equal("Node{labels=[person], id=0, propertyMap={name=Property{name='name', value=roi}, age=Property{name='age', value=32}, doubleValue=Property{name='doubleValue', value=3.14}, boolValue=Property{name='boolValue', value=True}, nullValue=Property{name='nullValue', value=null}}}", expectedNode.ToString()); Edge expectedEdge = new Edge(); expectedEdge.SourceId = 0; expectedEdge.DestinationId = 1; expectedEdge.RelationshipType = "knows"; expectedEdge.Properties.Add("place", place); expectedEdge.Properties.Add("since", since); expectedEdge.Properties.Add("doubleValue", name); expectedEdge.Properties.Add("boolValue", false); expectedEdge.Properties.Add("nullValue", null); Assert.Equal("Edge{relationshipType='knows', source=0, destination=1, id=0, propertyMap={place=Property{name='place', value=TLV}, since=Property{name='since', value=2000}, doubleValue=Property{name='doubleValue', value=3.14}, boolValue=Property{name='boolValue', value=False}, nullValue=Property{name='nullValue', value=null}}}", expectedEdge.ToString()); var parms = new Dictionary <string, object> { { "name", name }, { "age", age }, { "boolValue", boolValue }, { "doubleValue", doubleValue } }; Assert.NotNull(_api.Query("social", "CREATE (:person{name:$name,age:$age, doubleValue:$doubleValue, boolValue:$boolValue, nullValue:null})", parms)); Assert.NotNull(_api.Query("social", "CREATE (:person{name:'amit',age:30})")); Assert.NotNull(_api.Query("social", "MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows{place:'TLV', since:2000,doubleValue:3.14, boolValue:false, nullValue:null}]->(b)")); ResultSet resultSet = _api.Query("social", "MATCH (a:person)-[r:knows]->(b:person) RETURN a,r, a.name, a.age, a.doubleValue, a.boolValue, a.nullValue, r.place, r.since, r.doubleValue, r.boolValue, r.nullValue"); Assert.NotNull(resultSet); Assert.Equal(0, resultSet.Statistics.NodesCreated); Assert.Equal(0, resultSet.Statistics.NodesDeleted); Assert.Equal(0, resultSet.Statistics.LabelsAdded); Assert.Equal(0, resultSet.Statistics.PropertiesSet); Assert.Equal(0, resultSet.Statistics.RelationshipsCreated); Assert.Equal(0, resultSet.Statistics.RelationshipsDeleted); Assert.NotNull(resultSet.Statistics.GetStringValue(Label.QueryInternalExecutionTime)); Assert.Equal(1, resultSet.Count); Record record = resultSet.First(); Node node = record.GetValue <Node>(0); Assert.NotNull(node); Assert.Equal(expectedNode, node); node = record.GetValue <Node>("a"); Assert.Equal(expectedNode, node); Edge edge = record.GetValue <Edge>(1); Assert.NotNull(edge); Assert.Equal(expectedEdge, edge); edge = record.GetValue <Edge>("r"); Assert.Equal(expectedEdge, edge); Assert.Equal(new [] { "a", "r", "a.name", "a.age", "a.doubleValue", "a.boolValue", "a.nullValue", "r.place", "r.since", "r.doubleValue", "r.boolValue", "r.nullValue" }, record.Keys); Assert.Equal(new object[] { expectedNode, expectedEdge, name, age, doubleValue, true, null, place, since, doubleValue, false, null }, record.Values); Assert.Equal("roi", record.GetString(2)); Assert.Equal("32", record.GetString(3)); Assert.Equal(32, record.GetValue <int>(3)); Assert.Equal(32, record.GetValue <int>("a.age")); Assert.Equal("roi", record.GetString("a.name")); Assert.Equal("32", record.GetString("a.age")); }
/// <summary> /// Returns data from the MSI tables: `FeatureComponents`, `Feature`, `Component`, `File`. /// We filter to just get the files that end in (*.SQL). /// </summary> /// <param name="session">Windows Installer Session.</param> /// <param name="listFeatureNames">List list with names to be installed.</param> /// <returns>Returns scripts database files to be installed.</returns> private static List <FeatureInstallTO> GetFeatureScriptDataBase(Session session, List <string> listFeatureNames) { try { List <FeatureInstallTO> listFeatures; string sLevel = session["INSTALLLEVEL"]; listFeatures = new List <FeatureInstallTO>(); FeatureInstallTO f; int i; string sFileName; string sQuery = "SELECT `Feature`.`Feature`, `Feature`.`Title`, `Feature`.`Display`, " + " `Component`.`Directory_`, `File`.`FileName` " + " FROM `FeatureComponents`, `Feature`, `Component`, `File` " + " WHERE `FeatureComponents`.`Feature_` = `Feature`.`Feature` " + " AND `FeatureComponents`.`Component_` = `Component`.`Component` " + " AND `File`.`Component_` = `Component`.`Component` " + " AND `Feature`.`RuntimeLevel` > 0 AND `Feature`.`Level` > 0 " + // " AND `Feature`.`Level` <= " + sLevel + " ORDER BY `Feature`.`Display`"; using (View v = session.Database.OpenView(sQuery)) { if (v != null) { v.Execute(); for (Record r = v.Fetch(); r != null; r = v.Fetch()) { if (listFeatureNames.Contains(r.GetString("Feature")) && r.GetString("FileName").ToUpper().EndsWith(".SQL")) { i = r.GetString("FileName").IndexOf("|", StringComparison.Ordinal); if (i > 0) { sFileName = r.GetString("FileName").Substring(i + 1); } else { sFileName = r.GetString("FileName"); } f = new FeatureInstallTO { Feature = r.GetString("Feature"), Title = r.GetString("Title"), DisplayOrder = r.GetInteger("Display"), FileName = sFileName, DirectoryPath = session.GetTargetPath(r.GetString("Directory_")) }; listFeatures.Add(f); } r.Dispose(); } } } return(listFeatures); } catch (Exception ex) { InstallUtilities.WriteLogInstall(session, "Exception, ReadFeactureScriptDataBase", ex, true); throw; } }
public void Execute() { var fileTransfers = new List <IFileTransfer>(); var trackedFiles = new List <ITrackedFile>(); var directories = new Dictionary <string, ResolvedDirectory>(); var mediaRows = this.Section.Tuples.OfType <MediaTuple>().ToDictionary(t => t.DiskId); var wixMediaRows = this.Section.Tuples.OfType <WixMediaTuple>().ToDictionary(t => t.DiskId_); using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) { using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) { while (true) { using (Record directoryRecord = directoryView.Fetch()) { if (null == directoryRecord) { break; } string sourceName = Common.GetName(directoryRecord.GetString(3), true, this.LongNamesInImage); directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName)); } } } using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?")) { using (Record fileQueryRecord = new Record(1)) { // for each file in the array of uncompressed files foreach (FileFacade facade in this.FileFacades) { var mediaTuple = mediaRows[facade.WixFile.DiskId]; string relativeFileLayoutPath = null; string mediaLayoutFolder = null; if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; } var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); // setup up the query record and find the appropriate file in the // previously executed file view fileQueryRecord[1] = facade.File.File; fileView.Execute(fileQueryRecord); using (Record fileRecord = fileView.Fetch()) { if (null == fileRecord) { throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); } relativeFileLayoutPath = PathResolver.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); } // finally put together the base media layout path and the relative file layout path var fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); var transfer = this.BackendHelper.CreateFileTransfer(facade.WixFile.Source.Path, fileLayoutPath, false, facade.File.SourceLineNumbers); fileTransfers.Add(transfer); // Track the location where the cabinet will be placed. If the transfer is // redundant then then the file should not be cleaned. This is important // because if the source and destination of the transfer is the same, we // don't want to clean the file because we'd be deleting the original // (and that would be bad). var tracked = this.BackendHelper.TrackFile(transfer.Destination, TrackedFileType.Final, facade.File.SourceLineNumbers); tracked.Clean = !transfer.Redundant; trackedFiles.Add(tracked); } } } } this.FileTransfers = fileTransfers; this.TrackedFiles = trackedFiles; }