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."); } } } }
/// <summary> /// Query an MSI table for all records /// </summary> /// <param name="msi">The path to an MSI</param> /// <param name="sql">An MSI query</param> /// <returns>A list of records is returned</returns> /// <remarks>Uses DTF</remarks> public static List<DTF.Record> QueryAllRecords(string msi, string query) { List<DTF.Record> result = new List<DTF.Record>(); using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { using (DTF.View view = database.OpenView(query,null)) { view.Execute(); DTF.Record record = null; while (null != (record = view.Fetch())) { // Copy record created by Fetch to record created manually to remove View reference DTF.Record copyRecord = new DTF.Record(record.FieldCount); for (int i = 0; i <= record.FieldCount; i++) { copyRecord[i] = record[i]; } record.Close(); result.Add(copyRecord); } } } return result; }
public static ActionResult RemoveClickOnceInstalls(Session Session) { string ShortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "UnrealGameSync", "UnrealGameSync.appref-ms"); if(!File.Exists(ShortcutPath)) { Session.Log("Couldn't find {0} - skipping uninstall", ShortcutPath); return ActionResult.Success; } Record Record = new Record(1); Record.FormatString = "The previous version of UnrealGameSync cannot be removed automatically.\n\nPlease uninstall from the following window."; MessageResult Result = Session.Message(InstallMessage.User | (InstallMessage)MessageBoxButtons.OKCancel, Record); if(Result == MessageResult.Cancel) { return ActionResult.UserExit; } Process NewProcess = Process.Start("rundll32.exe", "dfshim.dll,ShArpMaintain UnrealGameSync.application, Culture=neutral, PublicKeyToken=0000000000000000, processorArchitecture=msil"); NewProcess.WaitForExit(); if(File.Exists(ShortcutPath)) { Record IgnoreRecord = new Record(1); IgnoreRecord.FormatString = "UnrealSync is still installed. Install newer version anyway?"; if(Session.Message(InstallMessage.User | (InstallMessage)MessageBoxButtons.YesNo, IgnoreRecord) == MessageResult.No) { return ActionResult.UserExit; } } return ActionResult.Success; }
public static ActionResult GetWebSites(Session session) { try { if (session == null) { throw new ArgumentNullException("session"); } View comboBoxView = session.Database.OpenView("select * from ComboBox"); int order = 1; foreach (IisWebSite site in IisManager.GetIisWebSites()) { Record newComboRecord = new Record("WEBSITEVALUE", order++, site.ID, site.Name); comboBoxView.Modify(ViewModifyMode.InsertTemporary, newComboRecord); } return ActionResult.Success; } catch (Exception ex) { if (session != null) session.Log("Custom Action Exception: " + ex); return ActionResult.Failure; } }
public static ActionResult GetAppPools(Session session) { try { if (session == null) { throw new ArgumentNullException("session"); } var comboBoxView = session.Database.OpenView("select * from ComboBox"); int order = 1; string first = null; foreach (var appPool in IisManager.GetIisAppPools()) { var newComboRecord = new Record("APPPOOLVALUE", order++, appPool); comboBoxView.Modify(ViewModifyMode.InsertTemporary, newComboRecord); if (string.IsNullOrWhiteSpace(first)) first = appPool; } if (first != null) session["APPPOOLVALUE"] = first; return ActionResult.Success; } catch (Exception e) { if (session != null) session.Log("Custom Action Exception " + e); } return ActionResult.Failure; }
public static ActionResult GetWebSites(Session session) { try { if (session == null) { throw new ArgumentNullException("session"); } var comboBoxView = session.Database.OpenView("select * from ComboBox"); int order = 1; string first = null; foreach (var site in IisManager.GetIisWebSites()) { var newComboRecord = new Record("WEBSITEVALUE", order++, site.ID, site.Name); comboBoxView.Modify(ViewModifyMode.InsertTemporary, newComboRecord); if (string.IsNullOrWhiteSpace(first)) first = site.ID; } if (first != null) session["WEBSITEVALUE"] = first; return ActionResult.Success; } catch (Exception ex) { if (session != null) session.Log("Custom Action Exception: " + ex); return ActionResult.Failure; } }
public MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { try { this.progressCounter.ProcessMessage(messageType, messageRecord); this.progressBar.Value = (int)(this.progressBar.Minimum + this.progressCounter.Progress * (this.progressBar.Maximum - this.progressBar.Minimum)); this.progressLabel.Text = "" + (int)Math.Round(100 * this.progressCounter.Progress) + "%"; switch (messageType) { case InstallMessage.Error: case InstallMessage.Warning: case InstallMessage.Info: string message = String.Format("{0}: {1}", messageType, messageRecord); this.LogMessage(message); break; } if (this.canceled) { this.canceled = false; return MessageResult.Cancel; } } catch (Exception ex) { this.LogMessage(ex.ToString()); this.LogMessage(ex.StackTrace); } Application.DoEvents(); return MessageResult.OK; }
public void ProcessMessage(InstallMessage messageType, Record messageRecord) { // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#. switch (messageType) { case InstallMessage.ActionStart: if (this.enableActionData) { this.enableActionData = false; } break; case InstallMessage.ActionData: if (this.enableActionData) { if (this.moveForward) { this.completed += this.step; } else { this.completed -= this.step; } this.UpdateProgress(); } break; case InstallMessage.Progress: this.ProcessProgressMessage(messageRecord); break; } }
/// <summary> /// Creates the appropriate unit test class and returns the base class. /// </summary> /// <param name="session">MSI session handle.</param> /// <param name="record">Record from the LuxCustomAction MSI table.</param> /// <param name="logger">Logger to record unit test output.</param> /// <returns>A Lux unit test appropriate for the given record. Returns null on error.</returns> public LuxUnitTest CreateUnitTest(Session session, Record record, LuxLogger logger) { string wixUnitTestId = record["WixUnitTest"] as string; string customAction = record["CustomAction_"] as string; string property = record["Property"] as string; LuxOperator op = (LuxOperator)Convert.ToInt16(record["Operator"] as object); string value = record["Value"] as string; string expression = record["Expression"] as string; string condition = record["Condition"] as string; string valueSeparator = record["ValueSeparator"] as string; string nameValueSeparator = record["NameValueSeparator"] as string; string index = record["Index"] as string; switch (this.DetermineTestType(expression, property, op, index, valueSeparator, nameValueSeparator)) { case TestType.Expression: return new LuxExpressionUnitTest(session, logger, wixUnitTestId, condition, expression); case TestType.PropertyValue: return new LuxPropertyValueUnitTest(session, logger, wixUnitTestId, condition, property, op, value); case TestType.DelimitedList: return new LuxDelimitedListUnitTest(session, logger, wixUnitTestId, condition, property, op, value, valueSeparator, index); case TestType.DelimitedKeyValue: return new LuxDelimitedKeyValueUnitTest(session, logger, wixUnitTestId, condition, property, op, value, nameValueSeparator, index); default: logger.Log(Constants.TestNotCreated, wixUnitTestId); return null; } }
/// <summary> /// Query an MSI table for all records /// </summary> /// <param name="msi">The path to an MSI</param> /// <param name="sql">An MSI query</param> /// <returns>A list of records is returned</returns> /// <remarks>Uses DTF</remarks> public static List <DTF.Record> QueryAllRecords(string msi, string query) { List <DTF.Record> result = new List <DTF.Record>(); using (DTF.Database database = new DTF.Database(msi, DTF.DatabaseOpenMode.ReadOnly)) { using (DTF.View view = database.OpenView(query, null)) { view.Execute(); DTF.Record record = null; while (null != (record = view.Fetch())) { // Copy record created by Fetch to record created manually to remove View reference DTF.Record copyRecord = new DTF.Record(record.FieldCount); for (int i = 0; i <= record.FieldCount; i++) { copyRecord[i] = record[i]; } record.Close(); result.Add(copyRecord); } } } return(result); }
public static ActionResult GetAppPools(Session session) { try { if (session == null) { throw new ArgumentNullException("session"); } // Check if running with admin rights and if not, log a message to // let them know why it's failing. if (false == HasAdminRights()) { session.Log("GetAppPools: " + "ATTEMPTING TO RUN WITHOUT ADMIN RIGHTS"); return ActionResult.Failure; } View comboBoxView = session.Database.OpenView("select * from ComboBox"); int order = 1; session.Log("Trying to retutn the app pool list"); foreach (string appPool in IisManager.GetIisAppPools()) { Record newComboRecord = new Record("APPPOOLVALUE", order++, appPool); comboBoxView.Modify(ViewModifyMode.InsertTemporary, newComboRecord); } return ActionResult.Success; } catch (Exception e) { if (session != null) session.Log("Custom Action Exception " + e); } return ActionResult.Failure; }
public static MessageResult IncrementProgressBar(Session session, int progressPercentage) { var record = new Record(3); record[1] = 2; // "ProgressReport" message record[2] = progressPercentage; // ticks to increment record[3] = 0; // ignore return session.Message(InstallMessage.Progress, record); }
/* * helper methods to control the progress bar * kudos to a fellow developer http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Update-progress-bar-from-deferred-custom-action-tt4994990.html#a4997563 */ public static MessageResult ResetProgressBar(Session session, int totalStatements) { var record = new Record(3); record[1] = 0; // "Reset" message record[2] = totalStatements; // total ticks record[3] = 0; // forward motion return session.Message(InstallMessage.Progress, record); }
public static ActionResult PromptToCloseOutlook(Session session) { session.Log("Detecting running instances of Microsoft Outlook..."); if (null != Process.GetProcessesByName("outlook").FirstOrDefault()) { session.Log("Microsoft Outlook is running."); var record = new Record { FormatString = "Please exit Microsoft Outlook before continuing\n" + "or click Retry to close it automatically." }; var result = session.Message( InstallMessage.Error | (InstallMessage)MessageBoxIcon.Error | (InstallMessage)MessageBoxButtons.AbortRetryIgnore, record); if (result == MessageResult.Abort) { session.Log("User chose to abort the installer."); return ActionResult.Failure; } if (result == MessageResult.Ignore) { session.Log("User chose to ignore."); record.FormatString = "This application will not be available until you restart Outlook."; session.Message( InstallMessage.Error | (InstallMessage)MessageBoxIcon.Exclamation | (InstallMessage)MessageBoxButtons.OK, record); return ActionResult.Success; } //check to see if it's still running var outlook = Process.GetProcessesByName("outlook").FirstOrDefault(); if (outlook == null) { session.Log("User closed Outlook"); return ActionResult.Success; } session.Log("User clicked Retry but Outlook is still running, attempting to kill it."); try { outlook.Kill(); } catch { session.Log("Failed to kill Outlook, raising alert and returning failure."); record = new Record { FormatString = "Outlook is still running. Open the Task Manager, end any open Outlook processes, and try this install again." }; session.Message( InstallMessage.Error | (InstallMessage)MessageBoxIcon.Error, record); return ActionResult.Failure; } } return ActionResult.Success; }
private static void CreateComboBoxRecordItem(View view, int numRows, string propertyName, string text, string value) { Record record = new Record(4); record.SetString(1, propertyName); record.SetInteger(2, numRows); record.SetString(3, value); record.SetString(4, text); view.Modify(ViewModifyMode.InsertTemporary, record); }
/* * helper method used to send the actiontext message to the MSI * kudos to a fellow developer http://community.flexerasoftware.com/archive/index.php?t-181773.html */ internal static void StatusMessage(Session session, string status) { Record record = new Record(3); record[1] = "callAddProgressInfo"; record[2] = status; record[3] = "Incrementing tick [1] of [2]"; session.Message(InstallMessage.ActionStart, record); Application.DoEvents(); }
/// <summary> /// Executes the query specified by a SQL string. The query may not be a SELECT statement. /// </summary> /// <param name="sql">SQL query string</param> /// <param name="record">Optional Record object containing the values that replace /// the parameter tokens (?) in the SQL query.</param> /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception> /// <exception cref="InstallerException">the View could not be executed</exception> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a> /// </p></remarks> public void Execute(string sql, Record record) { if (String.IsNullOrEmpty(sql)) { throw new ArgumentNullException("sql"); } using (View view = this.OpenView(sql)) { view.Execute(record); } }
public ActionResult DoAction(Session session) { Record record = new Record(3); for (int i = 1; i <= 100; i++) { record[1] = "ProgressMessageDemo"; record[2] = string.Format("Выполнение Demo-плагина (выполнено {0}%)", i); record[3] = ""; session.Message(InstallMessage.ActionStart, record); Thread.Sleep(20); } return ActionResult.Success; }
/// <summary> /// Logs a message to the MSI log using the MSI error table. /// </summary> /// <param name="id">Error message id</param> /// <param name="args">Arguments to the error message (will be inserted into the formatted error message).</param> public void Log(int id, params string[] args) { // field 0 is free, field 1 is the id, fields 2..n are arguments using (Record rec = new Record(1 + args.Length)) { rec.SetInteger(1, id); for (int i = 0; i < args.Length; i++) { rec.SetString(2 + i, args[i]); } this.session.Message(InstallMessage.User, rec); } }
/// <summary> /// Processes the message. /// </summary> /// <param name="messageType">Type of the message.</param> /// <param name="messageRecord">The message record.</param> /// <param name="buttons">The buttons.</param> /// <param name="icon">The icon.</param> /// <param name="defaultButton">The default button.</param> /// <returns></returns> public override MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { switch (messageType) { case InstallMessage.ActionStart: { try { //messageRecord[0] - is reserved for FormatString value string message = null; bool simple = true; if (simple) { for (int i = messageRecord.FieldCount - 1; i > 0; i--) { message = messageRecord[i].ToString(); } } else { message = messageRecord.FormatString; if (message.IsNotEmpty()) { for (int i = 1; i < messageRecord.FieldCount; i++) { message = message.Replace("[" + i + "]", messageRecord[i].ToString()); } } else { message = messageRecord[messageRecord.FieldCount - 1].ToString(); } } if (message.IsNotEmpty()) currentAction.Text = message; } catch { } } break; } return MessageResult.OK; }
/// <summary> /// Resets the progress bar to zero and sets a new value for total ticks.. /// </summary> /// <param name="session">Windows Installer Session.</param> /// <param name="totalTicks">Total number of ticks.</param> /// <returns>Returns the message handler .</returns> public static MessageResult ResetProgress(Session session, int totalTicks) { var record = new Record(4); record[1] = "0"; // / Set reset progress bar and set the total number of ticks of the bar record[2] = totalTicks.ToString(); // Total ticks //Move progress bar // 0: Moving forward from left to right . 1: Way back from right to left ) record[3] = "0"; // 0: Execution in progress, the UI calculates and displays the time remaining // 1: Creating script execution . The UI displays a message while the installer finishes preparing the installation. record[4] = "0"; return session.Message(InstallMessage.Progress, record); }
/// <summary> /// Set the amount to increase the progress bar for each message sent ActionData . /// </summary> /// <param name="session"> Windows Installer Session.</param> /// <param name="ticks"> Number of ticks to be added to the progress bar.</param> /// <param name="increaseForActionData"> /// Indicates whether the progress bar increases with each message sent by ActionData: /// <para>False: : Indicates send the current message to the progress report.</para> /// <para> /// True: Indicates increase the progress bar in each ActionData in the number of ticks <paramref name="ticks" /> /// . /// </para> /// </param> /// <returns>Returns message handler.</returns> public static MessageResult NumberOfTicksPerActionData(Session session, int ticks, bool increaseForActionData) { var record = new Record(3); record[1] = "1"; // Provides information related to the progress message sent by the current action // Ticks ActionData increase in each message sent by the custom action , this value is ignored if field 3 is 0 record[2] = ticks.ToString(); if (increaseForActionData) { record[3] = "1"; // Set the progress bar increasing in each ActionData in the number of ticks in field 2 espeficicados } else { record[3] = "0"; // / Set the current message to send progress report } return session.Message(InstallMessage.Progress, record); }
public override MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { switch (messageType) { case InstallMessage.ActionStart: { try { var message = messageRecord[messageRecord.FieldCount - 1].ToString(); if (message.IsNotEmpty()) currentAction.Text = message; } catch { } } break; } return MessageResult.OK; }
public static MessageResult ExternalUIRecordLogger( InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { if (messageRecord != null) { if (messageRecord.FormatString.Length == 0 && messageRecord.FieldCount > 0) { messageRecord.FormatString = "1: [1] 2: [2] 3: [3] 4: [4] 5: [5]"; } Console.WriteLine("{0}: {1}", messageType, messageRecord.ToString()); } else { Console.WriteLine("{0}: (null)", messageType); } return MessageResult.None; }
static void DisplayMSIError(Session session, string msg) { var r = new Record(); r.SetString(0, msg); session.Message(InstallMessage.Error, r); }
/// <summary> /// Processes information and progress messages sent to the user interface. /// </summary> /// <param name="messageType">Message type.</param> /// <param name="messageRecord">Record that contains message data.</param> /// <param name="buttons">Message box buttons.</param> /// <param name="icon">Message box icon.</param> /// <param name="defaultButton">Message box default button.</param> /// <returns>Result of processing the message.</returns> public MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton) { // Synchronously send the message to the setup wizard window on its thread. object result = this.setupWizard.Dispatcher.Invoke(DispatcherPriority.Send, new Func<MessageResult>(delegate() { return this.setupWizard.ProcessMessage(messageType, messageRecord, buttons, icon, defaultButton); })); return (MessageResult) result; }
internal RecordStream(Record record, int field) : base() { this.record = record; this.field = field; }
/// <summary> /// [MSI 4.0] Gets the list of files that can be updated by one or more patches. /// </summary> /// <param name="productCode">ProductCode (GUID) of the product which is /// the target of the patches</param> /// <param name="patches">list of file paths of one or more patches to be /// analyzed</param> /// <returns>List of absolute paths of files that can be updated when the /// patches are applied on this system.</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetpatchfilelist.asp">MsiGetPatchFileList</a> /// </p></remarks> internal static IList<string> GetPatchFileList(string productCode, IList<string> patches) { if (String.IsNullOrEmpty(productCode)) { throw new ArgumentNullException("productCode"); } if (patches == null || patches.Count == 0) { throw new ArgumentNullException("patches"); } StringBuilder patchList = new StringBuilder(); foreach (string patch in patches) { if (patch != null) { if (patchList.Length != 0) { patchList.Append(';'); } patchList.Append(patch); } } if (patchList.Length == 0) { throw new ArgumentNullException("patches"); } IntPtr phFileRecords; uint cFiles; uint ret = NativeMethods.MsiGetPatchFileList( productCode, patchList.ToString(), out cFiles, out phFileRecords); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } List<string> files = new List<string>(); for (uint i = 0; i < cFiles; i++) { int hFileRec = Marshal.ReadInt32(phFileRecords, (int) i); using (Record fileRec = new Record(hFileRec, true, null)) { files.Add(fileRec.GetString(1)); } } return files; }
/// <summary> /// Gets a formatted Windows Installer error message in a specified language. /// </summary> /// <param name="errorRecord">Error record containing the error number in the first field, and /// error-specific parameters in the other fields.</param> /// <param name="culture">The locale for the message.</param> /// <returns>The message string, or null if the error message or locale is not found.</returns> /// <remarks><p> /// Error numbers greater than 2000 refer to MSI "internal" errors, and are always /// returned in English. /// </p></remarks> internal static string GetErrorMessage(Record errorRecord, CultureInfo culture) { if (errorRecord == null) { throw new ArgumentNullException("errorRecord"); } int errorNumber; if (errorRecord.FieldCount < 1 || (errorNumber = (int) errorRecord.GetInteger(1)) == 0) { throw new ArgumentOutOfRangeException("errorRecord"); } string msg = Installer.GetErrorMessage(errorNumber, culture); if (msg != null) { errorRecord.FormatString = msg; msg = errorRecord.ToString((IFormatProvider)null); } return msg; }
/// <summary> /// Gets a formatted Windows Installer error message in the system default language. /// </summary> /// <param name="errorRecord">Error record containing the error number in the first field, and /// error-specific parameters in the other fields.</param> /// <returns>The message string, or null if the error message is not found.</returns> /// <remarks><p> /// Error numbers greater than 2000 refer to MSI "internal" errors, and are always /// returned in English. /// </p></remarks> internal static string GetErrorMessage(Record errorRecord) { return Installer.GetErrorMessage(errorRecord, null); }
private void ProcessProgressMessage(Record progressRecord) { // This MSI progress-handling code was mostly borrowed from burn and translated from C++ to C#. if (progressRecord == null || progressRecord.FieldCount == 0) { return; } int fieldCount = progressRecord.FieldCount; int progressType = progressRecord.GetInteger(1); string progressTypeString = String.Empty; switch (progressType) { case 0: // Master progress reset if (fieldCount < 4) { return; } this.progressPhase++; this.total = progressRecord.GetInteger(2); if (this.progressPhase == 1) { // HACK!!! this is a hack courtesy of the Windows Installer team. It seems the script planning phase // is always off by "about 50". So we'll toss an extra 50 ticks on so that the standard progress // doesn't go over 100%. If there are any custom actions, they may blow the total so we'll call this // "close" and deal with the rest. this.total += 50; } this.moveForward = (progressRecord.GetInteger(3) == 0); this.completed = (this.moveForward ? 0 : this.total); // if forward start at 0, if backwards start at max this.enableActionData = false; this.UpdateProgress(); break; case 1: // Action info if (fieldCount < 3) { return; } if (progressRecord.GetInteger(3) == 0) { this.enableActionData = false; } else { this.enableActionData = true; this.step = progressRecord.GetInteger(2); } break; case 2: // Progress report if (fieldCount < 2 || this.total == 0 || this.progressPhase == 0) { return; } if (this.moveForward) { this.completed += progressRecord.GetInteger(2); } else { this.completed -= progressRecord.GetInteger(2); } this.UpdateProgress(); break; case 3: // Progress total addition this.total += progressRecord.GetInteger(2); break; } }
/// <summary> /// Executes the specified SQL SELECT query and returns all results as strings. /// </summary> /// <param name="sql">SQL SELECT query string</param> /// <param name="record">Optional Record object containing the values that replace /// the parameter tokens (?) in the SQL query.</param> /// <returns>All results combined into an array</returns> /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception> /// <exception cref="InstallerException">the View could not be executed</exception> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// Multiple rows columns will be collapsed into a single on-dimensional list. /// </p><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a> /// </p></remarks> public IList<string> ExecuteStringQuery(string sql, Record record) { if (String.IsNullOrEmpty(sql)) { throw new ArgumentNullException("sql"); } using (View view = this.OpenView(sql)) { view.Execute(record); IList<string> results = new List<string>(); int fieldCount = 0; foreach (Record rec in view) using (rec) { if (fieldCount == 0) fieldCount = rec.FieldCount; for (int i = 1; i <= fieldCount; i++) { results.Add(rec.GetString(i)); } } return results; } }