Menu

#381 Using FileExist() in preprocessor condition statements

migrated
nobody
compiler (105)
2015-02-16
2008-04-02
Michael S.
No

Feature Request:

Support for FileExist() function call in preprocessor condition statement to check for file existence.

Rationale:

To allow to include stuff into the WiX Source depending on file existence.

Documentation input:

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>

Implementation Proposal:

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
        ...

Discussion

  • Michael S.

    Michael S. - 2010-08-06

    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.

     
  • Rob Mensching

    Rob Mensching - 2013-08-21
    • Status: open --> migrated