I am reading WIX script written by others. There are some code really confuses me.
<Custom Action='UnLoadSchedulerPerfCounters' After='InstallInitialize'>
<![CDATA[(Installed) AND (!Scheduler = 3)]]>
</Custom>
<Custom Action='RollbackSchedulerPerfCounters' After='WriteRegistryValues'>
<![CDATA[(&Scheduler = 3)]]>
</Custom>
So, what's the difference between !Scheduler and &Scheduler?
Is any special meaning when property is prefix-ed by & or !?
From http://www.tramontana.co.hu/wix/lesson5.php#5.3:
Prepending some special characters to
the names will give them extra
meaning:
% environment variable (name is case insensitive)
$ action state of component
? installed state of component
& action state of feature
! installed state of feature
The last four can return the following
integer values:
-1 no action to be taken
1 advertised (only for components)
2 not present
3 on the local computer
4 run from the source
Those are operators on the Windows Installer condition syntax. See this MSI SDK documentation for a complete list: http://msdn.microsoft.com/en-us/library/aa368012.aspx.
Related
I have an WiX installer configured like this:
<Property Id="MY_PROPERTY">
...
<Registry Name="MyValue" Type="multiString" Value="[MY_PROPERTY]" />
Now I want to pass this property value at the command line as a list:
MsiExec.exe /i MyInstaller.msi /qb MY_PROPERTY="One[~]Two[~]Three"
However, the installer does not split the values into a list and the literal value is written instead.
If I hard code the element it works properly:
<Registry Name="MyValue" Type="multiString" Value="One[~]Two[~]Three" />
Does anyone know how to specify a list of values at the command-line for a multiString registry value? Thanks in advance
Better late than never!
This can be achieved using a Custom Action.
Follow this MS document carefully: https://learn.microsoft.com/en-us/windows/win32/msi/registry-table
In your custom action, insert the registry value into MSI table from your property as follows,
Set db = Session.Database
set oView = db.OpenView("INSERT INTO `Registry` (`Registry`,`Root`,`Key`,`Name`,`Value`,`Component_`) VALUES ('reg_MY_PROPERTY', -1,'Software\Company\Product','MyValue','" & _
Session.Property("MY_PROPERTY") & "','CM_CP_BlahBlah') TEMPORARY")
oView.Execute
oView.Close
CM_CP_BlahBlah is your WIX component Registry values are attached to.
Please note "custom action must come before the RemoveRegistryValues and WriteRegistryValues actions in the action sequence"
<InstallExecuteSequence>
<Custom Action="SetMyPropertyCustomAction" Before="RemoveRegistryValues">NOT REMOVE</Custom>
</InstallExecuteSequence>
REG_MULTI_SZ
A sequence of null-terminated strings, terminated by an empty string (\0).
The following is an example:
String1\0String2\0String3\0LastString\0\0
The first \0 terminates the first string, the second to the last \0 terminates the last string, and the final \0 terminates the sequence. Note that the final terminator must be factored into the length of the string.
So as per this LINK you should be doing this:
MY_PROPERTY="One\0Two\0Three\0"
For MULTISTRINGValues check this element: MULTISTRINGVALUE
I would like to write a value to registry which consists of installation path and some additional path. Delimiter must be '/', e.g.
Value="[INSTALLLOCATION]/folder1/folder2"
How can I format this value so that installation path will be also with '/' delimiter instead of '\'?
MSI formatting doesn't support this. You'd have to write a custom action that read the property, reformatted the string and wrote it to a new property ( INSTALLLOCATIONFORMATTED) then you could use that property in the Registry table.
The bigger question and simpler answer though is .... "why?"
Are you doing something like file://c:/foo/bar.txt ?
file://C:\foo\bar.txt should work also as \ is the standard on the Windows Platform. It's probably better that whatever code reads this registry value be modified to accept \ instead of /. This results in a simpler and less fragile installer.
I'm trying to setup a custom action to initialize my SQLite database using the sqlite3.exe command line tool. In a command prompt I type the following: c:\sqlite3.exe database.db < sqlscript.sql
My Wix custom action falls apart in the ExeCommand attribute because I cannot seem to escape out the <.
<CustomAction Id="InitializeDatabase" FileKey="SQLiteEXE" ExeCommand="database.db < sqlscript.sql" Execute.../>
I've tried "<" as well.
I know I could just install an empty initiailzed database but I'm curious how to redirect inputs.
Thanks.
So, what exactly is happening when you say it falls apart? Does it compile?
Just so that we're on the same page, are you ending you XML entity with the semi-colon. You probably are, but it didn't come through in your code sample. Are you using:
<
If that doesn't work, you could try putting the command into a property and using CDATA tags, such as:
<Property Id="MyCommand">
<![CDATA[
database.db < sqlscript.sql
]]>
</Property>
and using that in the ExeCommand attribute:
ExeCommand="[MyCommand]"
That might work.
If you really have to call an EXE, I reccomend using the WiX QuietExec Custom Action pattern. Worse case you could install a .BAT file then use the cmd /c foo.bat command to call it. Then you wouldn't have to escape the <.
Otherwise I would search for an alternative to the EXE. I try to stick with data driven custom actions that run in process ( say C++ or C#/DTF ).
Quiet Execution Custom Action
I have a custom action inside an MSI installer that makes some changes to some configuration file. my requirement is to run the installation in silent mode so I am using msiexec.
Here is the command:
msiexec /i myInstaller.msi /l* out.txt myContextParameter=value1
myContextParameter is never passed to the custom action so when I do
context.Parameters["myContextParameter"] I get a null value.
When I run my MSI in UI mode the parameter is passed correctly. I also made sure the name of the property is correctly set in the CustomActionData.
I've been beating my head against the wall on this one, so here's what I found out:
You have to set your parameters on the commandline, as well as on the "CustomActionData" property on each of your Custom Actions (whatever you have under Install, Commit, etc)
Your commandline will look something like this:
msiexec /i myInstaller.msi MYFIRSTPARAM=VALUE1 MYSECONDPARAM=VALUE2
Then, your CustomActionData should look like this:
/myfirstparam=[MYFIRSTPARAM] /mysecondparam=[MYSECONDPARAM]
Now, here's a bunch of special cases:
It looks like #Klaus is right, you need to use ALLCAPS in your parameter names.
if your values contain spaces, you'll need quotes around them in both the commandline and your CustomActionData properties, as in:
msiexec /i myInstaller.msi MYFIRSTPARAM="VALUE1" MYSECONDPARAM="VALUE2"
/myfirstparam="[MYFIRSTPARAM]" /mysecondparam="[MYSECONDPARAM]"
if your values end with a slash, like most file paths do, you'll have a weird problem: when the msiexec builds your customactiondata, it'll create this string:
/myfirstparam="C:\myfile\" /mysecondparam="C:\myfile\"
it doesn't matter if you use quotes on the commandline or not, if that slash is the last character on your value, it will effectively be read as an escape character, and will escape the quote in your customactiondata property. This causes havoc. The solution is to either 1) add a space between your parameter and the last quote, and then remember to trim() it in your code somewhere, or 2) add and extra slash between your parameter and quote, in order to escape the escape character. See both methods below:
/myfirstparam="[MYFIRSTPARAM] " /mysecondparam="[MYSECONDPARAM]\"
Hope that helps.
MixedCase properties are "private" and will not be passed in from the command line.
ALLCAPS properties are "public" and can be passed in on the command line.
However only secure public properties are passed through to the 'server' (i.e. retained during UAC elevation). See the SecureCustomProperties property documentation.
Assuming you're trying to access this property in a deferred CA, this is happening on the server side so you need to use a public property (all caps) that is also marked as secure.
Here's an example using WiX:
<Property Id="MYPUBLICPROPERTY" Secure="yes" Value="{}">
If you want to be able to pass parameters from the outside you need to use ALLCAPS in your parameter names. I know it sounds weird, but try it! :-)
I know this is an old thread, but I tried a variety of things here and it seemed that I was at a loss. I then found the following thread on msdn:
http://social.msdn.microsoft.com/Forums/windows/en-US/8dd009ce-52d5-4737-98c8-89d9831ab60b/unable-to-pass-parameters-to-msi-thro-msiexec-via-command-prompt?forum=winformssetup&prof=required
Viewing the MSI in ORCA, you can see a few entries under "CustomAction." These Entries will basically override the values passed in from the command prompt. If you simply delete the entries in the CustomAction Table like: "CustomTextA_SetProperty_EDIT1" and then save the MSI (Save AS has a different behavior in ORCA). You can then pass the Property Values from the command line to the MSI. This will allow me to install remotely using msiexec and I am now be able to pass the parameters to the install via the command line. I imagine this happens because the logic for the CustomAction values is executed after having populated the property values from the command line which means that the CustomAction values overwrite the command line populated values.
There is also a link at the bottom of the thread to do some manipulation in VS as opposed to ORCA.
http://blogs.technet.com/b/alipka/archive/2007/04/20/how-to-use-custom-actions-in-visual-studio-setup-project-msi-from-command-line.aspx
On a Windows 7 machine I cannot read any registry values that contain a semicolon.
For example if you have 7-zip, running the following
SET(MYPATH [HKEY_LOCAL_MACHINE\\SOFTWARE\\7-Zip;Path])
MESSAGE("MYPATH = ${MYPATH}")
results in
MYPATH = [HKEY_LOCAL_MACHINE\SOFTWARE\7-Zip;Path]
instead of the actual path as per the following thread. I think cmake support for registry paths that contain ";" are broken on Windows 7. Can somebody confirm this? Is there any work-around?
According to the wiki, you can't use SET to view the value of a registry key. The registry value is only read when you do some cache operation on it. For example, the following should output the path you want:
GET_FILENAME_COMPONENT(MYPATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\7-Zip;Path]"
ABSOLUTE CACHE)
MESSAGE("MYPATH = ${MYPATH}")