Solved

WiX - Custom Action Error - DLL is required for this install to complete

Posted on 2016-09-07
29
54 Views
Last Modified: 2016-09-09
I have the below WiX code.  I created a Custom Action.  I have two issues.

1. I have to put the entire path for the SourceFile -> SourceFile="C:\MyDir\GetConnections.dll".  Anyway to shorten?
2.  I'm receiving an error "A DLL is required for this install to complete could not run." etc..  Can't figure out what is causing it.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
	<Fragment>
    <CustomAction Id="FillingListBox" BinaryKey="FillListBox" DllEntry="FillListBox" />
    
    <UI Id="DatabaseScreen">
      <Dialog Id="DatabaseDialog"
              Width="370"
              Height="270"
              Title="Database Connections"
              NoMinimize="no">

        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no"
                 Text="!(loc.LicenseAgreementDlgBannerBitmap)" />

        <Control Id="Dbases" Type="ListBox" Sorted="no" 
                 Indirect="no" Property="DBaseValues" 
                 X="10" Y="50" Width="150" Height="180">
          <ListBox Property="DBaseValues">
            <ListItem Text="ARGHH!" Value="1"/>
          </ListBox>
        </Control>
        
        <Control Id="Title"
                 Type="Text"
                 X="15"
                 Y="23"
                 Width="280"
                 Height="15"
                 Transparent="yes"
                 NoPrefix="yes"
                 Text="Database Information" />

        <Control Id="InstallButton"
                 Type="PushButton"
                 Text="Install"
                 Height="17" Width="56"
                 X="300" Y="243"
                 TabSkip="yes">
          <Publish Event="EndDialog" Value="Return" />
        </Control>

        <Control Id="BackButton"
         Type="PushButton"
         X="235" Y="243"
         Height="17" Width="56"
         Text="Back">
          <Publish Event="NewDialog" Value="LicenseDialog" />
        </Control>

        <Control Id="CancelButton"
                 Type="PushButton"
                 X="10" Y="243"
                 Height="17" Width="56"
                 Text="Cancel">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
      </Dialog>

      <InstallUISequence>
        <Custom Action="FillingListBox" After="CostFinalize" />
        <Show Dialog="DatabaseDialog" After="FillingListBox" />
      </InstallUISequence>

    </UI>

    <Binary Id="FillListBox" SourceFile="C:\MyDir\GetConnections.dll" />
  </Fragment>
</Wix>

Open in new window

    public class DBase
    {
        public string Name { get; set; } = string.Empty;
    }

    public class CustomActions
    {
        [CustomAction]
        public static ActionResult GetSQLConnections(Session session)
        {
            session.Log("Begin GetSQLConnections");

            session["USER_DATABASES"] = "DefaultValue";

            int i = 0;
            int j = 0;
            string s = string.Empty;
            var dt = SmoApplication.EnumAvailableSqlServers(false);

            if (dt != null)
            {
                List<DBase> db = new List<DBase>();
                foreach (DataRow row in dt.Rows)
                {
                    foreach (var item in row.ItemArray)
                    {
                        if (i == j)
                        {
                            db.Add(new DBase()
                            {
                                Name = item.ToString()
                            });
                        }
                        else
                        {
                            break;
                        }
                        j++;
                    }
                    i++;
                }

                var z = (from y in db
                              select y).ToList();

                Microsoft.Deployment.WindowsInstaller.View listBoxView = session.Database.OpenView("SELECT * FROM ListBox");

                i = 1;
                foreach (var db1 in z)
                {
                    s += db1.Name + "; ";
                    Record newListBoxRecord = new Record(4);
                    newListBoxRecord[1] = "DBaseValues";
                    newListBoxRecord[2] = i;
                    newListBoxRecord[3] = db1.Name;
                    newListBoxRecord[4] = db1.Name;
                    listBoxView.Modify(ViewModifyMode.InsertTemporary, newListBoxRecord);
                    i++;
                }
            }
            //MessageBox.Show(s, "", MessageBoxButtons.OK, MessageBoxIcon.Information);

            return ActionResult.Success;
        }
    }

Open in new window

0
Comment
Question by:CipherIS
  • 16
  • 13
29 Comments
 
LVL 40

Assisted Solution

by:Vadim Rapp
Vadim Rapp earned 500 total points
ID: 41788248
#1 - you can use relative path; you can also include config.wxi, define your path as a variable, and refer to it as  $(var.SourceDir)

#2 - since probably the only dll out there is your GetConnections.dll, I would run Process Monitor and checked (1) if it's found, and (2) how it's called. If that does not help, and if this is your own dll, then the next step is to debug it by attaching to the installation process.
1
 
LVL 1

Author Comment

by:CipherIS
ID: 41788284
I downloaded Process Monitor.  I do not see my install in the Process Monitor nor the DLL.  How do I debug it?

Oh, and for the Sourcefile I typed c:\.... but it's actuall G:\....  I don't know if that makes a difference.  I'm developing this on an external drive.
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788318
The DLL was created by the CustomAction.  Below is the example that I used.

https://www.firegiant.com/wix/tutorial/standard-libraries/custom-actions-and-user-interface/
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788449
> I do not see my install in the Process Monitor nor the DLL.

Process monitor monitors processes, so during the installation it will be msiexec. At some point it probably will try to load the dll, but how exactly it will do it depends on how WiX packs it in the installation. The log should tell. You can also open the MSI in Orca and inspect the custom action.

WiX is not the most user-friendly authoring tool, to say the least, and involves quite a learning curve. And on the top of that, you are trying to use in your installation quite advanced stuff, such as this custom action in C++ that connects to the installation session from within, or embedded installation of sql server - where each would be a nontrivial project even with more user-friendly tool, and for the developer already intimately familiar with it. Maybe it would make sense to make your learning curve less steep - such as, when you read those tutorials, you first try each of them verbatim as it's published, on special simple sample projects, and do it in your real project when you already have mastered it. Then move to the next challenge.
1
 
LVL 1

Author Comment

by:CipherIS
ID: 41788467
It is unfortunate that it requires a steep learning curve.  I was able to get an install to work.  I am now modifying the process and creating UI's.  I was successfully able to create UI's.  

Do you have a recommendation of another tool or any advice with a lesser learning curve that will give me the results I'm looking for?

It would be nice if the tutorials were more explicit, meaning the code samples worked.
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788489
Myself, I have been using Wise Installer for many years. Installshield as well. Both are far from being free, and Wise is actually discontinued, so you can't acquire it legally anymore, although imho it's still the best.

Re. learning curve, I mostly meant the absence of visual UI in WiX, so you have to write everything by hand, remembering the keywords, and not seeing the big picture, so to speak.

My main suggestion was basically to separate the complexity of learning new nontrivial tool from the complexity of creating a nontrivial project - with self-written custom actions, embedded installation and configuration of the database, and more. Combining both of these complexities makes it difficult. I'm sure you'll succeed, but most likely you will spend many times more time; plus, if you are going to release the installation to the public or customer, most likely you will make some mistakes because it's new tool, which you wouldn't make after several years of using it, so the end result may be not as excellent as it might be. Make sure to run all the validations.
1
 
LVL 1

Author Comment

by:CipherIS
ID: 41788532
I used to use Wise in the 90's.  Can't use Installshield so I'm trying to learn this tool.  I miss Wise.  I just wish things were clear cut.  Even their examples and documentation isn't.  I've had to figure out how to get stuff to work.  

I downloaded Orca.  This is what I have.
Orca.jpg
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788547
What's in Binary table?
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788554
See attached
Binary.jpg
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788584
Let's try to figure out whether the installation fails to load the dll, or it launches it, but the code itself fails.

1. Check detailed installation log, or post the log here. Is "Begin GetSQLConnections" in the log?

2. I would also uncomment MessageBox.Show in the dll, and put another one in the very beginning. If you see the beginning message but not the ending one, then either debug by attaching to the process msiexec, once the beginning message is on the screen, or insert even more messagebox's after each line, so you figure where it bombs out.
1
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788594
also - just noticed... in your c++ code, there's smoapplcaition.EnumAvailableSqlServers . But is smoapplication available to the installation, if there's no sql server yet?
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788605
There is a SQL Server on my local machine.  I'm testing to see what show's up.  I wrote the C# code in a .NET app and it works.  I then copied it to the CustomActions.

Ok, I fixed some things and figure out some stuff but still have same issue.

1.  My DLLEntry was wrong.  Fixed that.
2.  Renamed BinaryID so it matches BinaryKey.
3.  Renamed CustomActionID so it matches CustomAction in InstallUISequuence.

Also, figured out the sourcefile in <Binary>  I've seen examples where both source.dll and source.ca.dll were used.  If i use my sqlconnection.dll (which is .dll) then I get the error.  If I change the extension to .ca.dll the installer flashes for a sec and disappears.

    <Binary Id="FillListBoxBinary"
            SourceFile="$(var.SQLConnections.TargetDir)$(var.SQLConnections.TargetName).dll" />

    <CustomAction Id="FillListBoxAction" BinaryKey="FillListBoxBinary" DllEntry="GetSQLConnections"
        Execute="immediate" Return="check" />
    
    <InstallUISequence>
      <Custom Action="FillListBoxAction" After="CostFinalize" />
      <Show Dialog="DatabaseDialog" After="FillListBoxAction" />
    </InstallUISequence>

Open in new window


Where is the installation log?
0
 
LVL 40

Assisted Solution

by:Vadim Rapp
Vadim Rapp earned 500 total points
ID: 41788621
1
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41788623
>Where is the installation log?

https://support.microsoft.com/en-us/kb/223300

the log itself will be in %temp% folder.
1
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Author Comment

by:CipherIS
ID: 41788636
Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor.  Action FillListBoxAction, entry: GetSQLConnections, library: C:\Users\*****\AppData\Local\Temp\MSI325D.tmp
=== Logging stopped: 9/7/2016  15:36:12 ===
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788649
Commented out the <Binary> and the code that wires up the Custom Action on the UI.  I added the below to the ListItem and it is displaying the name of the DLL with the correct path.
        <Control Id="DbaseList" Type="ListBox" Sorted="no" 
                 Indirect="no" Property="DBaseValues" 
                 X="10" Y="50" Width="150" Height="180">
          <ListBox Property="DBaseValues">
            <ListItem Text="ARGHH!" Value="1"/>
            <ListItem Text="$(var.SQLConnections.TargetDir)$(var.SQLConnections.TargetName).dll" Value="2"/>
          </ListBox>
        </Control>

Open in new window

0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788715
When I set Return to "ignore" the install will run but that dialog will start first when it is supposed to be third.  Anyway to debug the Custom Action?  I don't know if there is an issue in the Custom Action.   Wish I could set a breakpoint and walk through it.
    <CustomAction Id="FillListBoxAction" BinaryKey="FillListBoxBinary" 
                  DllEntry="GetSQLConnections" Execute="immediate" Return="ignore" />

Open in new window

0
 
LVL 1

Author Comment

by:CipherIS
ID: 41788730
I made it simpler for troubleshooting.  Same exact error.  There is no code in the CustomAction.  

Code in the UI
    <Binary Id="FillListBoxBinary"
        SourceFile="$(var.DBConnect.TargetDir)$(var.DBConnect.TargetName).dll" />

    <CustomAction Id="FillListBoxAction"
                  BinaryKey="FillListBoxBinary"
                  DllEntry="GetListofDB"
                  Execute="immediate" Return="check" />

    <InstallUISequence>
      <Custom Action="FillListBoxAction" After="CostFinalize" />
      <Show Dialog="DatabaseDialog" After="FillListBoxAction" />
    </InstallUISequence>

Open in new window

My Custom Action
namespace DBConnect
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult GetListofDB(Session session)
        {
            session.Log("Begin CustomAction1");

            return ActionResult.Success;
        }
    }
}

Open in new window

0
 
LVL 40

Accepted Solution

by:
Vadim Rapp earned 500 total points
ID: 41788849
OK, I looked further :-)

Custom action that calls a dll is so called custom action type 1, which is what your project is using. However, the dll must be written in C++ or C, i.e. it has to be so called native dll. Managed dll won't work.

WiX has apparently created some framework in order to make calling managed dll possible. For that, it creates its own native .ca.dll, which is called by the custom action. So when you replaced .dll by .ca.dll, it looks you were on the right track. You said that with .ca.dll, Installer flashes and disappears. Produce the log and look there, or post here (the whole log, not the piece of it).
1
 
LVL 1

Author Comment

by:CipherIS
ID: 41789634
Ok, the .CA.dll seems to work.  There are two issues though.  

1.  The database screen shows up first and not the license screen.  When I click on install then it goes to the License Screen and starts navigating correctly.
2.  If I use a for loop or a foreach loop to get the values from my collection it seems to be causing an issue.  
                    i = 2;
//                    foreach (var db1 in z)
//                    {
                        View listBoxView = session.Database.OpenView("SELECT * FROM ListBox");
                        Record newListBoxRecord = new Record(4);
                        newListBoxRecord[1] = "DBaseValues";
                        newListBoxRecord[2] = i;
                        newListBoxRecord[3] = "Test"; //db1.Name;
                        newListBoxRecord[4] = "Test"; //db1.Name;
                        listBoxView.Modify(ViewModifyMode.InsertTemporary, newListBoxRecord);
                    //}

Open in new window



Error
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2878. The arguments are: DatabaseDialog, DbaseList, DESKTOP-******
=== Logging stopped: 9/8/2016  9:31:18 ===
Dbase.png
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41789682
I figured out that this needs to be outside of the for loop or foreach loop.
View listBoxView = session.Database.OpenView("SELECT * FROM ListBox");
Record newListBoxRecord = new Record(4);

Open in new window

When I do below it works but having it in a loop is better as I don't know what is going to return from the list.  Any ideas?
View listBoxView = session.Database.OpenView("SELECT * FROM ListBox");
Record newListBoxRecord = new Record(4);
newListBoxRecord[1] = "DBaseValues";
newListBoxRecord[2] = i;
newListBoxRecord[3] = z[0].Name;  //sName;  //"Test " + k; //db1.Name;
newListBoxRecord[4] = z[0].Name;  //sName;  //"Test " + k; //db1.Name;
listBoxView.Modify(ViewModifyMode.InsertTemporary, newListBoxRecord);

newListBoxRecord[1] = "DBaseValues";
newListBoxRecord[2] = 3;
newListBoxRecord[3] = z[1].Name;  //sName;  //"Test " + k; //db1.Name;
newListBoxRecord[4] = z[1].Name;  //sName;  //"Test " + k; //db1.Name;
listBoxView.Modify(ViewModifyMode.InsertTemporary, newListBoxRecord);

Open in new window

0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41789757
I think at this point we are already on purely programming issue in your code, so you're on your own :-) - especially since I don't program in C# (I do in VB) and I don't use WiX (I still use Wise).

But that said, the tried-and-true method of debugging, absent any better, is to put "messagebox" after each line in in the code, and see which one bombs out.


                  foreach (var db1 in z)
//                    {
messagebox "1"
                        View listBoxView = session.Database.OpenView("SELECT * FROM ListBox");
messagebox "2"
                        Record newListBoxRecord = new Record(4);
messagebox "3"
                        newListBoxRecord[1] = "DBaseValues";
messagebox "4"

and so on. Then when it runs, you will see which number was the last.

More elaborate is to try to debug by attaching debugger to the process in Visual Studio - see https://msdn.microsoft.com/en-us/library/3s68z0b3.aspx. However, in this case it's probably very problematic because of .ca.dll which probably won't have the symbols.
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41789766
Just doesn't make sense why adding a for loop would cause a problem.
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41789768
...by the way, if you only want to list available servers on local machine, it would be much easier with vbcript custom action that would enumerate HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL. Or if not only local but you have SQLDMO installed, you might use that in vbscript as well. Vbscript would avoid all the trouble described in the articles about using managed code in custom actions.
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41789787
It's not the code in the custom action.  It returns a "Success".  I put message boxes as you suggested.
0
 
LVL 40

Expert Comment

by:Vadim Rapp
ID: 41789791
looking at your code, it looks like you are reopening the view in every loop iteration. It's probably not what you want. Openview probably has to be outside of foreach.
0
 
LVL 1

Author Comment

by:CipherIS
ID: 41790274
Yes, I moved it outside the loop.  I thought I commented about that.  I did in ID: 41789682.  

Ok, so it is working.  Got all the bugs ironed out.  Now the only issue I have is that the license screen is not opening first.  The database screen is.  If I click on the install on the database then it will go to the license and continue to navigation and back to database screen.  Any idea how to resolve that?
0
 
LVL 40

Assisted Solution

by:Vadim Rapp
Vadim Rapp earned 500 total points
ID: 41790452
No way, for two reasons, one legal, another technical. Both just guesses, see if it makes sense. If not, post your whole wix fle.

The technical one is that sql server setup is a prerequisite, so it's being launched not by the MSI, but by setup.exe. Setup.exe installs sql server, if necessary, and only then launches the MSI. The license agreement is displayed by the MSI.

The legal one is that sql server is not your product, so you are not in position to accept or reject the license on it. From the legal standpoint, the user should read and accept the (separate) license on sql server presented by its setup.
1
 
LVL 1

Author Comment

by:CipherIS
ID: 41791278
Ok.  Thanks for that info regarding SQL.  I did resolve my issue with the screens not displaying in the right order.

The issue was that the custom action is set to run immediate so the sequence was putting it before the license on my install.  I changed the database dialog to go after the license dialog in Orca.  The custom action still has to run first.

This gets updated everytime I build.  It's a pain but at least I know what to do.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

One of the major drawbacks of deploying applications by GPO is the complete lack of any centralized reporting. After a normal deployment, there are two ways to find out if it was successful – by looking in the event log, and by looking in the log of…
If you don't know how to downgrade, my instructions below should be helpful.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now