How do know the csv created from SQLite is closed so I can read from it? - vb.net

In vb.net, I have my program run sqlite3.exe. Sqlite3 runs the following commands, which are stored in a text file:
.open prod.db
.mode csv
.output output.csv
SELECT STATEMENT
.output stdout
.exit
Once output.csv has been created, I then run a Streamreader to see what the results were and I get the following error:
The process cannot access the file 'output.csv' because it is being used by another process.
However, I know it is not locked up for long because I can go to the csv and open it manually after it is created.
I would write code to check to see when the process finishes, but I'm not sure what process is running to check this (I already check for SQLite3.exe to close). In other words, how do I know my csv is free for Streamreader to open?

Using droque's link"
VB.Net 3.5 Check if file is in use
I was able to combine this with some of my own code to fix the problem:
While FileInUse("output.csv") And j < 100
System.Threading.Thread.Sleep(100)
j += 1
End While
'Timeout after ~10 seconds
If j = 100 Then
MessageBox.Show("CSV timeout. Exiting now.")
Exit Sub
End If
where FileInUse is defined here:
Public Function FileInUse(ByVal sFile As String) As Boolean
Dim thisFileInUse As Boolean = False
If System.IO.File.Exists(sFile) Then
Try
Using f As New IO.FileStream(sFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
' thisFileInUse = False
End Using
Catch
thisFileInUse = True
End Try
End If
Return thisFileInUse
End Function

Related

VB.NET: The process cannot access the file 'filename' because it is being used by another process

I should add a list of files into a ZIP. Procedure code is like this
Sub CreateZip
Dim FileList As New ArrayList 'List of File Paths to be added to the ZIP
For Each path in FileList
Try
AddFileToZip(ZipFilePath, path.ToString)
Catch (ex as New Exception)
....
End Try
Next
End Sub
And this is AddFileToZip
Public Sub AddFileToZip(ByVal zipFilename As String, ByVal fileToAdd As String)
Using zip As Package = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate)
Dim destFilename As String = ".\" & Path.GetFileName(fileToAdd)
Dim uri As Uri = PackUriHelper.CreatePartUri(New Uri(destFilename, UriKind.Relative))
If zip.PartExists(uri) Then
zip.DeletePart(uri)
End If
Dim part As PackagePart = zip.CreatePart(uri, "", CompressionOption.Normal)
Using fileStream As New FileStream(fileToAdd, FileMode.Open, FileAccess.Read)
Using dest As Stream = part.GetStream()
CopyStream(fileStream, dest)
End Using
End Using
End Using
End Sub
At runtime, I get this error message
The process cannot access the file [ZipFilePath] because it is being used by another process
this error is raised randomly, maybe on adding small files into the Zip. If I place breakpoints and run procedure in debug mode, it works.
It seems clear that procedure thread is not synchronized with IO, so that my procedure loop continues even if IO is still adding processed file into Zip (ie VB.NET is faster than IO).
I also tried to place a Thread.Sleep(1000) before AddFileToZip, but this may be not enough to synchronize the two processes. Placing Thread.Sleep(2000) seems to make procedure work, but it may slow down dramaticly performances (I should pack more than 50 files into my Zip).
So, how can I force my loop to "wait" until IO Process has released ZIP file?

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.

Check the file whether is it by another process

I have some ask to you to check and advice if my code is enough and correct. My application works on files sometimes its downloading multiple files by windows service and then by other windows service parser process those files are parsing. Unfortunately before process file has to be finished downloading before process parser should open the file and play with it therefore i prepared some code to check firstly whether the file is free - means not open by another process or some person, whatever. I use most cases streamreader to open the file and play with it but as i said i would like firstly check file if its ready.
This is my code, what do you think:
Public Shared Function FileInUse(ByVal sFile As String, ByVal log As String) As Boolean
Dim thisFileInUse As Boolean = True
Dim counter As Integer = 0
For i = 0 To 30
counter += 1
If System.IO.File.Exists(sFile) Then
Try
Using f As New IO.FileStream(sFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
thisFileInUse = False
Exit For
End Using
Catch
System.Threading.Thread.Sleep(10000) '10 sec
End Try
End If
Next
Return thisFileInUse
End Function

How to check if file (.wav) is opened and then play file

I am currently working on a console application to play a freshly created WAV RIFF file, and then delete it. Like I said, it is freshly created, so I need to make sure the file isn't being edited before I start playing it or it will be corrupted. After it plays, I delete it.
Currently, my code looks like this (using System.IO):
Sub Main()
Dim fileName As String
fileName = "C:\temp\Burst\Burst.wav"
While CheckFile(fileName)
End While
Try
My.Computer.Audio.Play(fileName, AudioPlayMode.WaitToComplete)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
My.Computer.FileSystem.DeleteFile(fileName)
End Sub
Private Function CheckFile(ByVal filename As String) As Boolean
Try
System.IO.File.Open(filename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)
FileClose(1)
Return False
Catch ex As Exception
Return True
End Try
End Function
The function I am using to check if the file is opened was created by sealz. I found it here. Unfortunately, however, this function is causing an exception in that after it runs, the program cannot access the file because it is being used by another process. If I remove this function, the file can be opened, played and deleted.
The exception reads as follows:
An unhandled exception of type'System.IO.IOException' occurred in mscorlib.dll Additionalinformation: The process cannot access the file 'C:\temp\Burst\burst.wav' because it is being used by another process.
So the function that is supposed to help determine if the file is being used, is actually causing the file to be opened. It seems like it isn't closing. Is there anyway I can modify this current function to work properly for my application or are there any other ideas on how to tackle this. Thanks for your time.
-Josh
Here is your problem:
System.IO.File.Open(filename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)
FileClose(1)
Return False
A Using will help:
Using _fs as System.Io.FileStream = System.IO.File.Open(filename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)
End Using
Return False
File.Open Returns a Filestream, not an Integer needed for FileClose
As far as I get you are trying to check if file exists before playback using System.IO.File.Open however you may do it with File.Exists.
Method File.Exists from System.IO returns true if file exists on path and returns false the otherwise.
Also you are doing it wrong here,
While CheckFile(fileName)
End While
If file is found it will enter into an infinite loop without doing anything other than calling CheckFile repeatedly. If file is not found, it will get out of loop and attempt Audio.Play and FileSystem.DeleteFile and you end up getting a file not found exception.
Here is your code modified and working.
Imports System.IO
Module Module1
Sub Main()
Dim fileName As String
fileName = "C:\temp\Burst\Burst.wav"
While CheckFile(fileName)
Try
My.Computer.Audio.Play(fileName, AudioPlayMode.WaitToComplete)
'Delete statement here if you want file to be deleted after playback
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End While
My.Computer.FileSystem.DeleteFile(fileName)
Console.ReadLine()
End Sub
Private Function CheckFile(ByVal filename As String) As Boolean
If (File.Exists(filename)) Then
Return True
Else
Return False
End If
End Function
End Module

Why am I getting object reference not set error on script task connector?

I have an SSIS package (SQL Server 2005) that loops through a bunch of flat files in a folder. I need to wait until the source application has finished writing the file before I can open it in my flat file import task.
I have a For Each loop container and within it a script task to execute before the Data Flow Task.
When I try to create the success connector between the Script Task and the Data Flow Task I get this error:
Could not create connector. Object reference not set to an instance of
an object.
I get that something is being set to nothing, but I can't see it. I have DelayValidation set to true on both the Script Task and the Data Flow Task. What else am I missing?
I'm a C# guy so maybe I'm missing something obvious in the VB. Here's the script I poached from the interwebs:
Public Sub Main()
Dim strFileName As String = CType(Dts.Variables("FileName").Value, String)
Dim objFS As System.IO.FileStream
Dim bolFinished As Boolean = False
Do
Try
objFS = System.IO.File.Open(strFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
bolFinished = True
objFS.Close()
Catch ex As Exception
System.Threading.Thread.Sleep(1000)
End Try
Loop
If bolFinished Then
Dts.TaskResult = Dts.Results.Success
Else
Dts.TaskResult = Dts.Results.Failure
End If
End Sub
Milen k is more than right. It looks like you have an infinite loop which is opening a file several times until it breaks down.
You could change your code with the below suggested code. This will help you to get out of the infinite loop.
Your current code:
Do
Try
objFS = System.IO.File.Open(strFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
bolFinished = True
objFS.Close()
Catch ex As Exception
System.Threading.Thread.Sleep(1000)
End Try
Loop
Suggested code:
Do While(true)
Try
objFS = System.IO.File.Open(strFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
bolFinished = True
objFS.Close()
Exit Do
Catch ex As Exception
System.Threading.Thread.Sleep(1000)
End Try
Loop
Make sure that you have created a Flat File Source for your Data Flow task. If you do not have an existing one, create a temporary one which act as a place-holder for the file paths you feed it through the For Each loop.
From what I understand, you should be passing the path to each file that you will be importing to your Flat File Connection. This can easily be done by adding the variable generated in your For Each loop as an expression in the Expression property of your Flat File Connection.
UPDATE:
You need to set a condition in your Do ... Loop. For example: Loop While Not bolFinished. Look at this document for more information.