UnauthorizedAccessException with File.AppendAllText in VB.NET - vb.net

I have recently started getting System.UnauthorizedAccessException errors when using File.AppendAllText to write to a shared drive on the network. I think there were some changes to the network when this happened. The code in my application hasn't changed.
I have asked our IT dept to grant me full permission to the folder. I can see I have permissions for Modify, Read & Execute, Read, Write under my username if I navigate to the file and look at the Security tab under properties. I am also part of a group with read, write and modify permissions to the folder.
This works without error in the same folder:
File.WriteAllText(myFile, myText)
This generates a System.UnauthorizedAccessException error when it reaches the AppendallText:
If File.Exists(myFile) = False Then
' Create a file to write to.
Dim createText As String = logTime & " " & report_data
File.WriteAllText(myFile, createText)
Else
Dim appendText As String = logTime & " " & report_data
File.AppendAllText(myFile, appendText)
End If
I have tried deleting the file and creating it again, that made no difference.
I tried File.SetAttributes(myFile, FileAttributes.Normal)
The IT dept can't see what the problem is.
I can manually open, change and modify the file. The problem only arises if I am trying to do this programmatically.
Is there a different 'user' which tries to modify files? Could the file be open somehow, or would that generate a different error?
I'm using VB.NET 2012, .net framework 4.5, Windows 8.1

The network changes were the problem. It doesn't seem possible to resolve this as it is. Instead I made a copy of the text data, append my new text to that, delete the file, and save the updated text to a new file.

Related

Problem handling errors with FileSystemWatcher

To start with it has been many years since I have done much programming, probably about 15 years, in fact VB 6 was still being taught then so I'm not up to date on anything and can get lost in what I'm reading but I am trying. I'm using Visual Studio 2019 and trying to create a VB Windows Forms App that uses the FileSystemWatcher. Unfortunately the only solutions to my problem that I could find are in C#. I tried to transfer them to my app but couldn't get them to work. Actually Visual Studio wasn't happy with what I put in and wouldn't run at all, probably due to incorrect syntax.
This part of my little app is supposed to copy a file that another program creates, while the other program is running, and place the copy in another folder. It seemed simple, detect that the file had been changed and then copy the changed file. Well I came across a few problems.
The first problem is that if I create an empty file the code works most times with no problems but occassionally 2 copies of the file are created. I could live with that but.
If I replace the empty file with a larger file, the file that it is meant to copy, then it can make 3 or 4 copies and most times produces a messagebox telling me that it can't access the file because it is in use. The main program is also minimised to display the error message, which I don't want.
Even if my app is the only program running and I replace the watched file manually with the larger file I still get the file in use error, so I am assuming that the event has been triggered twice and one of them is the process that is using the file and causing the error.
If I tell the error message to cancel then my program continues and produces only 1 copy of the file. Which is what I do want.
The second problem is that the file being copied is also accessed by another program for a short period imediately after it has been changed and this also causes an extra few copies of it to be made and sometimes a file in use error message box appears, and again the main program is minimised to display the error message. I originally had other IO.NotifyFilters in place that weren't really necassary and thought that they may have been triggering the errors so I removed them, but it made no difference.
The most common error is that the file is in use but there has also been the odd "Unhandled exception has occured in your application. could not find file.". The only reason that I can think of for this error is that the file may have been renamed to a backup file and a new version created by the main program at the exact time my program tried to access it.
From what I have read the FileSystemWatcher can trigger multiple times and I presume that this is what is causing the duplicate copies from both problems.
I need my app to make only 1 copy without the error messagebox appearing as this program needs to run in the background with no user input. Essentially this part of my app is an external program to backup a file when the file changes because the main program changes this file often but only seems to back up the file every few hours.
The following code is what I have used but nothing that I have tried has caught the error so I removed the error event handler. This code was copied from something else that was similar and in C# then modified for my purpose. I thought that the {} were used for C# not VB but it seems to work and if I take them out it won't.
My code for the FileSystemwatcher is:-
WatchFile = New System.IO.FileSystemWatcher With {
.Path = Path.GetDirectoryName(strArkMapFileNamePath),
.Filter = Path.GetFileName(strArkMapFileNamePath),
.NotifyFilter = IO.NotifyFilters.LastWrite
}
' add the handler to each event
AddHandler WatchFile.Changed, New FileSystemEventHandler(AddressOf OnLastWrite)
'Set this property to true to start watching
WatchFile.EnableRaisingEvents = True
The event handler is:-
Private Sub OnLastWrite(sender As Object, e As FileSystemEventArgs)
'Copy the Save file to a new folder and rename it.
My.Computer.FileSystem.CopyFile(
strArkMapFileNamePath,
strBackupPath & "\" & strArkMapFileName & "_" &
DateTime.Now.ToString("dd.MM.yyyy_hh.mm.ss") & ".ark",
Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs,
Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
End Sub
I added an error event handler after AddHandler WatchFile.Changed, New FileSystemEventHandler(AddressOf OnLastWrite) but that did nothing.
I tried to add an on error statement before the end sub and that did nothing either, I presume because the Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, caught the error first.
I got frustrated and tried to add a statement before the Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, but it didn't like that and I didn't expect it to work.
So how do I catch the errors before the FileSystemWatcher acts on the error?
I don't know what I am doing wrong so any help would be appreciated.
Also if anybody could offer code for what I need to do can it please be code for a Windows Forms App because I don't seem to have much luck in converting C# or anything else.
Edit
I have replaced the My.Computer.FileSystem.CopyFile with the File.Copy method as suggested and added a few extra bits..
Private Sub OnLastWrite(sender As Object, e As FileSystemEventArgs)
'Verify that source file exists
If File.Exists(strArkMapFileNamePath) Then
'Copy the Save file to a new folder and rename it.
Dim i As Integer
For i = 0 To 3
Try
' Overwrite the destination file if it already exists.
File.Copy(strArkMapFileNamePath, strBackupPath & "\" & strArkMapFileName & "_" & DateTime.Now.ToString("dd.MM.yyyy_hh.mm.ss") & ".ark", True)
i = 3
' Catch exception if the file was already copied.
Catch copyError As IOException
'If copy failed reset counter
i += 1
End Try
Next
End If
End Sub
Although this shouldn't be required because this is done before the FileSystemWatcher is enabled I have added an If statement to check that the files exists before attempting to copy the file.
I'm not entirely happy with the loop but I know under normal conditions that it's not going to be an endless loop.
Is there a way to just catch the specific errors that I would need to deal with or will it be fine the way it is?
I will probably still need to work out how to stop the FileSystemWatcher from sending more than 1 event or somehow make multiple events appear as 1.
The If statement was the last thing that I added and for some reason the program now seems to only make 1 copy and appears to be faster.
The other external program that accesses the file being copied must be slower to react than my program because now it displays a message that it's waiting until my program has finished copying the file.
My program is now performing as it was intended but I believe that it is just a matter of timing rather than the correct code.

Unable to set write permission on file

I want to create a file and give a user write permission.
IO.File.Create(Path & "\test.json")
Dim fs As Security.AccessControl.FileSecurity = IO.File.GetAccessControl(Path & "\test.json")
Dim far As Security.AccessControl.FileSystemAccessRule = New Security.AccessControl.FileSystemAccessRule("DOMAIN\USER", Security.AccessControl.FileSystemRights.WriteData, Security.AccessControl.AccessControlType.Allow)
fs.AddAccessRule(far)
When I check the Security tab for this file, I see no changes. VS2015 output window does not show any exceptions. VS2015 is running as Administrator.
I used this for reference: https://msdn.microsoft.com/en-us/library/d49cww7f(v=vs.110).aspx
All you have changed in your code is the in-memory file security. In order to apply these changes to the file, you must call SetAccessControl.
For example:
File.SetAccessControl(Path & "\test.json", fs)

DateCreated glitch? How to identify if overwriting

As part of an auto-update macro, I have a copy of an Access FrontEnd on the local drive which when opened, checks to see if the file on the server has a newer CreatedDate. If it is newer, my code currently uses fileSystemObject to CopyFile and overwrites the local drive version (filename remains the same).
The problem I am having however is that when this is done, the 'date created' does not change to that of the newer file and so continually loops as the old file is closed and the new one opened - which checks for updates based on date created... I even tried using kill on the local file and waiting 10 seconds before doing the Copyfile command but even then it appears with the deleted file's creation date.
When I get back to the office I'm going to try copying the file from the server to the local drive without renaming it, deleting the original local drive file, then copying the newly created file so I can rename it back to the original name (the name should not be changed so that any shortcuts will still work).
Has anyone come across this before and found a solution? Am I missing something obvious that would 'refresh' the created date of the file?
EDIT
I think this is pretty close to what I had.
Dim strSource As String, strDest As String, strOrigDB As String, strSvrDB As String
Dim varOldDB As Variant, varNewDB As Variant, fso As Object
Set fso = CreateObject("scripting.filesystemobject")
strSource = "\\192.168.1.2\Data\svrDatabase"
strSvrDB = "AnyOldName.mde"
strDest = "C:\myFolder\myDatabase"
strOrigDB = "KeepMyName.mde"
varOldDB = (strDest & "\" & strOrigDB)
varNewDB = (strSource & "\" & strSvrDB)
If fso.getfile(varOldDB).DateCreated < fso.getfile(varNewDB).DateCreated Then
Kill strDest & "\" & strOrigDB
Excel.Application.Wait Now() + TimeValue("00:00:05")
fso.copyfile (strSource & "\" & strSvrDB), (strDest & "\" & strOrigDB), True
'open new database version
ShellExecute 0, "Open", (strDest & "\" & strOrigDB), "", "", 1
DoCmd.Quit
End If
I was originally using date modified, but noticed that as soon as the Front end opened, this would get renewed and would therefore always be a newer date value than the server file.
EDIT
After thinking about this, and hoping my logic hasn't completely broken down, it would be best if I had a shortcut for the user to click on, but instead of opening the Frontend, it opens a script file that checks for an update. If there is an update, then it deletes the local Frontend and copies the server one (which should be named differently to the original) to the local folder - then opens the new frontend.
This would mean that the datecreated being checked is always going to be updated on copy to the local folder and the kill will work because the file has not been opened. I am still a little wary of using lastdatemodified incase a user has the database open when an update is created - the Frontend contains tables used in searches which I believe will alter the modified date of the Frontend. In this scenario the local date modified would still be greater than a new frontend on the server.
You should be using Date Modified. That's when the file was last changed.
This is what helps says about times.
Timestamps are updated at various times and for various reasons. The only guarantee about a file timestamp is that the file time is correctly reflected when the handle that makes the change is closed.
So try closing all files before comparing times.
Also From https://support.microsoft.com/en-us/kb/172190
When a name is removed from a directory (rename or delete), its short/long name pair and creation time are saved in a cache, keyed by the name that was removed. When a name is added to a directory (rename or create), the cache is searched to see if there is information to restore. The cache is effective per instance of a directory. If a directory is deleted, the cache for it is removed.
Also coping from an untrusted source will change last modified for sure.
Also there are rules for copy versus move.
Also files need to be wholey within Windows eco system for windows rules to apply for sure.

Can't Delete INI File After Calling GetPrivateProfileString

I am having trouble deleting files after calling the GetPrivateProfileString command. I have the following code:
'Read the INI File
sb = New StringBuilder(500)
Select Case FileType
Case "Scanner File"
res = GetPrivateProfileString("ScannerSetings", "ScannerType", "", sb, sb.Capacity, Filename)
Case "Scale File"
res = GetPrivateProfileString("ScaleSetings", "ScaleType", "", sb, sb.Capacity, Filename)
End Select
'If the result is a value store it, otherwise move it to unprocessed
If res <> 0 Then InputArray.Add(sb.ToString)
File.Delete(Filename)
After reading the details from the INI file, as soon as I try to delete the file, I am getting the following error: The process cannot access the file 'R:\Drop\011_11_Scanner' because it is being used by another process.
I cannot even delete these files manually until I exit my application.
Any help would be appreciated.
Thanks
I cannot even delete these files manually until I exit my application.
This clearly shows that the file that Filename points to is locked. As long as it's locked, you won't be able to delete it.
Check your code for any file handles you have opened (eg for writing purposes) and did not close.
If you don't close a file after you've opened it, the file is not released and remains in locked state… which practically means it can not be deleted until (a) you close that file-handle, or (b) you close your program, since that's what's holding the file-handle after opening.
EDIT
The next thing that comes to mind is that VB.NET may need special user access rights to remove the INI on recent Windows versions. You can quickly cross-check that by simply executing your application with elevated user rights (eg via right-click menu; run as admin). I can't imagine that that's actually the problem — but it's worth a shot. Should it indeed be the problem, check (and modify) the permissions on the folder your application and/or INI resides in.

the process cannot access the file because it is being used by another process in vb.net

help me.. i'm new in visual basic....
when i'm running the update it shows the error
The process cannot access the file 'C:\Documents and Settings\Macky\My Documents\Visual Studio 2008\Projects\Marcelo 2.2.3\Marcelo\bin\Debug\Students\MIC953867.jpg' because it is being used by another process.
my code is this
Public Sub copingfile()
If inFileName = Nothing Then
studpic.Image = Nothing
Else
outFileName = inFileName
pos = inFileName.LastIndexOf(".")
If (pos > 0) Then
outFileName = outFileName.Substring(0, pos)
End If
outFileName += ".jpg"
str = Application.StartupPath & "\Students\"
saveJPEGFile.FileName = str & StudID.Text & ".jpg" '& outFileName
fil1.Copy(inFileName, saveJPEGFile.FileName, True) 'the error shows here...
outFileName = saveJPEGFile.FileName()
End If
End Sub
I can save new student information with picture.. but when it comes in updating the picture these codes didn't work......
fil1.Copy(inFileName, saveJPEGFile.FileName, True)
You're attempting overwrite a file that's open or being used. If the file is open in a viewer/editor, then it can't be copied over. Either you opened it manually, or did so through code and it's still "attached" to something running.
If it's not open in a window, try stopping your code and deleting that file manually. If you can, it's pretty obvious something in code is still using it when you get to the line that errored. You'll need to figure out where that file is still being used (Open stream somewhere? Open in VS, itself?), as it doesn't appear to be in the code you provided.
You are going to need to show more code, you are using variables not in your code listing. Plus you do not show the code that originally saves your image.
But here is my guess...are you sure you closed the file when you saved it for the first time? You cannot generally copy to, or from, a file that is open.
(Files can be opened as shared, but I don't think you are doing that).
Post more code if you get a chance.