How to escape quote marks in Exec Command in MSBuild - msbuild

I'm trying to build an MSBuild script that maps a network drive to a drive letter in the script, but unfortunately the path to the target folder includes an embedded space. The embedded space causes the mapping to fail, and I don't know if it is possible to escape quotes around the path. I've tried double quote marks, but MSBuild doesn't like it (either that or Windows XP doesn't like it). Anyone know how to code this beast so the map works?
<Exec Command="net use x: \\ofmapoly703\c$\program files\ar\iap /user:$(UserID) $(Password)"
WorkingDirectory="c:\"
ContinueOnError="false"
/>
The embedded space of course occurs in "program files".

Use " to encode the double quotes that you want net to see inside the Command attribute value :
<Exec Command="net use x: "\\ofmapoly703\c$\program files\ar\iap" /user:$(UserID) $(Password)"
WorkingDirectory="c:\"
ContinueOnError="false"
/>

You can use single quotes for command ,e.g.
<Exec Command='explorer.exe "$(DestinationDir)"' IgnoreExitCode="true" />
(From MSBuild exec task without blocking)

Escape the quotation marks - instead of "foo bar baz", use %22foo bar baz%22.
The hex value of " is 22.
References
Escape special characters in MSBuild
MSBuild special characters

As detailed by #Michael-Freidgeim the solution to this is to single quote, however you still have issue with trailing slashes (in Paths) being treated as escape characters in certain circumstances, a good method to avoid that would be to follow any folder paths with a dot (.)

Related

How to pass feature file path with included spaces on command line via karate.options

On Windows systems, paths with included spaces are allowed. For our framework built on top of Karate, I would like to robustly handle such eventualities. But if there are spaces in the feature file path given to karate.options, Karate interprets the value as multiple paths, as this is by design.
So I've already tried enclosing the path with single and double quotes, as well as all possible pairs of parentheses. Unfortunately, none of these seem to work. Is there no syntax to express this intention?

Replace a sign in a property

Lets say I got this AB_1.2.3.112211 in a property
What I want is to exchange the first "." to a "_"
So it becomes AB_1_2.3.112211
The two first characters could be longer fx ABCD_1.2.3.112211 but it should still be the output ABCD_1_2.3.112211
Is there a way to do this in msbuild task?
If the input strings are always as you show them, i.e. the first "." to replace comes after an underscore followed by a number you can use a property function and use C#'s static Regex.Replace method:
<Target Name="Repl">
<PropertyGroup>
<Prop>ABCD_1.2.3.112211</Prop>
</PropertyGroup>
<Message Text="$([System.Text.RegularExpressions.Regex]::Replace( $(Prop), '_(\d*)\.', '_$1_' ) )" />
</Target>
If the use case is more complicated there are other options:
use another regular expression in the code above
MSBuild Community tasks has a Regex task which supports the Count parameter of Regex.Replace, so you can use a simple regex to replace "." with "_" and set count to one to only do the first instance
use an inline task in which you write your preferred implementation to replace the first instance from the answers here

msbuild with multiple DefineConstant values, including embedded semicolon

I have an msbuild script which uses the Exec tag to kick off another MSBuild command including a DefineConstants property with multiple values. Since I have multiple values for that property, I'm using the technique described in this question to call MSBuild.exe directly (not use the MSBuild tag) and enclose the values in quotes.
However, I now need to embed a special symbol into one of those values, which I'm attempting to do using the code ¯ (registered trademark ®)
The problem is that the special character code must end in a semicolon, but when I embedded the semicolon, msbuild reads that as a value seperator. I can seem to find a valid way to escape the semicolon and have it still show up in the end parameter value.
My question is this:
How can I embed the special char into my build parameter?
To improve readability, I've moved the value to a variable in my example, but that's not a requirement.
File: TopLevelBuildScript.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildWithSpecialChar">
<ItemGroup>
<!-- Note: %3B is the escape code for semicolon -->
<MyProductName Include="Trademarked&#174%3B Product" />
<OtherProperty Include="foo" />
</ItemGroup>
<Exec Command="msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=#(MyProductName);OtherVar=#(foo);AnotherVar=asdf;" " />
</Target>
</Project>
When executed, the above produces the command line:
msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=Trademarked® Product;OtherVar=foo;AnotherVar=asdf;"
Which ends up defining the constants with the product name split at the semicolon:
MyProductName=Trademarked&#174
Product
OtherVar=foo
AnotherVar=asdf
Note: I've also tried using %25 for the percent sign:
<MyProductName Include="Trademarked&#174%253B Product" />
But that gives me:
MyProductName=Trademarked&#174B Product
OtherVar=foo
AnotherVar=asdf
Update
It turns out the issue wasn't with MSBuild, rather with the way WiX parses parameters (my subBuildScript utilizes WiX). I didn't consider that, so didn't mention it in my original posting.
Ultimately, I went with a solution based on this answer to another question:
<PropertyGroup>
<WixValues>
<MyProductName>Trademarked® Product<MyProductName>
<OtherProperty>foo"</OtherProperty>
</WixValues>
</PropertyGroup>
<MSBuild
Projects="subProjectScript.proj"
Properties="Configuration=Release;WixValues=$([MSBuild]::Escape($(WixValues)))"
Targets="Clean;Rebuild"
ContinueOnError="false"
StopOnFirstFailure="true">
</MSBuild>
and unescaping the values in subProjectScript.proj as described in the other answer.
First, MSBuild files are XML, which you can encode as UTF-8, so you should be able to copy/paste the trademark character directly in the MSBuild script, without escaping.
If you can't take that approach, don't escape the ampersand. There are two levels of escaping things in an MSBuild script. The first is XML-encoding, so that XML-sensitive characters (< and &) can be used and you'll still have safe XML. When MSBuild reads in the file, XML-escape sequences get unescaped. After that process, MSBuild then does its own un-escaping (i.e. %3B for semi-colons).
Because you're using & at the beginning of your XMl escape sequence, the XML processor is interpreting that as a literal ampersand, not the special XML ampersand, which denotes an escape sequence. Change your MyProductName item group's value to be:
<MyProductName Include="Trademarked® Product" />
Since MyProductName appears to be a scalar value, and not a list, I would use a property instead:
<PropertyGroup>
<MyProductName>Trademarked® Product</MyProductName>
</PropertyGroup>
In your Exec task you can then use it like this:
<Exec Command="msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=$(MyProductName);OtherVar=#(foo);AnotherVar=asdf;" " />

Using CMake's include_directories command with white spaces

I am using CMake to build my project and I have the following line:
include_directories(${LLVM_INCLUDE_DIRS})
which, after evaluating LLVM_INCLUDE_DIRS, evaluates to:
include_directories(C:\Program Files\LLVM\include)
The problem is that this is being considered two include directories, "C:\Program" and "Files\LLVM\include".
Any idea how can I solve this problem? I tried using quotation marks, but it didn't work.
EDIT: It turned out that the problem is in the file llvm-3.0\share\llvm\cmake\LLVMConfig.cmake. I enclosed the following paths with quotation marks and the problem was solved:
set(LLVM_INSTALL_PREFIX C:/Program Files/LLVM)
set(LLVM_INCLUDE_DIRS ${LLVM_INSTALL_PREFIX}/include)
set(LLVM_LIBRARY_DIRS ${LLVM_INSTALL_PREFIX}/lib)
In CMake,
whitespace is a list separator (like ;),
evaluating variable names basically replaces the variable name with its content and
\ is an escape character (to get the symbol, it needs to be escaped as well)
So, in your example, include_directories(C:\\Pogram Files\\LLVM\\include) is the same as
include_directories( C:\\Program;Files\\LLVM\\include)
that is, a list with two items. To avoid this, either
escape the whitespace as well:
include_directories( C:\\Program\ Files\\LLVM\\include) or
surround the path with quotation marks:
include_directories( "C:\\Program Files\\LLVM\\include")
Obviously, the second option is the better choice as it is
simpler and easier to read and
can be used with variable evaluation like in your example (since the result of the evaluation is then surrounded by quotation marks and thus, treated a single item)
include_directories("${LLVM_INCLUDE_DIRS}")
This works as well, if LLVM_INCLUDE_DIRS is a list of multiple directories because the items in this list will then be explicitly separated by ; so that there is no need for unquoted whitespace as implicit list item separator.
Side note:
When using hard-coded path-names (for whatever reason) in my CMake files, I usually uses forward slashes as directory separators as this works on Windows as well and avoids the need to escape all backslashes.
This is more likely to be an error at the point where LLVM_INCLUDE_DIRS is set rather than a problem with include_directories.
To check this, try calling include_directories("C:\\Program Files\\LLVM\\include") - it should work correctly.
The problem seems to be that LLVM_INCLUDE_DIRS was constructed without using quotation marks. Try for example running this:
set(LLVM_INCLUDE_DIRS C:\\Program Files\\LLVM\\include)
message("${LLVM_INCLUDE_DIRS}")
set(LLVM_INCLUDE_DIRS "C:\\Program Files\\LLVM\\include")
message("${LLVM_INCLUDE_DIRS}")
The output is:
C:\Program;Files\LLVM\include
C:\Program Files\LLVM\include
Note the semi-colon in the first output line. This is a list with 2 items.
So the way to fix this is to modify the way in which LLVM_INCLUDE_DIRS is created.

How can you remove empty or blank lines from a text file using MSBuild?

I would like to remove all blank lines (lines that just have some number of spaces and a newline character) from a list of files using MSBuild.
What is the best way to accomplish this?
I recognize that I could write a MSBuild plug in C# or VB.NET that will do this using simple Regex replacement, but would prefer a solution that doesn't need me to do this.
If there's a open source MSBuild plugin that does this - I'd welcome that solution as well.
#Ludwo is right, you have to take into account white-space characters. Moreover to replace any text with empty string you need to use ReplacementTextEmpty property instead of passing empty string to ReplacementText property. So, the following target should solve the problem:
<Target Name="Minify">
<ItemGroup>
<File Include="**\*.cs" />
</ItemGroup>
<FileUpdate
Files="#(File)"
Regex="(\n\s*\n)+"
Multiline="False"
ReplacementTextEmpty="True"/>
</Target>
You just need to call the target via MSBuild:
msbuild MyProject.csproj /t:Minify