July 8, 2005

Stupid .NET Bugs

I've been working on automating the deployment of test builds for SiN: Episodes internally, and I've been fighting for half the afternoon with what seemed to be (at first) a network permissions error, but ended up being really funky crap happening in the System.IO namespace.

I have the approved build on my box, and I want to copy that build up to my prop server. Normally, I'd use XCOPY, but we're still in the phase where files may also be deleted from the tree, and XCOPY doesn't have any sort of "delete files on one side" functionality.

So I came up with a pretty decent little application that uses the System.IO.FileInfo.CopyTo() method to copy files over. Only catch: it only works for one copy. The moment I need to send another set of updated files over, I get craploads of UnauthorizedAccessExceptions. It seems that after I copy a file over once, I can't delete it or overwrite it again until I reboot the machine I'm copying to. (Before you ask, yes, I am passing in True for the overwrite parameter.)

I love the functionality inside the .NET Framework, but on occasion, niggling little things like this really piss me off.

In case anyone wants to check my code, here it is:
    Sub DeleteFile(ByVal filename As String)
Dim fi As New FileInfo(filename)
If fi.Exists Then fi.Delete()
End Sub

Sub EnsureFolderPathExists(ByVal filepath As String)
Dim fi As New FileInfo(filepath)
If Not fi.Directory.Exists Then _
Directory.CreateDirectory(fi.Directory.FullName)
End Sub

Sub CopyFile(ByVal sourcefile As String, ByVal destfile As String)
Dim sfi, dfi As FileInfo
Try
sfi = New FileInfo(sourcefile)
If Not sfi.Exists Then Return
EnsureFolderPathExists(destfile)
DeleteFile(destfile)
sfi.CopyTo(destfile, True)
If Not destfile.StartsWith("\\") Then
dfi = New FileInfo(destfile)
dfi.LastWriteTime = sfi.LastWriteTime
End If
Catch ex As Exception
Console.Error.WriteLine("Error: " & ex.Message)
End Try
End Sub
EnsureFolderPathExists() is there because CopyTo() will not copy a file to a path that doesn't exist, so I use the function to create the directory ahead of time. DeleteFile() is there just as a test...I was thinking for a little while that if I deleted the original, I wouldn't have these issues, but I get the UnauthorizedAccessException even with I try to delete the file.

Now mind you, it says that the UnauthorizedAccessException is only thrown on FileInfo.Delete if the file in question is really a directory...but the file that's getting the exception thrown is really a file.

Now back to tearing what's left of my hair out...

UPDATE: Turns out that the .CopyTo method also copies over the file attributes, and FileInfo.Delete() and FileInfo.CopyTo() fail with UnauthorizedAccessExceptions if the destination file is ReadOnly.

To fix it, replace the above "DeleteFile" method with the following:
    Sub DeleteFile(ByVal filename As String)
Dim fi As New FileInfo(filename)
If fi.Exists Then
If fi.Attributes Or FileAttributes.ReadOnly Then
fi.Attributes = FileAttributes.Normal
End If
fi.Delete()
End If
End Sub

Grr...

4 comments:

jfb3 said...

Looks like you need to use rsync.

Anonymous said...

Did you ever find a fix for this? I am running into the same thing.

Anonymous said...

Man, this saved my patoot. I was playing with permissions for two hours trying to get my FileInfo to overwrite files. If the error had just indicated that the file was Read Only, life would have been stellar.

Thanks.

Hank said...

In case anyone missed it like I almost did. Make sure the folder you are copying to, is NOT set to read only.