简体   繁体   中英

Pass ConnectionString to Custom Action in WiX Installer (escape semicolon)

This is my first project with WiX.
I'm creating an installer for Windows Service and during the installation, I need to collect some configuration data that the service will use. This includes the connection string to the database.

<Binary Id="CustomActionBinary" SourceFile="$(var.ServiceSetupActions.TargetDir)$(var.ServiceSetupActions.TargetName).CA.dll"/>
  <CustomAction
    Id="ServiceSetupActions"
    BinaryKey="CustomActionBinary"
    DllEntry="SaveCompanySettings"
    Execute="deferred"
    Return="check"
    Impersonate="no" />
  <CustomAction
    Id="SetupCustomProperties"
    Property="ServiceSetupActions"
    Value="DBTYPE=[DBTYPE];CONNECTIONSTRING=[CONNECTIONSTRING];INSTALLFOLDER=[INSTALLFOLDER]"/>

<InstallExecuteSequence>
  <Custom Action="SetupCustomProperties" Before="ServiceSetupActions" />
  <Custom Action="ServiceSetupActions" After="InstallFiles">NOT Installed</Custom>
</InstallExecuteSequence>

Problem is that WiX is using a semicolon as a data separator ( https://github.com/wixtoolset/Dtf/blob/09dc7b4e4494182c0906bf5492f12e09c918444f/src/WixToolset.Dtf.WindowsInstaller/customactiondata.cs#L32 ), so the connection string that is entered during the setup is incorrectly deserialized in my custom action.

The question is: How can I correctly pass a string that contains a semicolon to custom action (using a session.CustomActionData ) so it will not be misformed.

The alternative is a full SQL connection dialog that will ask for server, database, user name, and password, but the service can handle PostgresSQL and MS SQL and sometimes the connection strings may contain some modifications.

I see you tagged this C# so I'm assuming your using DTF custom actions.

In DTF you can create another custom action and run it in immediate execution. In that action you can create a CustomActionData collection, populate the key value pairs and then call session.DoAction() and pass it the name of the deferred custom action to schedule and the CustomActionData collection. The serialization magic will happen magically and the key value pairs will be available in the deferred custom action simply by saying session.CustomActionData(key);

Please check this sample and see if it works for you: https://github.com/glytzhkof/WiXDeferredModeSample

Here is another version of the sample, this one uses the DTF CustomActionData class for more "auto-magic": https://github.com/glytzhkof/WiXDeferredModeSampleDTF - it will schedule the custom actions for you and you can just access the properties in deferred mode. Limited testing done.

  1. Set an upgrade GUID in this source line where it says "PUT-GUID-HERE" - you can create a GUID here .

  2. Change the property MYPROPERTY to contain semicolons ; . Do so at this WiX source line . You can use the below sample text if you like (anything else will do of course):

     <Property Id="MYPROPERTY" Hidden="yes" Secure="yes">Test;Test1;Test2</Property>
  3. Compile and do a test run. There will be a message box showing and it should contain the full string you specified in the source file.


If you want to combine several property values inside the string you send to deferred mode you have a few options. The simplest is to set several properties with the values you need and then combine them in a string sent to deferred mode. You can set the properties in several ways: dialog, command line, input boxes, etc...:

  • MYCOMPANY = "Some Company"
  • MYDATABASE = "TheDatabaseName"
  • Etc...

Then you call Session.Format in an immediate mode custom action to resolve values in your string. Something like this:

COMPANYID=[COMPANYID];DBTYPE=[DBTYPE];CONNECTIONSTRING=[CONNECTIONSTRING];INSTALLFOLDER=[INSTALLFOLDER]

var CAdata = Session.Format("MYCOMPANY=[MYCOMPANY];MYDB=[MYDB];MYDBTYPE=[MYDBTYPE]");
session["MYPROPERTYSENTTODEFERREDMODE"] = CAdata;

You also need a Type 51 CA to actually send that string to the deferred mode custom action. You see how that is done in the sample above.

Then you retrieve the string value of MYPROPERTYSENTTODEFERREDMODE in a deferred mode custom action and you should be able to use it directly?


Links :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM