Spaces and backslashes in Visual Studio build events - c#

I have an application that is supposed to aid my project in terms of pre- and post-build event handling. I'm using ndesk.options for command line argument parsing. Which gave me weird results when my project path contains spaces. I thought this was the fault of ndesk.options but I guess my own application is to blame. I call my application as a post-built event like so:
build.exe --in="$(ProjectDir)" --out="c:\out\"
A simple foreach over args[] displays the following:
--in=c:\my project" --out=c:\out"
What happened is that the last " in each parameter was treated as if it was escaped. Thus the trailing backslash was removed. And the whole thing is treated as a single argument.
Now I thought I was being smart by simply escaping the first " as well, like so:
build.exe --in=\"$(ProjectDir)" --out=\"c:\out\"
In that case the resulting args[] look like this:
--path="c:\my
project"
--out="c:\out"
The trailing backslash in the parameters is still swallowed and the first parameter is now split up.
Passing this args[] to ndesk.options will then yield wrong results.
How should the right command line look so that the correct elements end up in the correct args[] slots? Alternatively, how is one supposed to parse command line arguments like these with or without ndesk.options? Any suggestion is welcome.
Thanks in advance

Did you try to escape the last backslash?
build.exe --in="$(ProjectDir)\" --out="c:\out\\"
This works probably only, as long as the ProjectDir ends in \, which should be given.
This is just an idea, but I did not give it a try
EDIT:
I found a comment which suggests to leave out the trailing "

I actually used "." to solve this same problem:
build.exe --in="$(ProjectDir)." --out="c:\out\."
primarily because otherwise it might look like you are trying to escape the second quote...which you're not, you're escaping the final \ (which is hidden).
I also added a REM in the postbuild command describing why I did that.

Related

Replace beginning and end of string with unique midle?

I have lots of code like below:
PlusEnvironment.EnumToBool(Row["block_friends"].ToString())
I need to convert them to something like this.
Row["block_friends"].ToString() == "1"
The value that gets passed to EnumToBool is always unique, meaning there is no guarantee that itll be passed by a row, it could be passed by a variable, or even a method that returns a string.
I've tried doing this with regex, but its sort of sketchy and doesn't work 100%.
PlusEnvironment\.EnumToBool\((.*)\)
I need to do this in Visual Studio's find and replace. I'm using VS 17.
If you had a few places where PlusEnvironment.EnumToBool() was called, I would have done the same thing that #IanMercer suggested: just replace PlusEnvironment.EnumToBool( with empty string and the fix all the syntax errors.
#IanMercer has also given you a link to super cool, advanced regex usage that will help you.
But if you are skeptical about using such a complex regex on hundreds of files, here is what I would have done:
Define my own PlusEnvironment class with EnumToBool functionality in my own namespace. And then just replace the using Plus; line with using <my own namespace>; in those hundreds of files. That way my changes will be limited to only the using... line, 1 line per file, and it will be simple find and replace, no regex needed.
(Note: I'm assuming that you don't want to use PlusEnvironment, or the complete library and hence you want to do this type of replacement.)
in Find and Replace Window:
Find:
PlusEnvironment\.EnumToBool\((.*))
Replace:
$1 == "1"
Make sure "Use Regular Expressions" is selected

Running complex command line from C#

I'm trying to run the following command line from C#:
Process.Start("C:\\Program Files\\GoToTags\\GoToTags Encoder\\GoToTags.Encoder.exe --records "{'Url':'http://petshop.intato.com/index.php?id='" + TxtBoxIDCode.Text + "'','RecordType':'Website'}"");
Obviously it is not working.
The problem is that I need to keep the proper signs such as the : in order to make it work properly.
The original command is:
C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe --records "{'Url':'http://petshop.intato.com/index.php?id=29','RecordType':'Website'}"
I have to run that command and at the same time, replace that 29 with the content of a textbox
Would anyone be able to help me with that?
The string.Format command is your friend...
string path = #"C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe";
string args = string.Format("--records \"{'Url':'http://petshop.intato.com/index.php?id={0}','RecordType':'Website'}\"", TxtBoxIDCode.Text);
Process.Start(path, args);
You have several pitfalls awaiting you.
Firstly, as you've already discovered, the backslashes in path names cause problems in the strings, as they could also indicate C# escape sequences. It's usually good practice to use C#'s #"..." syntax for file names, partly to avoid needing to double up the backslashes and make it easier to read, and partly because you could inadvertently leave a \t in there and it'd go unnoticed for ages.
Secondly, the single-parameter call to Process.Start only takes a command - it cannot accept command arguments - so you have to call the two-parameter overload.
Thirdly, the quotes around of the value of the records argument need handling so that the C# syntax knows what you want with them - i.e. to pass them to the command. I've separated out the command arguments into two parts to make that clearer. I have elected to use backslashes to escape them, though using the alternative #"...""..." would be just as good, and the choice is largely down to personal preference unless the context points you strongly one way rather than the other.
string cmd = #"C:\Program Files\GoToTags\GoToTags Encoder\GoToTags.Encoder.exe";
string url = "http://petshop.intato.com/index.php?id=" + TxtBoxIDCode.Text;
string cmdArgs = "--records \"{'Url':'" + url + "','RecordType':'Website'}\"";
Process.Start(cmd, cmdArgs);
[edited to add:]
If for some reason you find you either want or need to use string.Format to help build your cmdArgs, there's a fourth gotcha waiting in the wings for you, in that string.Format looks for the brace ({ and }) characters to delimit insertion parameter specifications, but your records command-line argument wants braces characters in the string. The way to achieve that would be to double up the braces that you want, like this:
string cmdArgs =
string.Format("--records \"{{'Url':'{0}','RecordType':'Website'}}\", url)";
In addition to the other answers, you should use the two-argument overload of Process.Start. The first argument is the executable, and the second argument is the command line arguments.
Normally, if you insist on using a single argument call, you should enclose your executable in double quotes, as such:
"\"C:\\Program Files\\GoToTags\\GoToTags Encoder\\GoToTags.Encoder.exe\" ...arguments here..."
However, this form does not work for Process.Start(string) because it specifically disallows it.

Passing filepath into Main(string[] args) not working

I am trying to pass a file path into a C# Console Application but am having problems with the string being incorrect by the time it reaches the console application.
If I run my application from the command line, with a file path parameter:
MyApp "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject\"
A windows dialogue pops up and informs me that my application has stopped working, and when I click the Debug option, I can see that the result of args[0] is:
C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject"
Note there is still a trailing quote at the end.
If I pass a second argument:
MyApp "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject\" "any old string"
I get an error again, and after viewing in debug I see that args[0] is:
C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject" any
I am baffled as to why this is happening. My only guess is that the backslashes in the string are causing some kind of escape sequence from the string? Edit: I notice that the same is happening in the string example above! It seems \" is causing problems here.
I just want to pass in the file path of the current solution directory and am calling my app from a pre-build event using $(SolutionDir), and know that I can get the path of the current solution in other ways. But this is simplest and I am curious as to why it does not work as expected.
Yes, the rules for commandline arguments are a little murky.
The \ is the escape char and you can use it to escape quotes ("). You'll have to escape a backslash but only when it is preceding a quote. So use (note the '\\' at the end):
MyApp "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject\\"
or, simpler but you'll have to deal with it in C# somehow:
MyApp "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject"
Also see this question
That's why it's always better to use / in path
"C:/Users/DevDave/Documents/Visual Studio 2012/Projects/MyProject/" "any old string"
take a look: http://en.wikipedia.org/wiki/Path_(computing) , you can use both \ and / in path but if you want any shell compatibility I suggest to use /
Anything that comes after MyApp will be the first argument (args[0]). In your case, the first argument is "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject\". Also, the quote at the end of the string seems to happen because \" means that you want to want to escape the quote and write it as a string. In this case, the quote is not closing the string. That is the reason that your args[0] is the whole thing that comes after MyApp
If you don't want to scape the quote and have a slash behind it, you should do \\"
You could try this and tell me what happens:
MyApp "C:\Users\DevDave\Documents\Visual Studio 2012\Projects\MyProject\\"
(look at the double slash)
Hope it helps.
Continuation of Henk's answer, and choose to add a \ at the end of the path, then:
If you choose to hack the bug by choosing this code in Henk's answer ("simpler but you'll have to deal with it in C# somehow:"), then you should realize some bugs that will occur:
args[0] will only be set, even if you pass multiple parameters in. The length of args will be equal to 1. So you have to split args[0] into multiple pieces for your hack.
You have to replace any " characters with a \ if they are at the end of the pieces you split.

formatting strings with backslash

I'm a newbie to c# so hopefully this one isn't too hard for a few of you.
I'm trying to build a string that has a \ in it and I am having difficulty getting just one backslash to show up even though I am adding additional escape chars or ignoring them all together. Can someone show me what I am doing wrong?
What I want my string to look like:
"10.20.14.103\sql08"
What I've tried so far:
I added an additional character to make the compiler happy but it did not escape it.
ip = string.Format("{0}\\\\{1}", ip, instancename); // output has 2 \'s
I told it to ignore escapes, it decided to ignore me instead
string temp = #"192.168.1.200\sql08"; // output has 2 \'s
Can someone help me make sense of this? (The richtext editor here seems to do a better job with it than VS2010 is doing, lol)
I'm guessing you're getting confused by the debugger.
If you hover your mouse over a local variable in VS, strings will be escaped so a single \ will display as \\.
To see what your string really is, output it somewhere for display (e.g., to the console) or hover your mouse on the variable, click on the arrow next to the little magnifying glass that appears, and select "Text Visualizer."
If you're looking at these strings in the debugger (i.e., by hovering the mouse over the variable or using a watch), the debugger adds escape characters to the display string so that it's a valid string expression. If you want to view the string verbatim in this fashion, click on the magnifying glass on the right side of the tooltip or watch entry with the string in it.
I'm guessing you're looking at the values in the debugger and seeing that they have two slashes.
That's normal. The debugger will show two slashes even though the actual string representation will only have one. Just another hump to get over when getting used to the debugger.
Be assured that when you actually use your strings, they will still only have a single slash (using either of your methods).
string requiredString = string.Format(#"{0}\\{1}",str1,str2);

C# Special Characters in String Crashing Program

I have a slight problem with a path:
"D:\\Music\\DJ Ti%C3%ABsto\\Tiesto\\Adagio For Strings (Spirit of London).mp3"
"D:\\Music\\Dj Tiësto\\Tiesto\\Adagio For Strings (Spirit of London).mp3"
Currently, when it sends that path to my Audio Library, it cannot open the path. (the reason for it crashing is trying to assign a -1 to a trackbar...but it's irrelevant).
So I'm wondering, is there anyway to prevent C# from switching special characters with %[code]? I've done a .Replace for "[" and "]", but I rather not have to look up every single special character, and add a line of code to prevent it. Is there anyway around this?
Call Uri.UnescapeDataString.
By the way, when putting paths in strings, you can put an # sign before the string to tell the compiler not to process escape codes, like this: #"D:\Music\DJ Tiësto\Tiesto\Adagio For Strings (Spirit of London).mp3". This way, you don't need to double up every backslash.

Categories