i have an application that create a txt file and write in it a log.
I create the txt file with the following code:
If System.IO.File.Exists(sFileName) = True Then
System.IO.File.Delete(sFileName)
End If
'System.IO.File.Create(sFileName) '.dispose
Dim objWriter As New System.IO.StreamWriter(sFileName, True)
When i finish to write the log (using objWriter.WriteLine) and close it (objwriter.close and objwriter.dispose), send it by mail and need to delete it.
In order to delete the file i use this code:
For i = 0 To 10
Try
'System.IO.File.Delete(sFileName)
'My.Computer.FileSystem.DeleteFile(sFileName, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.DeletePermanently)
My.Computer.FileSystem.DeleteFile(sFileName)
Exit For
Catch ex As Exception
If i = 10 Then
invioMailTest(ex.ToString)
End If
Threading.Thread.Sleep(1000)
End Try
Next
The code works well in local, but when i run it on the server (as administrator) it gives me the following error:
System.IO.IOException: The process cannot access the file 'C:\Log_Eventi\Export log 2016-04-13.txt' because it is being used by another process.
i don't know how to delete it and i'm losing too much time on it....
When you create your file I'm guessing you are using
System.IO.File.Create(sFileName)
You can overcome that problem by using this code:
Using File.Create(sFileName)
End Using
put all code that deals with sFileName within Using.
other solutions:
use Close when you create it
System.IO.File.Create(sFileName).Close()
use filestream
Dim fs As FileStream = File.Create(sFileName)
do your work here
fs.Close()
You mention "send it by mail", so the problem is likely that the attachment is still being held by the server's email system.
Related
I'm trying to check the version of the Windows application the user is running against the version that is on the server to see if the local version needs to be updated. I do this by calling
FileVersionInfo.GetVersionInfo("path to file on server")
and reading the version information. This works fine for what I need, however, when I look at open files on the server from the computer management console, I see many instances of my file open in Read mode. This causes a problem when I need to copy a new version to the server. I first have to close all of the open files before it will let me write to it. Even though they are only open in Read mode, it still makes me close them.
Is there a better way to get the file version from the server? Or is there a way to dispose of the FileInfo variable that I am using so it disconnects?
I have not found a good resolution using FileVersionInfo. And from my research using FileVersionInfo does not release the variable as you would expect so I changed to getting the file information from a PowerShell script. This allows me to dispose the object and release the file as I have tested successfully. So here is the code that gets the information:
Dim server_version As String = ""
Dim invoker As New RunspaceInvoke
Dim command As String = "(Get-Item path_to_file_no_quotes_needed).VersionInfo.FileVersion"
Try
Dim outputObjects As Collection(Of PSObject) = invoker.Invoke(command)
For Each result As PSObject In outputObjects
server_version = result.ToString
Next
Catch ex As Exception
End Try
invoker.dispose
When this is run from my app, I see the file get opened in Read mode on the server but it disappears after about 3 seconds. So I can see the object is being properly disposed. Just FYI, there is no FileVersionInfo.dispose method.
In addition, for this to work you need:
Imports System.Management.Automation
which needs a reference in your project. It can be found in:
C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
In the Shown event I have code that looks like this,
Try
If My.Application.IsNetworkDeployed AndAlso My.Application.Deployment.CheckForUpdate Then
'update available - the update will happen when app is closed
End If
Catch ex As Exception
'error while checking for update or update is corrupt
End Try
I do this so I can provide the user an indication that an update is available.
In the FormClosed event I do,
Try
'see if update is available, and install if it is
If My.Application.IsNetworkDeployed Then
If My.Application.Deployment.CheckForUpdate Then
My.Application.Deployment.Update()
End If
End If
Catch ex As Exception
End Try
I'm writing a windows service which runs as the local system account. I'm trying to make sure if I have full read/write access to a file beginning to process it any further. Here is my code:
Dim FullPath As String
FullPath = "C:\directory\file.txt"
Dim ps As Security.PermissionSet
ps = New Security.PermissionSet(Security.Permissions.PermissionState.Unrestricted)
ps.AddPermission(New Security.Permissions.FileIOPermission(Security.Permissions.FileIOPermissionAccess.AllAccess, FullPath))
ps.AddPermission(New Security.Permissions.FileIOPermission(Security.Permissions.FileIOPermissionAccess.AllAccess, IO.Path.GetDirectoryName(FullPath)))
Try
ps.Demand()
Catch ex As Security.SecurityException
System.Diagnostics.EventLog.WriteEntry("ShopLink", "File " + FullPath + " will not be parsed. " + ex.Message)
Exit Sub
Catch ex As Exception
System.Diagnostics.EventLog.WriteEntry("ShopLink", "File " + FullPath + " will not be parsed. " + ex.Message)
Exit Sub
End Try
Then I set the full access permissions for the file to "Deny" for the user account my service is running as. After executing, the code above doesn't throw any exceptions and allows file processing to begin. When the service later tries to change and/or delete the file, I get an "Access Denied" exception.
Any suggestions?
For this purpose i use thise small function:
Private Function HasAccess(ByVal ltFullPath As String)
Try
Using inputstreamreader As New StreamReader(ltFullPath)
inputstreamreader.Close()
End Using
Using inputStream As FileStream = File.Open(ltFullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
inputStream.Close()
Return True
End Using
Catch ex As Exception
Return False
End Try
End Function
In your case then:
If HasAccess(FullPath) ...
I have solved the problem by using My.Computer.FileSystem.DeleteFile to delete the file instead of Kill. My.Computer.FileSystem.DeleteFile was executed without problems after successfully demanding full read/write access to the file in the way described above, while Kill consistently threw an "Access denied" exception.
Using "Kill"... I know this is a very old thread but I'll add this in case anyone stumbles on it like I did. I was working on some old VB6 legacy code. One of my clients users was getting a runtime exception during a file open after a kill. The code was "Killing" the file and then rebuilding it from scratch with binary data held in memory. It tuns out that the "Kill" function triggered the user's anti-virus software which locked the file long enough to cause the next "Open" statement to fail. I discovered this using an error logging utility (the name escapes me at the moment). The line in the error log file on the failed "Open" statement was that the file's status was "Delete pending" due to the user's anti-virus software.
After some great arguments made by other users in this question: How to write to a text file inside of the application, I decided to not use a resource file, instead create a file in a folder & then read/write from there.
Although, for some reason, I can't seem to write to the file in question, it keeps throwing an exception telling me the file is already in use by another process.
Here's the code which I use for writing to this file.
If System.IO.File.Exists(credentials) Then
Dim objWriter As New System.IO.StreamWriter(credentials, False)
objWriter.WriteLine(remember)
objWriter.Close()
Else
System.IO.Directory.CreateDirectory(Mid(My.Application.Info.DirectoryPath, 1, 1) & ":\ProgramData\DayZAdminPanel")
System.IO.File.Create(credentials)
Dim objWriter As New System.IO.StreamWriter(credentials, False)
objWriter.WriteLine(remember)
objWriter.Close()
End If
Any ideas on how I can write to the text file in question?
There's a good chance that a previous iteration of your application failed to properly close access to the file in the StreamWriter. Since your constructor is set to overwrite (and not append) to the file, this could be the source.
Try setting up your application with a "Using" statement to properly open/close the file:
If System.IO.File.Exists(credentials) Then
Using objWriter As StreamWriter = New StreamWriter(credentials, False)
objWriter.WriteLine(remember)
objWriter.Close()
End Using
Else
System.IO.Directory.CreateDirectory(Mid(My.Application.Info.DirectoryPath, 1, 1) & ":\ProgramData\DayZAdminPanel")
System.IO.File.Create(credentials)
Using objWriter As StreamWriter = New StreamWriter(credentials, False)
objWriter.WriteLine(remember)
objWriter.Close()
End Using
End If
It does look rather redundant to have a Using block and a close statement, but this ensures access to your file even if an exception occurs.
You are trying to create a directory in the common application data directory. This directory should be found using the Environment class methods and enums because is different between operating systems. However you use the value credentials for the filename. I suppose that you want to store your datafile in the common application directory and not in a place where there is no permission to write data files (Like C:\program files (x86)).
Then, to avoid problems with file stream not correctly closed try to use the Using statement that assures a correct closure and disposal of your file resource (No need to call close inside a Using).
Also, notice that StreamWriter is perfectly capable to create the file if it doesn't exists or if you wish to overwrite the previous contents (passing false for the Append flag).
So your code could be reduced to these lines.
' Get the common application data directory (could be different from Win7 and XP)
Dim workDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
' Combine with your own working data directory
workDir = Path.Combine(workdir, "DayZAdminPanel")
' Create if not exists
If Not Directory.Exists(workDir) Then
Directory.CreateDirectory(workDir)
End If
' Create/Overwrite your data file in a subfolder of the common application data folder
Dim saveFile = Path.Combine(workDir, Path.GetFileName(credentials))
Using objWriter = New System.IO.StreamWriter(saveFile, False)
objWriter.WriteLine(remember)
End Using
File.Create returns an opened FileStream that you should be passing into the StreamWriter constructor on the subsequent, rather than passing the filename again, or you can just omit the File.Create call altogether.
You might want to look into a Using block for the StreamWriter so it gets predictably closed.
I'm working with text files. Actually one file, where I have to copy information to it. I'm using streamReader and streamWriter. But I'm having an error whenver I close the file and try to open it again. I can't open it again to start writing from where I stopped, and if I use the same IO writer in any other sub method, I get a run-time error message saying that file is being used. Is there any way that I can close and open the text file separately at anytime?
Dim ioFile As New StreamWriter(filename, False)
'code
iofile.close()
There is no problem in how many times I read or Write in between , but whenever I close it, can't open it.
Wrap the streamwriter in a using clause, and set AutoFlush to True:
Using ioFile As New StreamWriter(filename, True)
ioFile.AutoFlush = True
'Code
End Using
In my app i have to copy and then delete image files from memory cards, the problem comes when some of the card inadvertantly have the "Lock" switch engaged turning them to read only.
When trying to delete these files i want to log the failure to delete but not show any UI messages until a time of my choosing.
Here is some sample code i am having trouble with.
Sub Main()
Try
System.IO.File.Delete("K:\BYZTCSQ_0050.JPG")
Catch ex As Exception
'Error would be logged here
End Try
End Sub
This works fine when debuging i.e. it tries to delete the file and if not the error is caught and i can proccess it as nessecary, but when i build and run the app i get an error message telling me that the file cannot be deleted.
To test this code you will need a drive that can be physically set to read only (USB memory key, SD card) and try to delete a file on it while debuging and after a build.
Why would the same code run differently and how can i stop the excess error messages?
You can try to create a file on the memory card. For reasons only known to Microsoft (or not), creating a file on a copy-protected drive will raise the error condition in the Try block while deleting a file will not. Incidentally, I got the same odd result -- catching the delete worked fine in debug mode, but not from the .exe.
Imports System.IO
...
Try
fs = File.Create(drive & "\tmp.~tmp")
Catch ex As Exception
copyprotected = true
End Try
if not copyprotected then
file.delete(drive & "\tmp.~tmp")
file.delete(the file you wanted to in the first place)
end if
Instead of wrapping it in a try/catch block, test to see if the file exists before trying to execute the delete:
Dim strFilePath as String = "K:\BYZTCSQ_0050.JPG"
If File.Exists(strFilePath) Then
System.IO.File.Delete(strFilePath)
End If