This project is read-only.
Home What's New Properties Command Line Managing Properties MSI Integration Samples Roadmap



What's New

2.0.18

New Features

  • For XML Spreadsheet 2003 format, used the frozen row at the top of the worksheet to indicate the beginning of the values. This prevents you from having to start your values at row 7. This can be overridden with the /firstValueRow (or /vr) argument.

Issues Fixed

  • Fix for Issue 13006 : Corrected default treatment of the value "false"

    Beginning with this version, the FixFalse behavior that has caused confusion to so many, has hopefully been addressed in a way that still accommodates those who need backward compatibility.

    The /FixFalse switch was introduced in Beta 1 to address issues caused when a settings has the value of  False.  When a value is False, the old behavior was to undefine the setting. This caused errors when you wanted to insert a literal "False" (a common value in configuration files). The workaround was to put the value in quotes, or pass the /f or /FixFalse switch.

    There are now two executables in the binary package, one that breaks backward compatibility, and does the right thing by defaulting FixFalse to True (XmlPreprocess.exe), and one that maintains backward compatibility (XmlPreprocess-NoFixFalse.exe).  Use the executable that is appropriate for your needs. If you are new to XmlPreprocess, most likely you're going to want to use XmlPreprocess.exe, and forget about the NoFixFalse version.

    • XmlPreprocess.exe - This version defaults FixFalse to true, so you no longer need to pass it.
    • XmlPreprocess-NoFixFalse.exe - This version is the old behavior.  If you require the old behavior, feel free to rename this file to be XmlPreprocess.exe, and use it instead.

2.0.17

New Features

  • Added three built-in properties useful in building absolute paths without hard-coding drive letters.
    • ${_dest_root} - Expands to the root of the destination file path (ex: "C:\")
    • ${_system_root} - Expands to the root of the system directory (ex: "C:\")
    • ${_current_root} - Expands to the root of the current directory as determined by Environment.CurrentDirectory (ex: "C:\")
  • Nested Properties: You can build property names from other properties.
    • Example: ${PROPERTY_${_machine_name}}. - In this example if your machine is named SERVER1 the nested property will be resolved first, the preprocessor will then look for a property named ${PROPERTY_SERVER1}
    • Note: This is not supported when using custom tokens with the start and end tokens matching.
  • Fallback Properties: You can now specify multiple property names delimited by semicolons in a single macro, and the preprocessor will try each one and perform the substitution for the first property it finds that was defined.
    • Example: ${PROPERTY1;PROPERTY2;PROPERTY3} - In this example, the preprocessor will first look for PROPERTY1, if it was not defined it will proceed to check for PROPERTY2 etc.  When it encounters a property that is defined, it will substitute that value and stop.
    • Note: This change makes it invalid to have semicolons in your property names.
  • Machine-Specific Settings: If you have settings that are unique to specific machines, you can do the following: (This common requirement is just an application of the new nested and fallback features)
    1. Define a set of properties (typically done in your Excel spreadsheet) for each machine and usually a fallback value
        PROPERTY = fallback value
        PROPERTY_SERVER1 = server 1's value
        PROPERTY_SERVER2 = server 2's value
    2. Use this nice and tidy replacement macro in your configuration file. (Note the use of both nested and fallback properties and compare to the legacy way to accomplish this in #3 below)
        ${PROPERTY_${_machine_name};PROPERTY}
      • When deployed on SERVER1, it will use the value for PROPERTY_SERVER1
      • When deployed on SERVER2, it will use the value for PROPERTY_SERVER2
      • On all other machines (ex: SERVER3), it will look for PROPERTY_SERVER3, not find it defined, and just fall back to PROPERTY
    3. Note: This was possible before the addition of nested and fallback properties, but it was fairly ugly and involved using scripting to do something like this:
      • ${Script= defined("PROPERTY_" + GetProperty("_machine_name")) ? GetProperty("PROPERTY_" + GetProperty("_machine_name")) : GetProperty("PROPERTY") }

Issues Fixed

  • Fix for Issue 12863 : Fix for resolving content when using custom token that differs in length from the default of "${" and "}".

2.0.16

New Features

  • Added MSBuild tasks and sample
  • Added WiX sample that uses WixCA
  • Local copy of the documentation included in the download
  • Made the old XML settings files also optionally support multiple environments by allowing you to specify nested <environment name="prod">prodvalue</environment> elements within the <property> elements.  This is backward compatible, and the old flatter format (single value) continues to work just fine, but you can now use the settings files as simplified spreadsheets and pass an additional /e: argument just like you do with them.
  • Added ability to count the number of times a property was used. This may be useful for cleaning unused values from spreadsheets. The argument is /countReportFile (or /cr) and you pass the name of a CSV file in which you want the counts written at the end of the preprocessing.
  • Converted solutions and projects to Visual Studio 2010
  • Web app to manage settings in database (not in distribution, only in Source Control)
  • Enabled an empty environment to be passed using the argument format /e:"" (then it will prompt for environment).
  • Fixed a defect in the Spreadsheet XML reader when cells are set to be Boolean data type, translated "1" and "0" to "True" and "False"

2.0.15

New Features

  • CSV files can be used as a source for configuration settings
  • SQL Server Databases can be used as a source for configuration settings
  • Custom data sources can be written to pull configuration settings from wherever you have them stored
  • Settings files and spreadsheets can be specified with a URL to enable them to be served up (or dynamically built) with a web server
  • Values can be read from the registry
  • Files to preprocess can be specified with a wildcard (for example: xmlpreprocess /i *.config ... would preprocess all *.config files)
  • The tokens used for replaceable properties can be overridden from the default (example: use $(..) instead of ${..} )

2.0.14
This release contains a very minor change in behavior to the order that settings files are read.


Issues Fixed

  • Reversed the order of reading spreadsheets and XML settings files. Previously, XML settings files were read first, then spreadsheets which prevented the use of XML settings files as overrides.

This allows you to do this:
xmlpreprocess.exe /x:spreadsheet.xml /s:overrides.xml ...
Where spreadsheet.xml is an Excel spreadsheet, and overrides.xml is an XML file that contains settings you want to override from the spreadsheet. For example if you have a spreadsheet setting named "foo", and overrides.xml looks like this, then "override value" will be used instead of whatever is in the spreadsheet.
<settings>
<property name="foo">override value</property>
</settings>
Previously this wasn't possible because the XML settings files were read first, and the spreadsheets were read second and overwrote whatever was in the XML settings files.

 

2.0.13
This release is a very minor bug fix release.

Issues Fixed

  • When multiple files are passed on the command line separated by semicolons, now empty files will quietly be skipped whereas before they would cause an error. The following would have exited with an error because xmlpreprocess assumed you were passing three files, even though the third file was an empty string, it would try to locate the file and exit saying the file "" did not exist. This makes building lists of files easier in scripts without needing to be so strict about eliminating the trailing semicolon.
Example:
xmlpreprocess /i file1.config;file2.config; ...
  • The spreadsheet for the binding example was updated to reflect the need to root your XPath expressions (Issue Request) This was a change ONLY to the sample spreadsheet. Due to some changes in the way the XPath is evaluated, the XPath now needs to be rooted, so the sample should have been updated to contain a slash at the beginning as shown below

Before:
${Xpath=configuration/...
After:
${Xpath=/configuration/...

 

2.0.12

New Features


Issues Fixed



For Each
Imagine you have a semicolon delimited list of server names in a property value like Servers=Server1;Server2;Server3, and you would like to repeat a section of XML configuration for each server. There isn't a good way to do this with previous versions of XmlPreprocess. Version 2.0.12.0 introduces a #foreach construct.
Examples:
Given a property like: Servers=Server1;Server2

<servers>
  <server name="Server1"/>
  <server name="Server2"/>
</servers>

Given a property like: Servers=Server1;Server2;Server3

<servers>
  <server name="Server1"/>
  <server name="Server2"/>
  <server name="Server3"/>
</servers>

Given two properties like: Servers=Server1;Server2, and Addresses=Address1;Address2

<servers>
  <server name="Server1" address="Address1"/>
  <server name="Server2" address="Address2"/>
</servers>

Example 1 - Simple Case
The body of the #ifdef will be repeated once for each value in the semicolon delimited list of the SomeVal property.
Input.xml:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal) <entry foo="${SomeVal}"/> -->
  <!-- #else -->
  <entry foo="One"/>
  <!-- #endif -->
</xml>

Command:
XmlPreprocess /i:Input.xml /d:SomeVal=One;Two
Output:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal) <entry foo="${SomeVal}"/> -->
  <!-- #else -->
  <entry foo="One"/>
  <entry foo="Two"/>
  <!-- #endif -->
</xml>

Example 2 - Multiple Values
Two properties can be expanded in parallel into one section of markup.
Input.xml

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal) <entry foo="${SomeVal}" bar="${SomeOtherVal}"/> -->
  <!-- #else -->
  <entry foo="One" bar="Alpha"/>
  <!-- #endif -->
</xml>

Command:
XmlPreprocess /i:Input.xml /d:SomeVal=One;Two /d:SomeOtherVal=Alpha;Beta
Output:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal) <entry foo="${SomeVal}" bar="${SomeOtherVal}"/> -->
  <!-- #else -->
  <entry foo="One" bar="Alpha"/>
  <entry foo="Two" bar="Beta"/>
  <!-- #endif -->
</xml>

Example 3 - Multiple Values with different lengths
The two lists do not have to be the same length. Note that SomeVal and SomeOtherVal have different number of items.
Input.xml

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal) <entry foo="${SomeVal}" bar="${SomeOtherVal}"/> -->
  <!-- #else -->
  <entry foo="One" bar="Alpha"/>
  <!-- #endif -->
</xml>

Command:
XmlPreprocess /i:Input.xml /d:SomeVal=One;Two /d:SomeOtherVal=Alpha
Output:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal) <entry foo="${SomeVal}" bar="${SomeOtherVal}"/> -->
  <!-- #else -->
  <entry foo="One" bar="Alpha"/>
  <entry foo="Two" bar=""/>
  <!-- #endif -->
</xml>

Example 4 - Repeated body spans multiple lines
The expanded section can be multiple lines.
Input.xml

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal)
  <wrapper>
    <entry foo="${SomeVal}"
           bar="${SomeOtherVal}"/>
  </wrapper>
  -->
  <!-- #else -->
  <wrapper>
    <entry foo="One"
           bar="Alpha"/>
  </wrapper>
  <!-- #endif -->
</xml>

Command:
XmlPreprocess /i:Input.xml /d:SomeVal=One;Two /d:SomeOtherVal=Alpha
Output:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!--
  #foreach(SomeVal,SomeOtherVal)
  <wrapper>
    <entry foo="${SomeVal}"
           bar="${SomeOtherVal}"/>
  </wrapper>
  -->
  <!-- #else -->
  <wrapper>
    <entry foo="One"
           bar="Alpha"/>
  </wrapper>
  <wrapper>
    <entry foo="Two"
           bar=""/>
  </wrapper>
  <!-- #endif -->
</xml>

Example 5 - Repeated body spans multiple comments
The expanded section can be in multiple comments.
Input.xml

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!-- #foreach(SomeVal,SomeOtherVal) -->
  <!-- <wrapper> -->
  <!--   <entry foo="${SomeVal}" bar="${SomeOtherVal}"/> -->
  <!-- </wrapper> -->
  <!-- #else -->
  <wrapper>
    <entry foo="One" bar="Alpha"/>
  </wrapper>
  <!-- #endif -->
</xml>

Command:
XmlPreprocess /i:Input.xml /d:SomeVal=One;Two /d:SomeOtherVal=Alpha
Output:

<xml>
  <!-- #ifdef _xml_preprocess -->
  <!--
  #foreach(SomeVal,SomeOtherVal)
  <wrapper>
  <entry foo="${SomeVal}" bar="${SomeOtherVal}"/>
  </wrapper>
  -->
  <!-- #else -->
  <wrapper>
  <entry foo="One" bar="Alpha"/>
  </wrapper>
  <wrapper>
  <entry foo="Two" bar=""/>
  </wrapper>
  <!-- #endif -->
</xml>



Xpath on include
An optional xpath expression can be specified on an #include to address a single node in the included XML document that is to be included. The XPath expression can also contain macros.

--Input.xml--

<xml>
  <!-- #include "Include.xml" xpath="/environments/environment[@name='${_environment_name}']" -->
</xml>

--Include.xml--

<environments>

  <environment name=""Development"">
    <connectionStrings>
      <developmentConnectionStrings/>
    </connectionStrings>
  </environment>

  <environment name=""Production"">
    <!-- COMMENT -->
    <connectionStrings>
      <productionConnectionStrings/>
    </connectionStrings>
  </environment>

</environments>


--Command Line--
Xmlpreprocess /i:Input.xml /e:Production /o:Output.xml

--Output.xml--

<xml>
  
    <!-- COMMENT -->
    <connectionStrings>
      <productionConnectionStrings />
    </connectionStrings>
  
</xml>



2.0.11

What's new in this release:
This is a large release containing a number of enhancements based on feedback given through the discussion forums and issue tracker. Thanks for your excellent suggestions, and keep them coming. I couldn't get to all of them, but wanted to get this release out as soon as possible. Backward compatibility is a priority, so I'm always trying to figure out how to add your new feature requests without impacting any existing behavior. With this release, I'm abandoning the concept of labeling releases as Beta or Release Candidates, and just going to a straight numbered versioning system. It became clear that with all of the great ideas out there, it will be difficult to call it "done", so this is version 2.0.11.


New Preferred Directive Syntax
XmlPreprocess now optionally supports an alternate directive syntax using the hash symbol (#ifdef instead of ifdef). This is more consistent with preprocessors in other languages.

<!-- #ifdef setting -->
<!-- #else -->
<!-- #endif -->

This old format is still supported, but it is now preferred to write your directives using this syntax. Note that leaving the ${ } out from the ifdef condition is also more "proper". (<!-- #ifdef setting --> instead of <!-- #ifdef ${setting} -->). I will try to convert the documentation over to using the new syntax, but it's in a lot of places, and it may take a while to get them all.

New Validation Arguments
New command line arguments to enable two different types of validation individually. It became necessary to control validation separately when the new /noDirectives argument enabled non-XML formats (see: http://xmlpreprocess.codeplex.com/Thread/View.aspx?ThreadId=60626). Previously there was only one switch (/validate or /v) that validated whether all settings existed and that the output was well-formed XML. Now there are three switches:

  • /validateSettingsExist (short version: /vs) Validate settings exist, return an error if any substitution settings are undefined
  • /validateXmlWellFormed (short version: /vx) Validate resulting XML is well-formed, return an error if the result document is not well-formed.
  • /validate (short version: /v) Validate all, turns on /validateSettingsExist, and /validateXmlWellFormed (this is identical to the old behavior)


New built-in property ${_environment_name}
A new built-in property ${_environment_name} was added to contain the name of the environment passed in with the /e argument (see http://xmlpreprocess.codeplex.com/WorkItem/View.aspx?WorkItemId=3807). This property comes in handy when paired with the new Includes feature.

input.xml:

<xml>
    <!-- #ifdef _xml_preprocess -->
    <!-- <entry foo="${_environment_name}"/> -->
    <!-- #else -->
    <entry foo="Development"/>
    <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml /x SettingsSpreadsheet.xml /e Production

Output:

<xml>
    <!-- #ifdef _xml_preprocess -->
    <!-- <entry foo="${_environment_name}"/> -->
    <!-- #else -->
    <entry foo="Production"/>
    <!-- #endif -->
</xml>


Ability to define properties inside the input file
You can now define properties inside the input file in define statements (see http://xmlpreprocess.codeplex.com/WorkItem/View.aspx?WorkItemId=3823)

input.xml:

<xml>
   <!-- #define SomeNewValue = "new_value" -->
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${SomeNewValue}" /> -->
   <!-- #else -->
   <entry foo="dev_value" />
   <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml

Output:

<xml>
   <!-- #define SomeNewValue = "new_value" -->
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${SomeNewValue}" /> -->
   <!-- #else -->
   <entry foo="new_value" />
   <!-- #endif -->
</xml>

Or alternately, a setting could be renamed like this:

input.xml:

<xml>
   <!-- #define SomeNewValue = ${sometoken} -->
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${SomeNewValue}" /> -->
   <!-- #else -->
   <entry foo="dev_value" />
   <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml /d sometoken=new_value

Output:

<xml>
   <!-- #define SomeNewValue = ${sometoken} -->
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${SomeNewValue}" /> -->
   <!-- #else -->
   <entry foo="new_value" />
   <!-- #endif -->
</xml>


Includes
You can now include external XML files using the <!-- #include "external-file.xml" --> syntax. (see http://xmlpreprocess.codeplex.com/Thread/View.aspx?ThreadId=44434). If the path is relative, it will be resolved from the location of the file being processed.

input.xml:

<xml>
   <!-- #include "include.xml" -->
</xml>

include.xml:

   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${val1}" /> -->
   <!-- #else -->
   <entry foo="bar" />
   <!-- #endif -->

Command Line:
xmlpreprocess /i input.xml /d val1=abc

Output:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${val1}" /> -->
   <!-- #else -->
   <entry foo="abc" />
   <!-- #endif -->
</xml>

The file name can contain macros that will be resolved during preprocessing. When coupled with the new _environment_name property, some interesting things can be done by having external environment-specific fragment included as shown below. (Alternatively the entire file could be specified in a macro like this <!-- #include "${includedFileName}" -->)

input.xml:

<xml>
   <!-- #include "included-${_environment_name}.xml" -->
</xml>

included-Production.xml:

   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${val1}" /> -->
   <!-- #else -->
   <entry foo="bar" />
   <!-- #endif -->

Command Line:
xmlpreprocess /i input.xml /d val1=abc /e Production

Output:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${val1}" /> -->
   <!-- #else -->
   <entry foo="abc" />
   <!-- #endif -->
</xml>


${} Escaping
You can now have property values that contain the ${..} sequence in them by escaping them using $${{..}} syntax. (see http://xmlpreprocess.codeplex.com/Thread/View.aspx?ThreadId=61074)

input.xml:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${PROPERTY}"/> -->
   <!-- #else -->
   <entry foo="abc"/>
   <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml /d PROPERTY=$${{newvalue}}

Output:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!-- <entry foo="${PROPERTY}"/> -->
   <!-- #else -->
   <entry foo="${newvalue}"/>
   <!-- #endif -->
</xml>


Nested Comments
XML comments cannot be nested. This made it impossible to include comments in the commented-out #ifdef branch. You can now embed specially formatted "spaced out" comments in the commented out branch using the format < ! - - and - - > (Note the additional space between each character). These comments will get transformed into regular XML comments upon preprocessing (see http://xmlpreprocess.codeplex.com/Thread/View.aspx?ThreadId=49128).

input.xml:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!--
   < ! - - This is a nested comment - - >
   <entry foo="${PROPERTY}"/>
   -->
   <!-- #else -->
   <entry foo="abc"/>
   <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml /d PROPERTY=newvalue

Output:

<xml>
   <!-- #ifdef _xml_preprocess -->
   <!--
   < ! - - This is a nested comment - - >
   <entry foo="${PROPERTY}"/>
   -->
   <!-- #else -->
   <!-- This is a nested comment -->
   <entry foo="newvalue"/>
   <!-- #endif -->
</xml>


Embedded C# Scripts
Property values can now contain embedded C# scripts that evaluate to a string. Rather than implementing a full expression language like NAnt did, I took a very simple approach of taking the expression and dynamically compiling it into a C# class and executing it. This is not a terribly efficient way to do it, but it does unlock the full power and expressiveness of C# and the .NET framework. To retrieve the value of a property use the built-in GetProperty("propertyname") method. To test if a property is defined use the built-in defined("propertyname") method.

input.xml:

<xml>
   <entry foo="${Script= GetProperty("val1")=="abc" ? "yes" : GetProperty("val3") }" />
   <entry foo="${Script= GetProperty("val1").IndexOf("a")==-1 ? "yes" : GetProperty("val3") }" />
   <entry foo="${Script= GetProperty("val1") + GetProperty("val3") }" />
</xml>

Command Line:
xmlpreprocess /i input.xml /d val1=abc /d val3=no /n

Output:

<xml>
   <entry foo="yes" />
   <entry foo="no" />
   <entry foo="abcno" />
</xml>


#if expressions
A new #if directive has been added that can contain embedded C# scripts that evaluate to a boolean value. Rather than implementing an expression language like NAnt did, I took a very simple approach of taking the expression and dynamically compiling it into a C# class and executing it. This is not a terribly efficient way to do it, but it does unlock the full power and expressiveness of C# and the .NET framework. To retrieve the value of a property use the built-in GetProperty("propertyname") method. To test if a property is defined use the built-in defined("propertyname") method (example: <!-- #if defined("DoServerCheck") -->).

In this example the substitution would only be done when run on a machine named SERVER1 or SERVER2, but not on any other machine.

input.xml:

<xml>
   <!-- #if GetProperty("PrimaryServers").IndexOf(GetProperty("_machine_name")) > -1 -->
   <!-- <entry foo="${SomeValue}"/> -->
   <!-- #else -->
   <entry foo="False"/>
   <!-- #endif -->
</xml>

Command Line:
xmlpreprocess /i input.xml /d SomeValue=abc /d DoServerCheck=True /d PrimaryServers=SERVER1;SERVER2

Output (when run on SERVER1 or SERVER2):

<xml>
   <!-- #if GetProperty("PrimaryServers").IndexOf(GetProperty("_machine_name")) > -1 -->
   <!-- <entry foo="${SomeValue}"/> -->
   <!-- #else -->
   <entry foo="abc"/>
   <!-- #endif -->
</xml>


More details can be found on the release notes for each release referenced below
RC2

  • Added a /noDirectives argument (/n for short) that treats the entire file as a single unit and just globally replaces all ${macro} values it encounters. It does not require any ifdef/else/endif directives. It works on all text file formats not just XML, so you can now replace macros in INI, CSV files etc.

RC1

  • Fixed bug when extracting values using the /p argument. It did not properly resolve values that contained macros to other settings.

Beta 8

  • Only prompting for environment and exiting, useful for scripting together multiple preprocessing steps without prompting each time

Beta 7

  • Dumping property values
  • #defines
  • UAC Run As Administrator shim executable

Beta 6

  • Dumping environments

Beta 5

  • Fixes to Excel XML Spreadsheet handling

Beta 4

  • XPath and Regex dynamic properties
  • /v also validates well-formedness.

Beta 3

  • Multiple input/output files
  • Prompting for environment name if not passed

Beta 2

  • Fixes to Excel XML Spreadsheet handling

Beta 1

  • Requires .NET 2.0 or newer runtime
  • Adds the ability to import spreadsheets directly thanks to Tom Abraham's excellent work on the Environment Settings Manager project.
  • Adds a command line switch (/f or /fixfalse) to fix the behavior of "False" values. This has been a long-standing request.
  • Adds a new command line switch (/v) to validate tokens, so if any replacement tokens are missing, it will report an error message identifying the missing tokens, return a nonzero error code and not write out the file

Last edited Jul 31, 2013 at 11:01 AM by lorenh, version 31

Comments

No comments yet.