1

In one of my projects I am using a path in the System.Environment.SpecialFolder.CommonApplicationData folder (in my case C:\ProgramData) to store configuration and registration data. However I ran into problems. I check if I can access the files by using the routine

Dim isok As Boolean = True
Try
   Dim ftry As New IO.FileStream(frmMain.APPDATA & "\regid.bin", FileMode.Open)
   ftry.Close()
Catch ex As Exception
  isok = False
End Try

APPDATA is the path to my config folder and I check if the file actually exists before that as well (it does). On one machine this routine returns false for me. The exception says no file access. If I rewrite this routine:

Dim isok As Boolean = True
Try
   Dim contents() as Byte = IO.File.ReadAllBytes(frmMain.APPDATA & "\regid.bin")
Catch ex As Exception
  isok = False
End Try

It returns true, so the IO routines obviously can access the file.

Can someone explain to me what the difference between the two methods are? Shouldn't file access be determined by the application's privileges? Is there a better way to determine if I have read/write access to the file?

Jens
  • 6,275
  • 2
  • 25
  • 51
  • I wouldn't recommend opening the file to determine access rights. See this Answer: http://stackoverflow.com/a/3456514/468973 – Magnus Feb 04 '14 at 09:55
  • 1
    As as aside, don't use string concatenation to create filenames. Use the methods in the Path class, specifically, use `Path.Combine(frmMain.APPDATA, "regid.bin")` – Chris Dunaway Feb 04 '14 at 21:13
  • You're correct Chris. In this case it doesn't really make a difference since I know what's inside APPDATA at any point. But you are right that the path.combine approach is a good idea in most cases. – Jens Feb 05 '14 at 07:57

2 Answers2

4

The FileStream constructor passes off to another constructor overload.. namely this one:

internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost)

The FileAccess it passes by default is FileAccess.ReadWrite. If your application does not have write permissions.. chances are this will fail.

On the other hand, File.ReadAllBytes does this:

using (var fileStream = new FileStream(..., ..., FileAccess.Read, ...
//                                                      ^^^^ this

Notice File.ReadAllBytes uses the FileAccess.Read value.

So that's the difference. FileStream.ctor uses FileAccess.ReadWrite, File.ReadAllBytes uses FileAccess.Read.

TLDR: Your app needs write permissions to use that basic constructor for FileStream. Remember there is a File.Exists method that is meant for this exact purpose. Opening and closing a file to see if it exists is not the right way to go about it.

Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • Thank you. I will check if I have write permissions to the file and report back. – Jens Feb 04 '14 at 09:58
  • 1
    Ok, I indeed only have read access to the file on that computer. This is pretty weird in itself and I don't know why but that explains the given scenario. Thanks. – Jens Feb 04 '14 at 10:04
1

use IO.File.Exist() routine to check if the file exist. You don't need to read the file content.

Sarvesh Mishra
  • 2,014
  • 15
  • 30