views:

180

answers:

2

My thought is to use CreateFile from kernel32 and check for sharing violations. I believe this will work because I watched the file system activity with Process Monitor while issuing a rename command from CMD that I knew would fail and the last activity was a failed CreateFile call that resulted in a sharing violation.

This is the Process Monitor information on the call.

Desired Access: Read Attributes, Delete, Synchronize
Disposition: Open 
Options: Synchronous IO Non-Alert, Open Reparse Point 
Attributes: n/a 
ShareMode: Read, Write, Delete 
AllocationSize: n/a

Using this VB code, I produced a call which gave the same information in Process Monitor but did not cause the sharing violation.

CreateFile(theDirectoryPath, _
           FILE_READ_ATTRIBUTES Or DELETE Or SYNCHRONIZE, _
           FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, _
           Nothing, _
           OPEN_EXISTING, _
           FILE_ATTRIBUTE_DIRECTORY Or FILE_FLAG_BACKUP_SEMANTICS _
               Or FILE_FLAG_OPEN_REPARSE_POINT, _
           Nothing)

The constants are pulled from various MSDN and pinvoke.net sources.

If I call the above code recursively on all subfolders it will eventually cause the sharing violation, but when CMD refused to rename, it did not recurse.

Yes, I know I could just try and catch the exception. But the point at which I want to know if the directory can be renamed and the point at which I want to rename the directory are not the same.

EDIT:

There may have been a source of confusion in this question. I am not concerned with permissions; I am concerned with file locks.

+1  A: 

Untested, but this should work:

Dim fp As New FileIOPermission(FileIOPermissionAccess.Write, "C:\myfolderpath")
Try
    fp.Demand()
Catch e As SecurityException
    Console.WriteLine("I can't rename this folder.")
End Try

This will "demand" Read and Write permissions on the folder without actually renaming anything.

Edit: The above doesn't do what I thought it would, see Stephen's comment below.

If this doesn't work, perhaps attempting to rename the file with the same filename will trigger the security exception without actually doing anything destructive (though it will probably "touch" the directory).

richardtallent
As far as I can tell, this returns true (does not throw the exception) for all valid paths, including those that don't exist, the C: root and directories which cannot be renamed.
Daniel Straight
Corrected, I hope... I think the "Or" above must result in an OR search rather than an AND search, which was my intent.
richardtallent
Still returns true for all paths mentioned before. Just for kicks, I tried it with .AllAccess and it still had the same behavior.
Daniel Straight
See edit on question.
Daniel Straight
This is a very common misunderstanding - FileIOPermissionAccess only tests Code Access Security (does the assembly have sufficient trust to access that file path) not File System Security(does the current user have permission to access that file or folder.
Stephen Martin
Renaming a file to itself is quite plainly documented as causing an IOException. I'm trying to be patient, but please do at least SOME research before suggesting anything else.
Daniel Straight
Daniel, no need to get testy. I wasn't trying to avoid the IOException in my other suggestion, I was trying to give you a way to test the rename permissions before renaming the file to *something else*. Your question refers to the need to know whether a file can be renamed *before* performing the action. Renaming it to itself is one way to do so.
richardtallent
Thanks for the clarification, Stephen... that makes a lot more sense.
richardtallent
Renaming it to itself doesn't tell you anything. It just throws an IOException. That's what I was saying.
Daniel Straight
+3  A: 

Yes, I know I could just try and catch the exception. But the point at which I want to know if the directory can be renamed and the point at which I want to rename the directory are not the same.

In my opinion, this is a design problem that creates a race condition. If you check first and rename later, you will not know that the time of rename if your previous check was valid.

JP Alioto
You will if you know the single cause of all previous failures to rename and know that the user can prevent them if simply warned.
Daniel Straight
How can you ever prevent the OS from taking a file lock without locking it yourself?
JP Alioto
You can't. But you can be reasonably certain it won't happen if you know what has caused every instance of it happening in the past and know that a warning will prevent that from happening.
Daniel Straight