Sunday, December 27, 2020

Gotcha With Spaces In Path or Filename

I came across an interesting problem on the Forums today. The guy was having problems with files with spaces in the name. He was trying to run a Process (using the System.Diagnostics.Process class), but it wouldn't recognize the file as existing.

For example, take a look at this (my version of his problem):

string path = @"D:\Downloads\WCF Examples\WF_WCF_Samples\";
string name = "
MSDN Readmes.txt";

if (File.Exists(path + name))
{
var process = new Process();
process.StartInfo.FileName = "
Notepad++.exe";
process.StartInfo.Arguments = path + name;
process.Start();
}

The path + name is valid (and File.Exists() returns true), but when trying to Start the Notepad++ app, it can't find this file!!  It appears to be because of the spaces (but there is more to it than that, I'll explain as we go along).

The problem doesn't occur for all applications. When I tried Notepad instead of Notepad++, it worked! So, you might think, aha! it has to be a Microsoft app instead of a 3rd party app! And, you would be wrong in thinking that, because the same problem occurs with Word or Excel. Back to the drawing board!

Hmmm, maybe we should use Path.Combine() to be absolutely sure that we've got a valid file. So, let's try this:

 

process.StartInfo.Arguments = Path.Combine(path, name);

Note that in the above code, path + name is valid, but to be absolutely sure, you should always use the Path.Combine() method. For example, if your path does not have a trailing backslash (\), then path + name will give you this:  D:\MyPathMyFile.txt, but Path.Combine(path, name) correctly puts the backslash in there (but only when needed) and you will get this:  D:\MyPath\MyFile.txt

It was suggested that perhaps it's a C drive thing vs any other drive. Nope, I got the same behavior trying to Start Word with a path/name with spaces on the C drive.

So, what's going on? Turns out that to be sure it works every time, a path and filename with spaces in it should be enclosed with quotes. That will take care of it for any application!!

So, let's create a helper method and use it like this:


process.StartInfo.Arguments = AddQuotesForWhiteSpace(Path.Combine(path, name));

// And here's the helper method
public string AddQuotesForWhiteSpace(string path)
{
return !string.IsNullOrWhiteSpace(path) ?
path.Contains(" ") && !path.StartsWith("\"") && !path.EndsWith("\"") ?
"\"" + path + "\"" : path :
string.Empty;
}

For readability, you could change it to the following (it does the same thing, so it's up to you as to whether you prefer brevity or readability).

public string AddQuotesForWhiteSpace(string path)
{
if (string.IsNullOrWhiteSpace(path))
return string.Empty;

if (path.Contains(" ") && !path.StartsWith("\"") && !path.EndsWith("\""))
return "\"" + path + "\"";
else
return path;
}

Note that the above methods simply put quotes around the entire parameter that's passed to it (but only if there are any spaces in there) and then the process.Start() method is happy!

Happy Coding and Happy Holidays!

4 comments:

  1. On .Net Core/.Net 5, an easier approach would be to use ProcessStartInfo.ArgumentList.

    ReplyDelete
    Replies
    1. Thanks for the info (I'm still old school). Will that work for a filename with spaces in it if it's not enclosed in quotes?

      Delete
  2. great text
    you helped me to solve the problem ;)
    Vojislav

    ReplyDelete
    Replies
    1. Hi Vojislav ... I didn't know that you had this problem! Well, I'm glad I fixed it for you! ;0)
      Take care!

      Delete