I'm trying to loop through a list of files to get the path and filename.
These files are dragged onto a datagrid:
Private Sub DataGridView1_DragDrop(ByVal sender As System.Object,
ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
Dim filenames As String() = DirectCast(e.Data.GetData(DataFormats.FileDrop), String())
For Each File In filenames
If Array.IndexOf(SupportedFormats, System.IO.Path.GetExtension(File)) <> -1 Then
Frm = New FormRestore(ServerName, File)
Frm.Show()
While Frm.Visible
Application.DoEvents()
End While
End If
Next
End Sub
A child form is created that processes an action based on the path and file name.
until the loop is complete, the folder the files were dragged from is locked.
How would I get a list of the path and file names AND process each one without locking out the source folder?
(I'm using the while loop to process the file names sequentially, pausing between each one while maintaining UI response)
Thanks.
Try processing the files after the drag&drop event by calling BeginInvoke in the handler.
Related
I'm trying to log file activity in a directory with the FileSystemWatch class by adding the file to a custom class within a list, unfortunately, it seems that when copying a file or adding a new file to the target directory, it's running 4 times instead of once.
When adding a file to the directory, the AddressOf Sub will write 3 to 4 times instead of just once. I'm not sure why.
Here's the code snippet.
Public fileTypefilter As String = "*.xlsx"
Public DesDir As String = "C:\"
Public EventLog As List(Of FileEvent)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim watchDir As String = DesDir
Dim watch As New FileSystemWatcher(watchDir)
Me.Text = "Monitoring " & watch.Path
watch.IncludeSubdirectories = false
watch.Filter = "*.xlsx"
AddHandler watch.Changed, AddressOf watch_Changed
watch.EnableRaisingEvents = True
End Sub
Private Sub watch_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs)
Try
EventLog.Add(New FileEvent(e.FullPath))
Exit Sub
Catch ex As NullReferenceException
EventLog = New List(Of FileEvent)({New FileEvent(e.FullPath)})
Exit Sub
End Try
End Sub
The Changed event handler is executed multiple times because multiple changes occur. As is ALWAYS the case, you should have read the relevant documentation for yourself first, which says:
The change of a file or folder. The types of changes include: changes to size, attributes, security settings, last write, and last access time.
If you don't want to log each individual change then you need to filter them somehow. For instance, you might want to record the time a change occurred for a particular path and then not log a change if some minimum time has not elapsed since the last change for the same path.
There would also be the option of using a HashSet instead of a List. That could be configured to use an appropriate equality comparer and then you could call Add as many times as you like for the same path and it will only be added once. That would mean that, were a set of changes to occur later for the same path, those would not be logged. I'm not sure whether that would be an issue for you or not.
I am new to VB and would like to create a software that moves a certain file extension into a single folder. I have already built the code that creates a folder on the desktop when clicking the button although after that runs I need to compile a certain file such as (.png) into the folder in created.
This code creates two buttons that when pressed creates a folder called "Pictures" and "Shortcuts".
How would I go about moving all .png files from the desktop into the pictures folder?
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
My.Computer.FileSystem.CreateDirectory(
"C:\Users\bj\Desktop\Pictures")
MessageBox.Show("Pictures Compiled And Cleaned")
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
My.Computer.FileSystem.CreateDirectory(
"C:\Users\bj\Desktop\Shortcuts")
MessageBox.Show("Shortcuts Compiled And Cleaned")
End Sub
End Class
We'll start simple. This command will generate an array of all the PNG files' paths on the desktop
Dim filePaths = Io.Directory.GetFiles("C:\Users\bj\Desktop\", "*.png")
We can loop through this array and act on each filepath:
For Each filePath in filePaths
Dim filename = Io.Path.GetFilename(filepath)
Dim newPath = IO.Path.Combine("C:\Users\bj\Desktop\Pictures", filename)
IO.File.Move(filePath, newPath)
Next filePath
We have to pull the filename off the path and put it into a new path, then move from old to new. This I also how you rename files; have a new name in the same folder and use Move. Always use the Path class to cut and combine file paths
I am using vb.NET and windows forms.
I have a simple form with a list box and two buttons.
btnLoadData opens up an OpenFileDialog and allows me to choose the text file to open, this is then read into the list box.
I can then delete items from the list box.
btnSaveList opens up a SaveFileDialog and allows me to choose a file to save to.
The problem occurs when I try to save to the same file that I read in.
It tells me that the file cannot be accessed as it is in use. It works if I choose a new file name.
I have searched and tried a number of different suggestions. I have altered the code a number of times and have finally decided I need to ask for help!
The code for the two buttons is below.
Private Sub btnLoadData_Click(sender As Object, e As EventArgs) Handles btnLoadData.Click
Dim openFD As New OpenFileDialog()
openFD.Filter = "Text [*.txt*]|*.txt|CSV [*.csv]|*.csv|All Files [*.*]|*.*"
openFD.ShowDialog()
openFD.OpenFile()
Dim objReader As New StreamReader(openFD.SafeFileName)
While objReader.Peek <> -1
lstList.Items.Add(objReader.ReadLine)
End While
objReader.Close()
End Sub
Private Sub btnSaveList_Click(sender As Object, e As EventArgs) Handles btnSaveList.Click
Dim saveFD As New SaveFileDialog()
If saveFD.ShowDialog = Windows.Forms.DialogResult.OK Then
Using objWriter As New StreamWriter(saveFD.FileName) 'Throws the exception here
For Each line In lstList.Items
objWriter.WriteLine(line)
Next
End Using
End If
End Sub
Private Sub lstList_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstList.SelectedIndexChanged
lstList.Items.Remove(lstList.SelectedItem)
End Sub
Thank you.
You create two streams but only closing one at the end of reading the file. The OpenFile() method of the OpenFileDialog is creating a stream you doesn't close at the end so it stays open and locks the file. In your case you are using your own stream so you don't need the method OpenFile().
code for button #1 (read the file):
openFD.Filter = "Text [*.txt*]|*.txt|CSV [*.csv]|*.csv|All Files [*.*]|*.*"
openFD.ShowDialog()
'openFD.OpenFile()
Using objReader As New StreamReader(openFD.FileName)
While objReader.Peek <> -1
lstList.Items.Add(objReader.ReadLine)
End While
End Using
code for button #2 (write the file):
Dim saveFD As New SaveFileDialog()
If saveFD.ShowDialog = Windows.Forms.DialogResult.OK Then
Using objWriter As New StreamWriter(saveFD.FileName)
For Each line In lstList.Items
objWriter.WriteLine(line)
Next
End Using
End If
Opening a file for read will lock the file against writes and deletes; opening a file for write will lock against reads, writes and deletes.
You can override those locks but trying to both read and write a file at the same time creates its own set of problems.
There are two approaches to avoid this:
Read the whole file in and close before processing and writing. Of course the whole content has to be in memory.
Write to a temporary file, after closing the input and finishing writing delete the original file and rename the temporary file. This will not preserve attributes (eg. ownership, ACL) without extra steps.
However in your case I suspect you need to use a using block to ensure the file is closed after the read rather than depending on the GC to close it at some point in the future.
Ok, so i'm trying to make an Injector. To load the DLLs, I used a File Dialog to select the DLL then write the info to a List Box. Now I want to save the data in the list box and reload the past data on the Form Load, but every method I have tried only saves the name of the DLL not the other info such as Location.
I would like to have no external files IF possible. Any solutions?
Cheers.
Edit: Source code for Open File Dialog
Private Sub OpenFileDialog1_FileOk(sender As Object, e As
System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
Dim FileName As String = OpenFileDialog1.FileName.Substring(OpenFileDialog1.FileName.LastIndexOf("\"))
Dim DLLfileName As String = FileName.Replace("\", "")
ListBox1.Items.Add(DLLfileName)
dlls.Add(DLLfileName, OpenFileDialog1.FileName)
End Sub
I added FileSystemWatcher in Form1_Load like this:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
....................
Dim watcher As New FileSystemWatcher()
'For watching current directory
watcher.Path = "/"
'For watching status.txt for any changes
watcher.Filter = "status.txt"
watcher.NotifyFilter = NotifyFilters.LastWrite
watcher.EnableRaisingEvents = True
AddHandler watcher.Changed, AddressOf OnChanged
End Sub
I have an OnChanged function which is a simple MessageBox. Still, when I change the status.txt file, no message box is shown.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim watcher As New IO.FileSystemWatcher()
'For watching current directory
watcher.Path = **System.IO.Directory.GetCurrentDirectory()** 'Note how to obtain current directory
watcher.NotifyFilter = NotifyFilters.LastWrite
'When I pasted your code and created my own status.txt file using
'right click->new->Text File on Windows 7 it appended a '.txt' automatically so the
'filter wasn't finding it as the file name was status.txt.txt renaming the file
'solved the problem
watcher.Filter = "status.txt"
AddHandler watcher.Changed, AddressOf OnChanged
watcher.EnableRaisingEvents = True
End Sub
Private Shared Sub OnChanged(ByVal source As Object, ByVal e As IO.FileSystemEventArgs)
MessageBox.Show("Got it")
End Sub
From http://bartdesmet.net/blogs/bart/archive/2004/10/21/447.aspx
You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use a FileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the operating system activities, all events that these applications fire will be picked up
You should also listen for the Deleted event.
Depending on the editor you're using, they sometimes Delete/Replace the file instead of simply changing it.