views:

623

answers:

3

This problem occurs when I try to hide a file in my directory with a tool named File Lock. This is not a regular hide as I can not see it in windows explorer. Code:

string[] textFiles = Directory.GetFiles(@"c:\mydir")
//0 files returned

string[] textFiles = Directory.GetFiles(@"c:\mydir", "*.txt")
//1 file returned: "c:\mydir\."
File.Exists(textFiles[0])
//false

How can the second function return a "c:\mydir\." file? I can remove all files that do not exist to solve my problem but I wonder why I get a "." file in the first place.

A: 

"." refers to the current directory. Try:

Directory.Exists(textFiles[0]);

to see it in action.

Why the second overload returns he entry and the first one doesn't, I don't know.

Rytmis
+3  A: 

I don't have experience with the File Lock tool, but I can assume that it hooks FindFirstFile WinAPI function to protect some file from listing (that function is used by .NET Directory.GetFiles() function). And this hook can be written a little... buggy :)

Could you please try to disable the tool and redo your test?
Most likely you'll solve the problem.
But If you get the same result, blame Directory.GetFiles().

Rageous
It works fine without the tool. One of our testers just got it in his mind to check if everything works when he starts locking and hiding files ;)
Carra
Probably sending link to this topic to the File Lock tool support can make your tester a little happier :)
Rageous
+1  A: 

A little more investigation:

  • C:\Test\ is a normal directory
  • C:\Test\text.txt is a normal text file.
  • C:\Text\text2.txt is a text file hidden by File Lock

The following code...

using System;
using System.IO;

public static class GetFilesTest {
  public static void Main() {
    int counter = 0;
    DirectoryInfo dir = new DirectoryInfo(@"C:\Test");
    foreach (FileSystemInfo fsi in dir.GetFileSystemInfos("*.txt")) {
      Console.WriteLine("########### FileSystemInfo {0} ###########", ++counter);
      Console.WriteLine("fsi: {0}", fsi);
      Console.WriteLine("Exists: {0}", fsi.Exists);
      Console.WriteLine("FullName: {0}", fsi.FullName);
      Console.WriteLine("Name: {0}", fsi.Name);
      Console.WriteLine("Extension: {0}", fsi.Extension);
      Console.WriteLine("Attributes: {0}", fsi.Attributes);
    }

    counter = 0;
    string[] files = {@"C:\Test\test.txt", @"C:\Test\test2.txt"};
    foreach(string file in files) {
      FileSystemInfo fi = new FileInfo(file);
      Console.WriteLine("########### FileInfo {0} ###########", ++counter);
      Console.WriteLine("fi: {0}", fi);
      Console.WriteLine("Exists: {0}", fi.Exists);
      Console.WriteLine("FullName: {0}", fi.FullName);
      Console.WriteLine("Name: {0}", fi.Name);
      Console.WriteLine("Extension: {0}", fi.Extension);
      Console.WriteLine("Attributes: {0}", fi.Attributes);
      Console.WriteLine("Contents: {0}", File.ReadAllText(fi.FullName));
    }
  }
}

... outputs:

########### FileSystemInfo 1 ###########
fsi: test.txt
Exists: True
FullName: C:\Test\test.txt
Name: test.txt
Extension: .txt
Attributes: Archive
########### FileSystemInfo 2 ###########
fsi: .
Exists: False
FullName: C:\Test\.
Name: .
Extension: .
Attributes: Directory
########### FileInfo 1 ###########
fi: C:\Test\test.txt
Exists: True
FullName: C:\Test\test.txt
Name: test.txt
Extension: .txt
Attributes: Archive
Contents: test
########### FileInfo 2 ###########
fi: C:\Test\test2.txt
Exists: True
FullName: C:\Test\test2.txt
Name: test2.txt
Extension: .txt
Attributes: Archive

Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'C:\Test\test2.txt' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
   at System.IO.StreamReader..ctor(String path, Encoding encoding)
   at System.IO.File.ReadAllText(String path, Encoding encoding)
   at System.IO.File.ReadAllText(String path)
   at GetFilesTest.Main() in c:\Users\Yvonne\Temp\GetFilesTest.cs:line 29
brianpeiris
So GetFileSystemInfos("*.txt") returns a non-existing directory ".".
Carra
Clearly whatever File Lock does to the file confuses the DirectoryInfo.GetFileSystemInfos method. In normal use it would never return a directory that does not exist.
brianpeiris
Yes, Rageous is probably right that the FileLock tool hooks into the windows api used by .net.
Carra