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.");
                    }
                }
            }
        }
示例#2
1
文件: Verifier.cs 项目: zooba/wix3
        /// <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;
            }
        }
示例#5
0
        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;
        }
示例#6
0
        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;
            }
        }
示例#7
0
        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;
        }
示例#8
0
        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;
            }
        }
示例#10
0
        /// <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);
        }
示例#11
0
        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);
 }
示例#14
0
        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();
        }
示例#17
0
        /// <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);
            }
        }
示例#18
0
 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;
 }
示例#19
0
        /// <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);
            }
        }
示例#20
0
        /// <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);
        }
示例#23
0
        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;
        }
示例#24
0
 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;
 }
示例#25
0
 static void DisplayMSIError(Session session, string msg)
 {
     var r = new Record();
     r.SetString(0, msg);
     session.Message(InstallMessage.Error, r);
 }
示例#26
0
 /// <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;
 }
示例#27
0
 internal RecordStream(Record record, int field)
     : base()
 {
     this.record = record;
     this.field  = field;
 }
示例#28
0
        /// <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;
        }
示例#29
0
        /// <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;
        }
示例#30
0
 /// <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);
 }
示例#31
0
        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;
            }
        }
示例#32
0
        /// <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;
            }
        }