Support for FileExist() function call in preprocessor condition statement to check for file existence.
To allow to include stuff into the WiX Source depending on file existence.
You can use the preprocessor function FileExist() in condition statements to check whether a file exists on your computer. The function returns true if the file exist, else false. You can use the usual WiX variable syntax to build up the argument.
Note: The argument to FileExist must not be quoted and does not accept wilcard characters (i.e. * or ?)
Technical Writer: The code uses the C# method File.Exists() which may inspire for additional documentation input. See:
http://msdn2.microsoft.com/en-us/library/system.io.file.exists.aspx
Examples:
1) Includes the "C:\MyInstall\include.wxs" wix source file if it exists.
<?if FileExist(C:\MyInstall\include.wxs)?> <?include C:\MyInstall\include.wxs?> <?endif?>
2) Includes a specific file source into a component if it exists.
<Component Id="UserGuide" Guid="..."> <?if FileExist($(env.SrcDir)\Doc\Spanish\User Guide.pdf)?> <File Source="$(env.SrcDir)\Doc\Spanish\User Guide.pdf" KeyPath="yes"/> <?else?> <File Source="$(env.SrcDir)\Doc\English\User Guide.pdf" KeyPath="yes"/> <?endif?> </Component>
I've made a very rough (but working) implementation into the "wix\src\wix\Preprocessor.cs" file.
The following code changes, introducing the FileExist, should be applied to cvs revision 1.35 of the preprocesor.cs file (I don't have write/cvs commit access myself):
line 877: ...
else if (expression.StartsWith("$(") || expression.StartsWith("FileExist("))
{
// Find the ending paren of the expression
int endingParen = -1;
int openedCount = 1;
int startPos = expression.IndexOf('(')+1;
for (int i = startPos; i < expression.Length; i++ )
...
line 999:
private string EvaluateVariable(string originalExpression, string variable) { // By default it's a literal and will only be evaluated if it // matches the variable format string varValue = variable; if (variable.StartsWith("$(")) { ... } else if (variable.StartsWith("FileExist(")) { try { varValue = null; string file = variable.Substring(10,variable.Length-11); try { file = this.core.PreprocessString(this.GetCurrentSourceLineNumbers(), file); if (File.Exists(file)) varValue = ""; } catch (ArgumentNullException) { // non-existent variables are expected varValue = null; } } catch(ArgumentNullException) { varValue = null; } } else if (variable.IndexOf("(") != -1 || variable.IndexOf(")") != -1) { // make sure it doesn't contain parenthesis ...
line 1114:
private bool EvaluateAtomicExpression(string originalExpression, ref string expression) { // Quick test to see if the first token is a variable bool startsWithVariable = expression.StartsWith("$("); // ... or FileExist preprocessor function bool startsWithFileExist = expression.StartsWith("FileExist("); ... // If the variables don't exist, they were evaluated to null if (null == leftValue || null == rightValue) { ... } else if (operation.Length == 0) { // There is no right side of the equation. // If the variable/function was evaluated, it exists, so the expression is true if (startsWithVariable || startsWithFileExist) { expressionValue = true; } else ...
Is there any reason for why this feature should not be included in WiX?
I have more or less already given the needed changes (though changes was tested using WiX 3.0 source files) so it should be a nobrainer to implement this feature.