This is my code. The input command line is var1 val1 var2 val2:
var rawCmd = Environment.CommandLine;
// Environment.CommandLine adds the .exe info that I don't want in my command line:
// rawCmd = "path\to\ProjectName.vshost.exe" var1 val1 var2 val2
// A. This correction makes it work, although it is pretty ugly:
var cleanCmd = rawCmd.Split(new string[] { ".exe\" " }, StringSplitOptions.None)[1];
// B. This alternative should be cleaner, but I can't make it work:
var exePath = System.Reflection.Assembly.GetCallingAssembly().Location;
cleanCmd = rawCmd.Replace(string.Format($"\"{exePath}\" "), "");
So to make B work, I should be able to find the .vhost.exe info (which I am not able to find).
But also I would like to know if there is a cleaner way to do all this.
As for the reason why I want to achieve this, here is the explanation (tl;dr: parsing a json from the command line): https://stackoverflow.com/a/36203572/831138
Instead of using
var rawCmd = Environment.CommandLine;
You can use:
var rawCmd = Environment.CommandLine;
var argsOnly = rawCmd.Replace("\"" + Environment.GetCommandLineArgs()[0] + "\"", "");
This will return "var1 val1 var2 val2" in your example. And it should work with the JSON example in the other post.
This only strips the command invocation part, no matter you write it as program, program.exe, .\program, c:program, "c:\Program Files\program", "\Program Files\program.exe", etc. or your path separator.
var exe = Environment.GetCommandLineArgs()[0]; // Command invocation part
var rawCmd = Environment.CommandLine; // Complete command
var argsOnly = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"').Substring(1);
It will leave double quotes, carets, and spaces between arguments untouched, even spaces at the beginning i.e., just after program name. Note there's an extra space at the beginning, don't ask me why. If that bothers you, remove first character, it should be easy. Hence the final .Substring(1). I define the two variables to make it more readable.
Edit:
Takes account of quoted invocation and the case where the program name string happens to appear as part of an argument (e.g., if your program is me.exe and you run me "Call me Ishmael", .Replace would trim the second me too). Now I also take out that extra space.
This is a very old question, but as of Windows 10 20H2 and .NET Framework 4.8, all of the above solutions appear to be broken in one way or another (eg. double-quote delimited exe paths).
I needed to remove the exe from Environment.CommandLine in a more generally robust way, so I decided to try a regex based approach. (Then I had 2 problems, lol.) Hope this helps somebody!
internal static string GetRawCommandLineArgs( )
{
// Separate the args from the exe path.. incl handling of dquote-delimited full/relative paths.
Regex fullCommandLinePattern = new Regex(#"
^ #anchor match to start of string
(?<exe> #capture the executable name; can be dquote-delimited or not
(\x22[^\x22]+\x22) #case: dquote-delimited
| #or
([^\s]+) #case: no dquotes
)
\s* #chomp zero or more whitespace chars, after <exe>
(?<args>.*) #capture the remainder of the command line
$ #match all the way to end of string
",
RegexOptions.IgnorePatternWhitespace|
RegexOptions.ExplicitCapture|
RegexOptions.CultureInvariant
);
Match m = fullCommandLinePattern.Match(Environment.CommandLine);
if (!m.Success) throw new ApplicationException("Failed to extract command line.");
// Note: will return empty-string if no args after exe name.
string commandLineArgs = m.Groups["args"].Value;
return commandLineArgs;
}
Testing done:
exe paths with/without doublequote
args containing doublequotes and also referencing the exe name
invoking exe with no args returns empty string
[Edit] Testing NOT done:
.NET 5 or any other runtime or OS
I have found a way to get the vhost path:
var exePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, System.AppDomain.CurrentDomain.FriendlyName);
...although I am afraid it could lead to inconsistencies depending on where the code is executed (Debug / production ...). I hope not, I'll have to keep testing.
If the number of spaces between elements is not important, you can just Join the argument array, which is split on unquoted space characters, and doesn't contain the executable:
void Main(string[] args)
{
var cleanCmd = string.Join(" ", args);
// etc
}
Actually, the command invocation part is always enclosed in double quotes, even if the path doesn't contain any spaces. And it is always followed by a space character, even if no command line params are specified. So this should be enough in any case:
string args = Environment.CommandLine
.Substring(Environment.GetCommandLineArgs()[0].Length + 3);
But if you're like me and want to make it 100% waterproof, you can use:
string args = Environment.CommandLine
.TrimStart('"')
.Substring(Environment.GetCommandLineArgs()[0].Length)
.TrimStart('"')
.TrimStart(' ');
Related
I am working on a project that involves having to manipulate a bat file based on certain user produced parameters. The bat files themselves are created manually, with a static format. A basic example of a bat file would be:
cd \some\predefined\bat
start run_some_script "user_generated_argument" [other pre-defined arguments]
The "user_generated_argument" bit of the bat file is manipulated in C# by the following code:
string bat_text = File.ReadAllText(bat_path);
Regex regex = new Regex("(.*?)\".*\"(.*)");
string new_argument = "A new argument";
string new_bat = regex.Replace(bat_text , "$1\"" + new_argument + "\"$2", 1);
And that would produce the following:
cd \some\predefined\bat
start run_some_script "A new argument" [other pre-defined arguments]
which is the expected output.
However, the problem lies when one of the other pre-defined arguments after the first quoted argument is also in quotes when that is the case, it seems that the second quoted argument disappears. For example, if the bat file looks like:
cd \some\predefined\bat
start run_some_script "user_generated_argument" "a_predefined_quoted_argument" [other pre-defined arguments]
Running the same C# code from above would produce the following:
cd \some\predefined\bat
start run_some_script "A new argument" [other pre-defined arguments]
The "a_predefined_quoted_argument" would no longer be in the string.
I may be doing this completely wrong. How would I make the predefined quoted argument not disappear?
the problem is that your expression
\".*\"
is eager or greedy, taking everything between the first quote and the last quote it finds. To make it lazy or reluctant, put a ? after the *
like so (I used VB, which escapes double quotes by double double quotes)
Dim batfile As String = "cd \some\predefined\bat" & vbCrLf & "start run_some_script ""user_generated_argument"" ""a_predefined_quoted_argument"" [other pre-defined arguments]"
Dim regex As Regex = New Regex("(.*?)"".*?""(.*)")
Dim new_argument As String = "A new argument"
Dim new_bat As String = regex.Replace(batfile, "$1""" + new_argument + """ $2", 1)
It will now take everything between the first quote, and the next quote.
Instead of using Regex you could also read the lines with File.ReadAllLines(), take the desired line and split it with string.Split() and replace them in that way.
Something like:
string[] lines = File.ReadAllLines(fileName);
string commandLine = lines.Where(d => d.StartsWith("start")).Single();
string[] arguments = commandLine.Split(' ');
foreach (var argument in arguments)
{
if (argument.StartsWith("\""))
{
// do your stuff and reassemble
}
}
I have a text file that contain only the FULL version number of an application that I need to extract and then parse it into separate Variables.
For example lets say the version.cs contains 19.1.354.6
Code I'm using does not seem to be working:
char[] delimiter = { '.' };
string currentVersion = System.IO.File.ReadAllText(#"C:\Applicaion\version.cs");
string[] partsVersion;
partsVersion = currentVersion.Split(delimiter);
string majorVersion = partsVersion[0];
string minorVersion = partsVersion[1];
string buildVersion = partsVersion[2];
string revisVersion = partsVersion[3];
Altough your problem is with the file, most likely it contains other text than a version, why dont you use Version class which is absolutely for this kind of tasks.
var version = new Version("19.1.354.6");
var major = version.Major; // etc..
What you have works fine with the correct input, so I would suggest making sure there is nothing else in the file you're reading.
In the future, please provide error information, since we can't usually tell exactly what you expect to happen, only what we know should happen.
In light of that, I would also suggest looking into using Regex for parsing in the future. In my opinion, it provides a much more flexible solution for your needs. Here's an example of regex to use:
var regex = new Regex(#"([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9])");
var match = regex.Match("19.1.354.6");
if (match.Success)
{
Console.WriteLine("Match[1]: "+match.Groups[1].Value);
Console.WriteLine("Match[2]: "+match.Groups[2].Value);
Console.WriteLine("Match[3]: "+match.Groups[3].Value);
Console.WriteLine("Match[4]: "+match.Groups[4].Value);
}
else
{
Console.WriteLine("No match found");
}
which outputs the following:
// Match[1]: 19
// Match[2]: 1
// Match[3]: 354
// Match[4]: 6
C# 6 brings compiler support for interpolated string literals with syntax:
var person = new { Name = "Bob" };
string s = $"Hello, {person.Name}.";
This is great for short strings, but if you want to produce a longer string must it be specified on a single line?
With other kinds of strings you can:
var multi1 = string.Format(#"Height: {0}
Width: {1}
Background: {2}",
height,
width,
background);
Or:
var multi2 = string.Format(
"Height: {1}{0}" +
"Width: {2}{0}" +
"Background: {3}",
Environment.NewLine,
height,
width,
background);
I can't find a way to achieve this with string interpolation without having it all one one line:
var multi3 = $"Height: {height}{Environment.NewLine}Width: {width}{Environment.NewLine}Background: {background}";
I realise that in this case you could use \r\n in place of Environment.NewLine (less portable), or pull it out to a local, but there will be cases where you can't reduce it below one line without losing semantic strength.
Is it simply the case that string interpolation should not be used for long strings?
Should we just string using StringBuilder for longer strings?
var multi4 = new StringBuilder()
.AppendFormat("Width: {0}", width).AppendLine()
.AppendFormat("Height: {0}", height).AppendLine()
.AppendFormat("Background: {0}", background).AppendLine()
.ToString();
Or is there something more elegant?
You can combine $ and # together to get a multiline interpolated string literal:
string s =
$#"Height: {height}
Width: {width}
Background: {background}";
Source: Long string interpolation lines in C#6 (Thanks to #Ric for finding the thread!)
I'd probably use a combination
var builder = new StringBuilder()
.AppendLine($"Width: {width}")
.AppendLine($"Height: {height}")
.AppendLine($"Background: {background}");
Personally, I just add another interpolated string using string concatenation
For example
var multi = $"Height : {height}{Environment.NewLine}" +
$"Width : {width}{Environment.NewLine}" +
$"Background : {background}";
I find that is easier to format and read.
This will have additional overhead compared to using $#" " but only in the most performance critical applications will this be noticeable. In memory string operations are extremely cheap compared to data I/O. Reading a single variable from the db will take hundreds of times longer in most cases.
Since C# 11 you can do it like this (file multiline.cs):
using System;
public class Program
{
public static void Main()
{
var multiLineStr =
$$"""
{
"Color" : "Blue",
"Thickness" : {{1 + 1}}
}
""";
Console.WriteLine(multiLineStr);
}
}
Now the string variable multiLineStr contains:
{
"Color" : "Blue",
"Thickness" : 2
}
Explanation:
The string is now delimited by """, and interpolation is delimited by {{ and }} because there were two consecutive $ specified (you can add more $ or " if needed, but for the quotes you must use the same number for opening and closing it).
The indentation of the lines where you define the starting and ending quotes matters! If you indented it with different amount of tabs and/or spaces, the compiler might complain.
If required, you can have more than 3 quotes, e.g. """"". Please note that the number of opening and closing quotes must match (in this case, 5 opening and 5 closing double quotes are required to enclose a string).
With this new syntax, the # prefix is not needed because you don't need to escape double quotes inside of the string any more
This simplifies declaring multi-line strings a lot.
You can find a full documentation here # Microsoft.
Note: You can try it out in LinqPad 7 (in Preferences -> Query tab, make sure that "Enable C#/F# preview features" is enabled), in Visual Studio or on the command line. DotNetFiddle does not support the new syntax (yet).
To try it out on the command line, use the batch file CompileCS you can find in the link and invoke it like: compilecs /run multiline.cs (provided you have installed a recent version of Roslyn).
I have a .Net application that take a bunch of command line arguments, process some of it, and use the rest as arguments for another application
E.g.
MyApp.exe foo1 App2.exe arg1 arg2 ...
MyApp.exe is my application,
foo1 is a parameter that my application care. App2.exe is another application, and my application will run App2 with arg1 arg2, etc. as arguments.
Currently my application just run App2.exe using something like this
Process.Start(args[1], String.Join(" ", args.Skip(2)). So the command above will correctly run: App2.exe with arguments "arg1 arg2". However, consider something like this
MyApp.exe foo1 notepad.exe "C:\Program Files\readme.txt"
The code above will not be aware of the quotes, and will run notepad.exe with arguments C:\Program Files\readme.txt (without quotes).
How can I fix this problem?
Environment.CommandLine
will give you the exact command line - you'll have to parse out the path to your app but otherwise works like a charm - #idle_mind alluded to this earlier (kind of)
Edited to move example into answer (because people are obviously still looking for this answer). Note that when debuging vshost messes up the command line a little.
#if DEBUG
int bodgeLen = "\"vshost.\"".Length;
#else
int bodgeLen = "\"\"".Length;
#endif
string a = Environment.CommandLine.Substring(Assembly.GetExecutingAssembly().Location.Length+bodgeLen).Trim();
You will need to modify MyApp to enclose any arguments with quotes.
Short story, the new code should be this:
var argsToPass = args.Skip(2).Select(o => "\"" + o.Replace("\"", "\\\"") + "\"");
Process.Start(args[1], String.Join(" ", argsToPass);
The logic is this:
each argument should be enclosed with quotes, so if you are calling with :
MyApp.exe foo1 notepad.exe "C:\Program Files\readme.txt"
The app will get called this way:
notepad.exe "C:\Program Files\readme.txt"
each argument should escape the quotes (if any), so if you are calling with:
MyApp.exe foo1 notepad.exe "C:\Program Files\Some Path with \"Quote\" here\readme.txt"
The app will get called this way:
notepad.exe "C:\Program Files\Some Path with \"Quote\" here\readme.txt"
Use Environment.GetCommandLine() as it will keep the parameter in quotes together as one argument.
Well, the simple answer is to just wrap every argument in quotes when calling MyApp2.exe.
It doesn't hurt to wrap arguments that are one word, and it will fix the case that it has spaces in the argument.
The only thing that might go wrong is if the argument has an escaped quote in it already.
You can use backslashes for escape quotes. below will work
MyApp.exe foo1 notepad.exe \"C:\Program Files\readme.txt\"
Above will be the best solution if you are don't have idea about which other exes going to run and what are the arguments they expecting. In that case you can't add quotes from your program.
give instructions to add backslashes when there is quotes when running your application
Credit to #mp3ferret for having the right idea. But there was no example of a solution using Environment.CommandLine, so I went ahead and created a OriginalCommandLine class that will get the Command Line arguments as originally entered.
An argument is defined in the tokenizer regex as being a double quoted string of any type of character, or an unquoted string of non-whitespace characters. Within the quoted strings, the quote character can be escaped by a backslash. However a trailing backslash followed by a double quote and then white space will not be escaped.
There reason I chose the exception of the escape due to whitespace was to accommodate quoted paths that end with a backslash. I believe it is far less likely that you'll encounter a situation where you'd actually want the escaped double quote.
Code
static public class OriginalCommandLine
{
static Regex tokenizer = new Regex(#"""(?:\\""(?!\s)|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(#"\\("")(?!\s|$)");
static Regex unquoter = new Regex(#"^\s*""|""\s*$");
static Regex quoteTester = new Regex(#"^\s*""(?:\\""|[^""])*""\s*$");
static public string[] Parse(string commandLine = null)
{
return tokenizer.Matches(commandLine ?? Environment.CommandLine).Cast<Match>()
.Skip(1).Select(m => unescaper.Replace(m.Value, #"""")).ToArray();
}
static public string UnQuote(string text)
{
return (IsQuoted(text)) ? unquoter.Replace(text, "") : text;
}
static public bool IsQuoted(string text)
{
return text != null && quoteTester.Match(text).Success;
}
}
Results
As you can see from the results below the above method fixes maintains the quotes, while more gracefully handling a realistic scenario you might encounter.
Test:
ConsoleApp1.exe foo1 notepad.exe "C:\Progra\"m Files\MyDocuments\" "C:\Program Files\bar.txt"
args[]:
[0]: foo1
[1]: notepad.exe
[2]: C:\Progra"m Files\MyDocuments" C:\Program
[3]: Files\bar.txt
CommandLine.Parse():
[0]: foo1
[1]: notepad.exe
[2]: "C:\Progra"m Files\MyDocuments\"
[3]: "C:\Program Files\bar.txt"
Finally
I debated using an alternative scheme for escaping double quotes. I feel that using "" is better given that command lines so often deal with backslashes. I kept the backslash escaping method because it is backwards compatible with how command line arguments are normally processed.
If you want to use that scheme make the following changes to the regexes:
static Regex tokenizer = new Regex(#"""(?:""""|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(#"""""");
static Regex unquoter = new Regex(#"^\s*""|""\s*$");
static Regex quoteTester = new Regex(#"^\s*""(?:""""|[^""])*""\s*$");
If you want to get closer to what you expect from args but with the quotes intact, change the two regexes. There is still a minor difference, "abc"d will return abcd from args but [0] = "abc", [1] = d from my solution.
static Regex tokenizer = new Regex(#"""(?:\\""|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(#"\\("")");
If you really, really want to get the same number of elements as args, use the following:
static Regex tokenizer = new Regex(#"(?:[^\s""]*""(?:\\""|[^""])*"")+|[^\s]+");
static Regex unescaper = new Regex(#"\\("")");
Result of exact match
Test: "zzz"zz"Zzz" asdasd zz"zzz" "zzz"
args OriginalCommandLine
------------- -------------------
[0]: zzzzzZzz [0]: "zzz"zz"Zzz"
[1]: asdasd [1]: asdasd
[2]: zzzzz [2]: zz"zzz"
[3]: zzz [3]: "zzz"
Try the following.
This code preserved the double quotes characters as well as giving the option to escape the \ and " characters (see comments in the code below).
static void Main(string[] args)
{
// This project should be compiled with "unsafe" flag!
Console.WriteLine(GetRawCommandLine());
var prms = GetRawArguments();
foreach (var prm in prms)
{
Console.WriteLine(prm);
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern System.IntPtr GetCommandLine();
public static string GetRawCommandLine()
{
// Win32 API
string s = Marshal.PtrToStringAuto(GetCommandLine());
// or better, managed code as suggested by #mp3ferret
// string s = Environment.CommandLine;
return s.Substring(s.IndexOf('"', 1) + 1).Trim();
}
public static string[] GetRawArguments()
{
string cmdline = GetRawCommandLine();
// Now let's split the arguments.
// Lets assume the fllowing possible escape sequence:
// \" = "
// \\ = \
// \ with any other character will be treated as \
//
// You may choose other rules and implement them!
var args = new ArrayList();
bool inQuote = false;
int pos = 0;
StringBuilder currArg = new StringBuilder();
while (pos < cmdline.Length)
{
char currChar = cmdline[pos];
if (currChar == '"')
{
currArg.Append(currChar);
inQuote = !inQuote;
}
else if (currChar == '\\')
{
char nextChar = pos < cmdline.Length - 1 ? cmdline[pos + 1] : '\0';
if (nextChar == '\\' || nextChar == '"')
{
currArg.Append(nextChar);
pos += 2;
continue;
}
else
{
currArg.Append(currChar);
}
}
else if (inQuote || !char.IsWhiteSpace(currChar))
{
currArg.Append(currChar);
}
if (!inQuote && char.IsWhiteSpace(currChar) && currArg.Length > 0)
{
args.Add(currArg.ToString());
currArg.Clear();
}
pos++;
}
if (currArg.Length > 0)
{
args.Add(currArg.ToString());
currArg.Clear();
}
return (string[])args.ToArray(typeof(string));
}
Try with "\"". I have to pass as arguments url too, this is the way:
_filenameDestin and _zip are urls. I hope it helps.
string ph = "\"";
var psi = new ProcessStartInfo();
psi.Arguments = "a -r " + ph + _filenameDestin + ".zip " + ph + _filenameDestin + ph;
psi.FileName = _zip;
var p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();
One solution might be to try using Command Line Parser, a free 3rd-party tool, to set up your application to take specific flags.
For example, you could define the accepted options as follows:
internal sealed class Options
{
[Option('a', "mainArguments", Required=true, HelpText="The arguments for the main application")]
public String MainArguments { get; set; }
[Option('t', "targetApplication", Required = true, HelpText = "The second application to run.")]
public String TargetApplication { get; set; }
[Option('p', "targetParameters", Required = true, HelpText = "The arguments to pass to the target application.")]
public String targetParameters { get; set; }
[ParserState]
public IParserState LastParserState { get; set; }
[HelpOption]
public string GetUsage()
{
return HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current));
}
}
Which can then be used in your Program.cs as follows:
static void Main(string[] args)
{
Options options = new Options();
var parser = new CommandLine.Parser();
if (parser.ParseArgumentsStrict(args, options, () => Environment.Exit(-2)))
{
Run(options);
}
}
private static void Run(Options options)
{
String mainArguments = options.MainArguments;
// Do whatever you want with your main arguments.
String quotedTargetParameters = String.Format("\"{0}\"", options.TargetParameters);
Process targetProcess = Process.Start(options.TargetApplication, quotedTargetParameters);
}
You would then call it on the command line like this:
myApp -a mainArgs -t targetApp -p "target app parameters"
This takes all the guesswork out of trying to figure out what's an argument for which app while also allowing your user to specify them in whatever order they want. And if you decide to add in another argument down the road, you can easily do so without breaking everything.
EDIT: Updated Run method to include ability to add quotes around the target parameters.
I have a regex expression that I'm trying to construct that processes a file path and tries to find a file path whose directory ends with "Processed" or "Failed".
I have something like this...
static string PROCESSED_DIRECTORY = "Processed";
static string FAILURE_DIRECTORY = "Failed";
...
if (Regex.IsMatch(FileFullPath, String.Format(#"(.*)\\({0})|({1})$", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)))....
This works fine.
However, I created an additional Regex expression because I am also trying to match the occurance of a file that is located in the Processed or Failed directory. The regex is not matching and I believe it has something to do with the pipe symbol. It matches when I check for either 'Failed' or 'Processed' without the pipe symbol.
For example: The following files don't match
- C:\ftp\business\Processed\file.txt
- C:\ftp|business\Failed\file.txt
I would expect them to match.
if (Regex.IsMatch(FileFullPath, String.Format(#"(.*)\\({0}|{1})\\(.*)", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)))
If I somehow could combine the two Regex queries into one to say "Match a path that ends with Failed' or 'Processed' and also match a file that exists in the 'Failed' or 'Processed' directory", that'd be amazing. Right now though, I'm content with having two separate regex calls and getting the second to work.
Works ok for me... Ran this in LINQPad:
string PROCESSED_DIRECTORY = "Processed";
string FAILURE_DIRECTORY = "Failed";
string FileFullPath = #"C:\ftp\business\Processed\moof\file.txt";
Regex.IsMatch(FileFullPath, String.Format(#"(.*)\\({0}|{1})\\(.*)", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)).Dump();
FileFullPath = #"C:\ftp|business\Failed\file.txt";
Regex.IsMatch(FileFullPath, String.Format(#"(.*)\\({0}|{1})\\(.*)", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)).Dump();
Here's a version that will look for either containing the processed/failed strings OR ending in \Processed|Failed\filename.ext:
string PROCESSED_DIRECTORY = "ProcessedPath";
string FAILURE_DIRECTORY = "FailedPath";
string FileFullPath = #"C:\ftp\business\ProcessedPath\moof\file.txt";
Regex.IsMatch(FileFullPath, String.Format(#"((.*)\\({0}|{1})\\(.*))|(.*\\(Processed|Failed)\\(?!.*\\.*))", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)).Dump();
FileFullPath = #"C:\ftp\business\NotTheProcessedPath\moof\Processed\file.txt";
Regex.IsMatch(FileFullPath, String.Format(#"((.*)\\({0}|{1})\\(.*))|(.*\\(Processed|Failed)\\(?!.*\\.*))", PROCESSED_DIRECTORY, FAILURE_DIRECTORY)).Dump();
There are quite a few ways to do this (progressively more complicated and more correct), but the simplest is probably this:
var targetStrings = new[] { PROCESSED_DIRECTORY, FAILURE_DIRECTORY }; //needles
string FileFullPath = #"C:\ftp\business\Processed\moof\file.txt"; //haystack
if (FileFullPath.Split('\\').Any(str => targetStrings.Contains(str)))
{
//...
No regex required. Regex seems overkill and possibly error-prone for this anyway.
System.IO.Path may be relevant to whatever you're doing here; it's what the Path class was made for.