IO.File.Delete Random UnauthorizedAccessException - vb.net

I'm using My.Computer.Filesystem.WriteAllBytes to write out an executable stored in my application's resources to it's startup directory. After running the executable, I then delete it. Everything works fine; however, I'll randomly get an UnauthorizedAccessException for no reason. After getting the exception, I can manually delete the file with no problem. Here's the full code:
' Convert MP3
' First, copy out converter
Dim Path = New IO.FileInfo(SoundPath)
Try
My.Computer.FileSystem.WriteAllBytes(Application.StartupPath + "\converter.exe", My.Resources.madplay, False)
Catch ex As Exception
MessageBox.Show(ex.ToString, "Report", MessageBoxButtons.OK)
Exit Sub
End Try
' Set up process
Dim MAD As New Process
' Set process info
Dim output As String = IO.Path.GetFileNameWithoutExtension(Path.FullName) + ".wav"
Dim input As String = Path.FullName
Dim adjust As String = barVolumeAdjust.Value.ToString
Dim hz As String = "15000"
With (MAD.StartInfo)
.FileName = Application.StartupPath + "\converter.exe"
.Arguments = "-v -a " + adjust + " -R " + hz + " -o """ + output + """ """ + input + """"
.UseShellExecute = False
.RedirectStandardInput = True
.RedirectStandardError = True
.RedirectStandardOutput = True
.CreateNoWindow = True
End With
' Start
MAD.Start()
' Update title with output
Dim Line As String = MAD.StandardError.ReadLine
While Not Line Is Nothing
Me.Text = Line
Line = MAD.StandardError.ReadLine
End While
' Stop
MAD.Close()
' Delete MAD
Try
IO.File.Delete(Application.StartupPath + "\converter.exe")
Catch ex As Exception
MessageBox.Show(ex.ToString, "Report", MessageBoxButtons.OK)
End Try
What perplexes me is that I literally just wrote out the executable, and nothing else could possibly be using it. I've checked the file attributes and it's not read-only. My application is also running as an administrator. What could be the problem?

You do not wait for the process to exit, so it is still running when you attempt to delete the file. See Process.WaitForExit

It looks like your using a separate process to write out the file - perhaps this is still using the file when you try to delete.
I suggest catching and handling the exception to get around the problem.

Related

vb.net cannot find file after file has been deleted and resaved by remote pc

I'm using a web page to create a file on a web server to control an Arduino device. The file gets created without issue. The problem exists when the VB app that controls the Arduino device reads the file and then deletes the file. After VB deletes the file the web app recreates the same file with new data. The VB app fails to see the new file. It still thinks the file has been deleted.
Here's the code:
Private Sub TimerCheck4CameraFile_Tick(sender As Object, e As EventArgs) Handles TimerCheck4CameraFile.Tick
Try
' Check if file exists if it doesn't leave this method.
Dim DirectoryList As New IO.DirectoryInfo("C:\inetpub\wwwroot")
Dim ArrayOfFilesFileInfo As IO.FileInfo() = DirectoryList.GetFiles("ServoDirection2Move.txt")
Dim Fi As IO.FileInfo
For Each Fi In ArrayOfFilesFileInfo
If String.Compare("ServoDirection2Move.txt", Fi.Name) <> 0 Then
TextBox1.Text += vbCrLf + "Did NOT Find File."
Exit Sub ' We DID NOT find the file so get out!
End If
Next
Catch ex As Exception
LabelStatus.Text = "Catch ex 1: " + ex.Message
End Try
' Read in the file.
Dim FileRead As String
Try
' **POSSIBLE ISSUE HERE**.
FileRead = My.Computer.FileSystem.ReadAllText("C:\inetpub\wwwroot\ServoDirection2Move.txt")
' Need better way to read txt file. It fails after file is deleted and can not read second file.
TextBox1.Text += vbCrLf + "Moving Value: " + FileRead
Catch ex As Exception
LabelStatus.Text = "Catch ex: " + ex.Message
End Try
' Check if it was UP.
If String.Compare("UP", FileRead) = 0 Then
' Delete the file to prepare for a new one.
System.IO.File.Delete("C:\inetpub\wwwroot\ServoDirection2Move.txt")
' Move servo to proper location.
Call PanningUp.PerformClick()
LabelStatus.Text = "Done Moving: UP" ' Update Status Bar.
TimerCheck4CameraFile.Enabled = True ' Turn timer back on.
Exit Sub
End If

Delete a file in use by another process in vb.net / framework 2.0

I have a program that watches if there is a file with a certain name, in a certain directory.
the FileStream is created with the sequent command:
fs = File.Open(PathK, FileMode.Append, FileAccess.Write, FileShare.None)
After half an hour, the program closes, disposes and kills the text file and then shuts down itself, calling for another program to create another process of itself and closes the old one.
Sometimes this doesn't happen though. The file can't be removed and it causes an error.
After that the program closes itself and continues with its restart routine. but when it starts itself, it checks if there is that specific file, and there it is, because it couldn't kill it. Now, i can do File.OpenRead on that file, so the old filestream of the old process is not running, so it means the old one process is shut down. But I still can't kill it!
this is the starting code:
Private Sub Verifica_PID_Aperti()
Dim Tentativi As Integer = 0
PidAlreadyOpen = 0
'file exist ?
If File.Exists(PathK) = True Then
Try
'can i read it?
File.OpenRead(PathK)
Catch ex As Exception
'if it's locked than there is another PID active right now, stop this process
Settaggi.lStop = 1
PidAlreadyOpen = 1
Exit Sub
End Try
'not locked? than it's a bug and the file is still open, try to delete
While (Tentativi < 1000)
Try
File.Delete(PathK)
Tentativi = 1000
Catch ex As Exception
Tentativi = Tentativi + 1
End Try
End While
'is him still alive?
If File.Exists(PathK) Then
'if yes, there is an error, sand a mail and close yourself
Dim pf As New Send_Mail
pf.Invio_Mail_Automatico_EDP(999, "ERRORECHIUSURA", Err.Description & " - " & PathK, "", Settaggi.lPID)
pf = Nothing
Settaggi.lStop = 1
PidAlreadyOpen = 1
Exit Sub
Else
'ok, if it does not exists anymore, create another one
fs = File.Open(PathK, FileMode.Append, FileAccess.Write, FileShare.None)
End If
Else
'no file ? than create it
fs = File.Open(PathK, FileMode.Append, FileAccess.Write, FileShare.None)
End If
End Sub
and here it's the code for the restart procedure:
If PidAlreadyOpen = 0 Then
'close and clean
fs.Close()
fs.Dispose()
End If
Threading.Thread.Sleep(1000)
Dim Chiusura As Integer = 0
While Chiusura < 1000
Try
'try to delete
File.Delete(PathK)
If TimeToReboot = 1 Then
System.Diagnostics.Process.Start(Application.ExecutablePath, "/noservice /release /PID:" & Settaggi.lPID)
End If
Catch ex As Exception
Chiusura = Chiusura + 1
' not deleted ? send an email, and don't stop yourself
If Chiusura = 999 Then
Dim pf As New Send_Mail
pf.Invio_Mail_Automatico_EDP(999, "ERRORECHIUSURA", Err.Description & " - " & PathK, "", Settaggi.lPID)
pf = Nothing
Exit Sub
End If
Threading.Thread.Sleep(100)
End Try
'deleted? than stop the loop
If Not File.Exists(PathK) Then
Chiusura = 1000
End If
End While
Me.Close()
how do you think should i resolve this problem ?
I don't think there's much you can do here. I had similar issues in the past and found that, while it's not possible to delete the file, it is possible to rename the file. Depending on the situation, you can rename the file and open a new file with that name. You'll also need to check, later in the process, if the renamed file is still used and delete it.

How to loop a file check until conditions are met in Visual studio 2017 with vb code?

So I'm trying to loop a file check until 1 file is there and the file that creates that file is gone. I keep trying to rewrite and have been trying to find a working setup but just can't find any this is the code that I have currently
Dim dir = My.Application.Info.DirectoryPath
If ProgressBar1.Value = 25 Then
Do
If CheckBox1.Checked Then
If FileExists(dir + "\download\downloaded.mp3") Then
If FileExists(dir + "\download\downloaded.mkv") Then
Else
ProgressBar1.Value = 45
Exit Do
End If
End If
End If
If FileExists(dir + "\download\dvid.mp4") Then
If FileExists(dir + "\download\dvid.mp4.part") Then
Else
ProgressBar1.Value = 45
Exit Do
End If
End If
Loop
when ever I get my application up a run this code the app stops responding so am I doing something wrong or is there something missing?
using wait for exit on process fixed my problem
Dim p As New Process
Dim psi As New ProcessStartInfo(dir + "file to start.exe")
psi.WindowStyle = ProcessWindowStyle.Hidden
psi.Arguments = "-x --audio-format mp3 --output /downloaded/downloaded.mkv " + Form1.TextBox1.Text
p.StartInfo = psi
p.Start()
p.WaitForExit()

Create and write to file > start application > delete file in VB.NET

I'm trying to create a VB.NET application which writes multiple lines of text into a text file, then starts an application and after the application started, deletes the text file.
How exactly can I realize that?
--
Edit:
I now got this code:
Dim iniFile As String = Application.StartupPath + "\settings.ini"
If System.IO.File.Exists(iniFile) = True Then
File.Delete(iniFile)
End If
If System.IO.File.Exists(iniFile) = False Then
File.Create(iniFile)
End If
Dim fileStr As String() = {"line1", "line2", "line3"}
File.WriteAllLines(iniFile, fileStr)
Dim p As Process = Process.Start(Application.StartupPath + "\app.exe")
p.WaitForInputIdle()
If System.IO.File.Exists(iniFile) = True Then
File.Delete(iniFile)
End If
The only problem I got, is that VS is telling me, the file is in use. Between creating and editing the file. Any ideas for that?
Your code is starting the app and then moving straight on to delete the ini file.
You need to wait for the process to exit first before you continue with deleting the ini file
E.g
{code to create ini file}
'Start the process.
Dim p As Process = Process.Start(Application.StartupPath + "\app.exe")
'Wait for the process window to complete loading.
p.WaitForInputIdle()
'Wait for the process to exit.
p.WaitForExit()
{code to delete ini file}
Full example here: https://support.microsoft.com/en-us/kb/305368
Just use File.WriteAllText
Note: As others already mentioned, you should check against True in your last If
If System.IO.File.Exists(Application.StartupPath + "\settings.ini") = False Then
File.Create(Application.StartupPath + "\settings.ini")
End If
Dim fileStr As String() = {"line1", "line2", "line3"}
System.IO.File.WriteAllText(Application.StartupPath + "\settings.ini", [String].Join(Environment.NewLine, fileStr))
Process.Start(Application.StartupPath + "\app.exe")
If System.IO.File.Exists(Application.StartupPath + "\settings.ini") = True Then
File.Delete(Application.StartupPath + "\settings.ini")
End If
Use File.WriteAllLines since it
Creates a new file, write the specified string array to the file, and then closes the file. [...] If the target file already exists, it is overwritten.
msdn
Also you should use Path.Combine to setup your path
Dim path as String = Path.Combine(Application.StartupPath, "settings.ini")
Dim fileStr As String() = {"line1", "line2", "line3"}
File.WriteAllLines(path, fileStr)
Use the Path.Combine for the Process.Start and File.Delete too.

PC cannot print to Email using Outlook

I am having a very strange problem where one of the computers in our company is unable to print an MS Access report and attach it to an email. I have done a lot of research however most of it doesn't apply to my case as this issue is happening only on one PC out of the 20+ we have in the company. This is a print screen of the error we are getting:
The code I am using is the following:
If PrintMode = "Email" Then
Dim mAcc As New Access.Application
Dim DefaultPrinterName As New String("")
Dim PDFPrinterName As New String("")
Maintain__Loading.Setup()
Try
mAcc.CloseCurrentDatabase()
mAcc.DoCmd.Close()
System.Runtime.InteropServices.Marshal.ReleaseComObject(mAcc)
mAcc = Nothing
Catch ex As Exception
End Try
Dim startInfo As New ProcessStartInfo("C:\Program Files (x86)\PDFCreator\PDFCreator.exe") 'starts PDF Creator so it can save the report to PDF
startInfo.WindowStyle = ProcessWindowStyle.Minimized
Process.Start(startInfo)
AttachmentName = "C:\PDFs\pdf.pdf" 'PDF has been set up to save all files as TestPrint.pdf
PDFPrinterName = "PDFCreatorDistribution"
'------ GETS DEFAULT PRINTER NAME -------
Dim oPS As New System.Drawing.Printing.PrinterSettings
Try
DefaultPrinterName = oPS.PrinterName
Catch ex As System.Exception
DefaultPrinterName = ""
Finally
oPS = Nothing
End Try
'sets PDFCreatorDistribution as default printer
Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", PDFPrinterName))
Try
If Not UCase(Trim(Database)) = "TEST" Then
mAcc.OpenCurrentDatabase("R:\Distribution\Access\Distribution-Reports.mde")
Else
mAcc.OpenCurrentDatabase("R:\Distribution\Access\Test-Distribution-Reports.mde")
End If
Catch ex As Exception
MsgBox(Err.Description)
End Try
If IO.File.Exists(AttachmentName) Then 'if file exists it deletes it
IO.File.Delete(AttachmentName)
End If
Select Case Trim(Grid.Rows(Grid.CurrentRow.Index).Cells("Passing1Type").Value.ToString)
Case "String"
mAcc.DoCmd.OpenReport(Trim(Grid.Rows(Grid.CurrentRow.Index).Cells("MacroName").Value.ToString), Access.AcView.acViewPreview, , Trim(Grid.Rows(Grid.CurrentRow.Index).Cells("Passing1").Value.ToString) & " = '" & Number & "'", Access.AcWindowMode.acWindowNormal)
Case "Numeric"
mAcc.DoCmd.OpenReport(Trim(Grid.Rows(Grid.CurrentRow.Index).Cells("MacroName").Value.ToString), Access.AcView.acViewPreview, , Trim(Grid.Rows(Grid.CurrentRow.Index).Cells("Passing1").Value.ToString) & " = " & Number & "", Access.AcWindowMode.acWindowNormal)
End Select
mAcc.DoCmd.PrintOut()
mAcc.Visible = True
mAcc.CloseCurrentDatabase()
mAcc.DoCmd.Close()
System.Runtime.InteropServices.Marshal.ReleaseComObject(mAcc)
mAcc = Nothing
Do While Not System.IO.File.Exists("C:\PDFs\pdf.pdf")
Threading.Thread.Sleep(2000) 'if doesn't exist, wait for 2 seconds
If Not System.IO.File.Exists("C:\PDFs\pdf.pdf") Then 'if doesn't exist, wait for another 2 seconds
Threading.Thread.Sleep(2000)
End If
If Not System.IO.File.Exists("C:\PDFs\pdf.pdf") Then 'if doesn't exist, wait for another 2 seconds
Threading.Thread.Sleep(2000)
End If
If Not System.IO.File.Exists("C:\PDFs\pdf.pdf") Then 'shows error message
MsgBox("Error creating PDF. Please try again")
Exit Do
End If
Loop
'sets default printer name
Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", DefaultPrinterName))
'saves file as
Dim saveFileDialog As New SaveFileDialog()
saveFileDialog.Filter = "PDF files (*.pdf)|*.pdf|All files (*.*)|*.*"
If saveFileDialog.ShowDialog() = DialogResult.OK Then 'if OK clicked
FileName = saveFileDialog.FileName 'get file name and move to new location/name
FileNameOnly = System.IO.Path.GetFileName(FileName)
Try
If IO.File.Exists(FileName) Then 'if file exists it deletes it before saving
IO.File.Delete(FileName)
End If
IO.File.Move(AttachmentName, FileName)
Catch ex As Exception
MsgBox(Err.Description)
Finally
Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", DefaultPrinterName))
End Try
Else 'user clicked cancel
FileName = ""
End If
Maintain__Loading.Dispose()
'GETS TO HERE AND AFTER THIS I GET THE ERROR MESSAGE DISPLAYED IN THE IMAGE ABOVE
If IO.File.Exists(FileName) Then
Try
Send_Email()
Catch ex As Exception
MsgBox(Err.Description)
End Try
Else
If Not FileName = "" Then MsgBox("An error has occured. Please try again")
End If
Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", DefaultPrinterName))
PhysicallyPrintedOrEmailed = True
End If 'Printmode = Email
I found a thread that I thought would solve my problem however unfortunately it didn't:
Unable to cast COM object - Microsoft outlook & C#
Any advice will be greatly appreciated
You have hardcoded the path to the program files location so if you are running this on a 32 bit machine it won't find the PDFCreator.exe.
Use Environment.GetFolderPath to find the path on the machine instead of hard coding it.`
Also it might help if you wrap the whole thing in a Try Catch block to see if there is an error somewhere you didn't expect
I have managed to solve this. Probably not the best way but we reinstalled Outlook and this solved the issue. We believe another program (most likely one that syncs Outlook contacts with phone) that has been installed has corrupted something. Thanks anyway :)