-1

I'm trying to programmaticaly locate a file on a network server where there are multiple directory levels, one of which has two spaces at the end of the name. EG:

\\MyServer\C$\TopLevel\Account \someone@somewhere.com\AFileName.pdf

Note that the Account level represents many folders using account codes for the folder name, and most of them have the two spaces at the end.

I can't amend the directory structure as it's used by other processes outside my control. I will know in advance the path down to and including the Account level, so I need to search the Email level subfolders for a file containing an order number in the file name. I also know the order number.

The problem is that FileInfo, Directory and DirectoryInfo all balk at the two spaces. Whilst Windows has allowed the folders to be created, and an automated third party process can create folders and files below the Account level, nothing I have tried so far has worked because the spaces get stripped out by the c# file and directory classes.

I can't use:

Directory.GetFiles(PathToTopLevel, "*.pdf")

because there are over 1000 Account level folders, each of which might have 5 or 6 Email level folders with possibly many hundreds of pdf files in each one. I did try it but had to kill it when it was still thinking about it after 5 minutes.

Directory.GetFiles(PathToAccountLevel, "*.pdf")  

This returns the 'can't find part of the path' error.

I also tried:

filePath = Path.Combine(PathToAccountLevel, $"{order_no}.pdf");  
var fi = new FileInfo(filePath);

which also returns 'can't find part of the path'.

I've done lots of trawling through SO and other forums with no success as they are mainly concerned either with file names or single spaces, but I did find a useful method here which I have tried:

filePath = AddQuotesIfRequired(PathToAccountLevel);  
Directory.GetFiles(filePath, "*.pdf")

Which does indeed add the quotes, but it makes no difference to the outcome.

Also tried (with and without adding quotes):

Directory.GetFiles(@filePath, "*.pdf")  

I've tried as many combinations as I can think of using quotes and '@' etc. but absolutely nothing has worked so far. I've even hard coded the full path down to the Email level and still no joy.

I'm using C# with VS2019 on Windows 10. The server is running Windows Server 2012 R2 DataCenter. I've run the test executable locally on the server and the results are the same.

The really galling aspect of this is that a simple test program written in and using FindFirst/Next works perfectly!

I should also mention that permissions are not an issue, and the files exist.

Any help at all would be great, thanks.

Re the possible duplicate/proposed answer from qaabaam:

Answer 1 for that question is not valid code - the line

DirectoryInfo wantedDir = tempWithoutMac.GetDirectories.Where(c => c.Contains(MacID)).First();

throws an error for GetDirectories being a method and not valid in the context. If you change it to GetDirectories() it then complains that DirectoryInfo does not have a definition for Contains.

Answer 2 using alt 0160 still throws the can't find part of the path error.

Answer 3 is basically an opinion and doesn't help at all.

If you can figure out how to get Answer 1 to work I'll definitely give it a try!

Mick
  • 141
  • 9
  • Use Trim() at end of string to remove the spaces. – jdweng Apr 13 '21 at 16:39
  • Does this answer your question? [Directory.GetFiles() throws exception - Folder name has spaces at the end not recognized](https://stackoverflow.com/questions/28888525/directory-getfiles-throws-exception-folder-name-has-spaces-at-the-end-not-re) – quaabaam Apr 13 '21 at 21:24
  • @jdweng My problem arises because the spaces are stripped by Directory/FileInfo, so trimming them out prior to searching doesn't help. – Mick Apr 14 '21 at 07:05
  • @qaabaam Answer 1 of the post you proposed is not valid code - the line 'DirectoryInfo wantedDir = tempWithoutMac.GetDirectories.Where(c => c.Contains(MacID)).First();' throws an error for GetDirectories being a method and not valid in the context. If you change it to GetDirectories() it then complains that DirectoryInfo does not have a definition for Contains. Answer 2 using alt 0160 still throws the can't find part of the path error. Answer 3 is basically an opinion and doesn't help at all. If you can figure out how to get Answer 1 to work I'll give it a try. – Mick Apr 14 '21 at 08:23
  • You have an unicode issue. Check by using GetInvalidCharacter(). See : https://social.msdn.microsoft.com/Forums/vstudio/en-US/ff695a41-1fd5-45d8-9f1e-318c28166724/unicode-and-file-operations?forum=netfxbcl&force_isolation=true – jdweng Apr 14 '21 at 09:37

1 Answers1

0

Leading or trailing spaces in directory names is one of those grey areas in Windows: you can do it, but you probably shouldn't. The reason for this is simple - the vast majority of the time, a leading or trailing space is a typo, and the Windows APIs around paths have been designed to take this into account, to the point where (as you've discovered) they will outright ignore leading or trailing spaces. (For example, in Windows 10, it's literally impossible to delete a directory with trailing spaces via Windows Explorer!) Since C# is built on top of these APIs, it inherits their "quirks".

Fortunately there is a way to tell Windows "don't try to fix this path, it is correct, I know what I'm doing" via the use of DOS device paths. In brief:

  • For local paths, prefix them with the literal \\?\. In other words, C:\foo\bar would become \\?\C:\foo\bar.
  • For UNC paths, replace the leading \\ with \\?\UNC\. In other words, \\server\foo\bar would become \\?\UNC\server\foo\bar.

In your case, then, all you need to do is change \\MyServer\C$\TopLevel\Account \ to \\?\UNC\MyServer\C$\TopLevel\Account \ and everything should work as you expect.


As an aside, what you are doing is a document search/query operation, which will be incredibly slow as it's performing I/O, and over the network at that. You'd be far better served in writing a tool to migrate these documents into a proper database, then searching that database for the documents.

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
  • You are the proverbial life saver! I had to use '\\.\UNC\' rather than '\\?\UNC\' and pre-build the full path to the file (which I've now realised I can do) but it definitely works where all else has failed. Thanks! – Mick Apr 14 '21 at 10:18