1
votes

I've been going crazy trying to figure out why the view isn't updating. From all the posts I've seen online I think I'm doing it right, but I keep getting a Null error. And if I try to use the session.Database.FilePath to load the Database that way it says the FilePath is null. The view itself is returning the Dummy Row, so the Database is in there. It's just bizarre.

Below is the property

<Property Id="IIS_SITE" />

The Binary and Custom Action

<CustomAction Id="UpdateComboBoxes" DllEntry="UpdateComboBoxes" BinaryKey="UpdateComboBoxes" Execute="immediate" Return="check" />
<Binary Id="UpdateComboBoxes" SourceFile="..\ProjectName.CustomActions\bin\Release\ProjectName.CustomActions.CA.dll"/>

The Install UI Sequence

<InstallUISequence>
  <Custom Action="UpdateComboBoxes" Before="CostFinalize"></Custom>
</InstallUISequence>

The control

   <Control Id="IisSite" Type="ComboBox" Sorted="yes" ComboList="yes" Property="IIS_SITE" X="45" Y="85" Width="220" Height="18" >
      <ComboBox Property="IIS_SITE" >
        <ListItem Text="Dummy" Value="Dummy"/>
      </ComboBox>
    </Control>

The Custom Action

     [CustomAction]
    public static ActionResult UpdateComboBoxes(Session session)
    {
        session.Log("Begin Custom Action UpdateComboBoxes");
        try
        {
            session.Log(string.Format("Database Location is: {0}", session.Database.FilePath));
            var database = session.Database;
                using (var view = database.OpenView("SELECT * FROM ComboBox WHERE Property = 'IIS_SITE'"))
                {

                    view.Execute();
                    session.Log("Executed view");

                    var isReadOnly = database.IsReadOnly;

                    session.Log(string.Format("Database is read only: {0}", isReadOnly));
                    session.Log(string.Format("# of rows in ComboBox Table: {0}",
                        view.Database.CountRows("ComboBox", "Property = 'IIS_SITE'")));

                    using (var serverManager = new ServerManager())
                    {
                        session.Log("Accessed Server Manager");
                        var index = 1;
                        var rowIndex = 1;
                        session.Log(string.Format("Going through {0} sites", serverManager.Sites.Count));
                        foreach (var site in serverManager.Sites)
                        {
                            if (!string.IsNullOrEmpty(site.Name))
                            {
                                session.Log(string.Format("Site # {0} {1}", index, site.Name));
                                var record = session.Database.CreateRecord(4);
                                //Property
                                record.SetString(1, "IIS_SITE");
                                //Order
                                record.SetString(2, rowIndex.ToString());
                                //Value
                                record.SetString(3, site.Name);
                                //Text
                                record.SetString(4, site.Name);

                                session.Log(string.Format("Modifying the view for site # {0}", index));
                                view.Modify(ViewModifyMode.InsertTemporary, record);
                            }
                            session.Log("Incrementing index");
                            index++;
                            rowIndex++;
                        }
                    }

                    session.Log("Closing the view");
                }
        }
        catch (Exception e)
        {

            session.Log(string.Format("ERROR in UpdateComboBoxes: {0}", e.Message));
            session.Log(e.StackTrace);
            var inner = e.InnerException;
            if(inner != null)
            {
                session.Log(string.Format("{0}{1}", "\t", inner.Message));
                session.Log(string.Format("{0}{1}", "\t", inner.StackTrace));
            }
            while ((inner = inner.InnerException) != null)
            {
                session.Log(string.Format("{0}{1}", "\t", inner.Message));
                session.Log(string.Format("{0}{1}", "\t", inner.StackTrace));
            }
            return ActionResult.Failure;
        }
        return ActionResult.Success;
    }

The error I'm getting:

MSI (c) (B0!F4) [14:46:40:369]: Note: 1: 2259 2: 3: 4:
ERROR in UpdateComboBoxes: Function failed during execution. at Microsoft.Deployment.WindowsInstaller.View.Modify(ViewModifyMode mode, Record record) at VideoQuestionInstaller.CustomActions.CustomActions.UpdateComboBoxes(Session session) Exception thrown by custom action: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at VideoQuestionInstaller.CustomActions.CustomActions.UpdateComboBoxes(Session session) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) at Microsoft.Deployment.WindowsInstaller.CustomActionProxy.InvokeCustomAction(Int32 sessionHandle, String entryPoint, IntPtr remotingDelegatePtr)

I looked it up and the error 2259 means that the database failed to update, which is pretty clear since the last log before the error is: Modifying the view for site # 1.

Does anyone have any ideas as to what I'm doing wrong, and why the ComboBox database isn't updating?

Thanks in advance!

1

1 Answers

1
votes

Never mind, I figured out the problem. Here's How I fixed it:

I added another control that was hidden so that the combo box table was created without having to put fake values into the actual combo box I was going to use

    <Property Id="HIDDEN_IIS_SITE" />

    <Control Id="DummyComboBox" Hidden="yes" Type="ComboBox" Sorted="yes" ComboList="yes" Property="HIDDEN_IIS_SITE" X="45" Y="85" Width="220" Height="18" >
      <ComboBox Property="HIDDEN_IIS_SITE" >
        <ListItem Text="Dummy" Value="Dummy"/>
      </ComboBox>
    </Control>

Then I altered the Custom Action so that it got the actual number of existing rows, and then added to the number as records were added so the correct number for the Order was used

    [CustomAction]
    public static ActionResult UpdateComboBoxes(Session session)
    {
        session.Log("Begin Custom Action UpdateComboBoxes");
        try
        {
            var database = session.Database;
                using (var view = database.OpenView("SELECT * FROM ComboBox WHERE Property = 'IIS_SITE'"))
                {

                    view.Execute();
                    session.Log("Executed view");

                    var index = view.Database.CountRows("ComboBox", "Property = 'IIS_SITE'");

                    using (var serverManager = new ServerManager())
                    {
                        foreach (var site in serverManager.Sites)
                        {
                            if (!string.IsNullOrEmpty(site.Name))
                            {
                                var record = session.Database.CreateRecord(4);
                                //Property
                                record.SetString(1, "IIS_SITE");
                                //Order
                                record.SetString(2, (++index).ToString());
                                //Value
                                record.SetString(3, site.Name);
                                //Text
                                record.SetString(4, site.Name);

                                view.InsertTemporary(record);

                                session.Log("Inserted new record");
                            }
                        }
                    }
                    session.Log("Closing the view");
                }
        }
        catch (Exception e)
        {

            session.Log(string.Format("ERROR in UpdateComboBoxes: {0}", e.Message));
            session.Log(e.StackTrace);
            var inner = e.InnerException;
            if(inner != null)
            {
                session.Log(string.Format("{0}{1}", "\t", inner.Message));
                session.Log(string.Format("{0}{1}", "\t", inner.StackTrace));
            }
            while (inner != null && (inner = inner.InnerException) != null)
            {
                session.Log(string.Format("{0}{1}", "\t", inner.Message));
                session.Log(string.Format("{0}{1}", "\t", inner.StackTrace));
            }
            return ActionResult.Failure;
        }
        return ActionResult.Success;
    }