I have a system that backs up data to a network with certain parameters in place such as:
'If x process is running, do not run the backup'
Because it's connected to a network, users will constantly be on it. The problem I have is that I don't want the data to get moved onto the network if it's in use, plus, the data is unable to move across if someone is using file explorer on the same computer as the program is on.
I would use 'If explorer is running, do not run the backup' but explorer is linked to windows and is always running
If program.Count > 0 Or program2.Count > 0 Then
Try
Msgbox("Process Running")
Catch ex As Exception
End Try
Else
'backup data
End If
Is there a way to try get the program to transfer files, but if fails because the file directory is already open, then do x?
Try this. It should generate an error if you can't lock the file.
Public Function IsFileLocked(file As FileInfo) As Boolean
Dim stream = DirectCast(Nothing, FileStream)
Try
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)
Catch generatedExceptionName As IOException
'handle the exception your way
Return True
Finally
If stream IsNot Nothing Then
stream.Close()
End If
End Try
Return False
End Function
Related
I'm trying to read the Windows update log on remote PCs on my LAN. Most of the time I can successfully read the file but at times the program locks up. Likely due to one issue or another - doesn't really matter. What I do need is a way to recover when the Filestream/Streamreader locks up - I'm not sure which is causing the lock. Some streams can set a timeout but the filestream below returns False on a .CanTimeout call.
How can I break out if the stream locks up? (Sometimes the lock is so tight a power off is needed to recover.)
Is there a way to test if the stream will fail before I actually attempt the read?
Is there an alternate way to read a remote log file that another program has open? (I'm using the stream method because the regular File.IO was blocked because the file is open on the remote PC.)
I'm getting closer (I think) with this code. I browed the pathExists code from the referenced post but it was the OP and not an answer.
Imports System.IO
Import System.Threading
...
Function GetAULog(PCName As String) As String
Try
Dim sLogPath As String = String.Format("\\{0}\c$\Windows\SoftwareDistribution\ReportingEvents.log", PCName)
If PCName = My.Computer.Name Then
sLogPath = String.Format("C:\Windows\SoftwareDistribution\ReportingEvents.log", PCName)
End If
' read file open by another process
If Not pathExists(sLogPath) Then
MsgBox("AU log file not found - PC on?")
Return "NA"
End If
Using fs As New FileStream(sLogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Using sr As New StreamReader(fs)
Dim s As String = sr.ReadToEnd
Return s
End Using
End Using
Catch ex As Exception
MsgBox(ex.Message)
Return ""
End Try
End Function
Public Function pathExists(path As String) As Boolean
Dim exists As Boolean = True
Dim t As New Thread(New ThreadStart(Sub() exists = System.IO.File.Exists(path)))
t.Start()
Dim completed As Boolean = t.Join(500)
'half a sec of timeout
If Not completed Then
exists = False
t.Abort()
End If
t = Nothing
Return exists
End Function
At least when the PC is off the pathExists() code returns False in short order.
My problem now is the process does not end when the program exits - at least in the IDE, didn't check runtime.
I added t = Nothing but that didn't help. I couldn't figure out the proper Using syntax to test that. How do I properly cleanup after a thread timeout?
I've had the situation with this locking until restart problem. It seems to be caused by the tcpip auto tuning feature. You can cure this issue by running
netsh interface tcp set global autotuninglevel=disable
Run this on both machines if you have access. I tried a few workarounds for this issue with checking locks etc but the only way I could solve it was to disable this. The issue is not really with locking but with something at a lower level in the file sharing protocol.
See this article for more detail
"Final" code shown below. The exceptions are not firing when the timeout occurs so the .Abort was evidently OK.
When the timeout does occur, because the remote PC did not respond, there is a process left hanging which goes away after 30 seconds or so. I notice this when using the IDE, I run the program and test a PC that is off. If I then exit the program the form closes but the IDE hangs for ~30 seconds - I can click Stop-Debugging at this point and it works, but the IDE continues on its own after the ~30 second timeout.
I guess the t = Nothing in the Finally block does not dispose of the thread. t.Dispose does not exists.
So, things are working OK with the exception of the dangling thread that eventually clears itself up. The program is no longer hanging to the point where it cannot not be stopped.
'Imports System.IO
'Imports System.Threading
Public Function pathExists(path As String) As Boolean
' check for file exists on remote PC
Dim exists As Boolean = False
Dim t As New Thread(New ThreadStart(Sub() exists = System.IO.File.Exists(path)))
Try
t.Start()
Dim completed As Boolean = t.Join(500)
'half a sec of timeout
If Not completed Then
exists = False
t.Abort()
End If
Catch ex2 As ThreadInterruptedException
MsgBox("timeout on AU log exists test" & vbNewLine & ex2.Message,, "ThreadInterruptedException")
Catch exAbort As ThreadAbortException
MsgBox("timeout on AU log exists test" & vbNewLine & exAbort.Message,, "ThreadAbortException")
Catch ex As Exception
MsgBox("exception on AU log exists test" & vbNewLine & ex.Message)
Finally
t = Nothing
End Try
Return exists
End Function
I have sent a file by SFTP to another server using WinSCP in VB.NET.
I would like to see if the connection was successful or not.
I also need to know if the file already exists in the directory beforehand.
There are a couple of things you can do. You can create a session log that tells you (in a LOT of detail) what happened during your file transfer. You can also put a try-catch block around mySession.Open(mySessionOptions) to catch an error.
Finally, use mySession.FileExists(remotepath) to check to see if the file is already on the server.
Dim mySessionOptions As New SessionOptions
With mySessionOptions
.Protocol = Protocol.Sftp
.HostName = "999.999.999.999"
.UserName = "login"
.Password = "mypassword"
.SshHostKeyFingerprint = "ssh-dss 1024 99:87:99:4d:99:a3:99:b9:99:15:99:f2:99:87:88:b2"
End With
Using mySession As Session = New Session
' Will continuously report progress of synchronization
AddHandler mySession.FileTransferred, AddressOf FileTransferred
' Connect
mySession.SessionLogPath = "C:\Users\yourName\yourFolder\Sessionlog.log"
'Use Try-Catch to check for error in connection
Try
mySession.Open(mySessionOptions)
Catch ex As Exception
MessageBox.show(ex.Message)
mySession.Close()
Exit Sub
End Try
'Check to see if file exist already on server
If mySession.FileExists(remotePath) Then
MessageBox.Show("File Exists on Server")
mySession.Close()
Exit Sub
End If
mySession.PutFiles("C:\Users\yourName\yourFolder\yourfile.dat", remotePath)
mySession.Close()
End Using
Remember to check the log you created to see exactly what happened.
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
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.
Is there a method to verify that a file is open? The only thing I can think of is the Try/Catch to see if i can catch the file-open exception but I figured that a method be available to return true/false if file is open.
Currently using System.IO and the following code under class named Wallet.
Private holdPath As String = "defaultLog.txt"
Private _file As New FileStream(holdPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
Private file As New StreamWriter(_file)
Public Function Check(ByVal CheckNumber As Integer, ByVal CheckAmount As Decimal) As Decimal
Try
file.WriteLine("testing")
file.Close()
Catch e As IOException
'Note sure if this is the proper way.
End Try
Return 0D
End Function
Any pointers will be appreciated! Thank you!!
Private Sub IsFileOpen(ByVal file As FileInfo)
Dim stream As FileStream = Nothing
Try
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)
stream.Close()
Catch ex As Exception
If TypeOf ex Is IOException AndAlso IsFileLocked(ex) Then
' do something here, either close the file if you have a handle, show a msgbox, retry or as a last resort terminate the process - which could cause corruption and lose data
End If
End Try
End Sub
Private Shared Function IsFileLocked(exception As Exception) As Boolean
Dim errorCode As Integer = Marshal.GetHRForException(exception) And ((1 << 16) - 1)
Return errorCode = 32 OrElse errorCode = 33
End Function
Call it like this:
Call IsFileOpen(new FileInfo(filePath))
There is really no point using a 'is file in use check' function since you will still need to have try catch to handle the case that the file fails to open. The file open can fail for many more reasons than it just being already open.
Also using a function to do a check is no guarantee of success. The 'is file in use check' might return false only for the file open to fail with a file already open error, because in time between the check and trying to open the file it was opened by someone else.
It looks like the two suggestions from this MSDN forum posting both involve trying to open the file.
The first one is similar to what you are doing now, and the second involves using a Windows API function (CreateFile) and checking for a invalid handle signifying the file is in use. In both cases they are relying on an error condition to determine if the file is open or not. In short, in my opinion the method you are using is correct since there is not a System.IO.File.IsOpen property.