VB .NET How to copy a directory without its subfolders - vb.net

I want t copy all files in a directory, but ignore all sub-folders. Is there a single function to do this?
The standard function:
My.Computer.FileSystem.CopyDirectory(inputDir.FullName, outputDir.FullName)
copies all the sub-folders.
Iterating over all files:
For Each file In inputDir.GetFiles()
file.CopyTo(Path.Combine(outputDir.FullName, file.Name), True)
Next
seems to work fine. But it looks too complex to me. Is there a simpler way?

Make it into a function ...
Public Sub CopyFiles(inputPath As System.IO.DirectoryInfo,
outputPath As System.IO.DirectoryInfo)
For Each fi In inputPath.GetFiles()
fi.CopyTo(Path.Combine(outputPath.FullName, fi.Name), True)
Next
End Sub
... so it can simply be called like this when you want to use it
CopyFiles(New DirectoryInfo("C:\test1"), New DirectoryInfo("C:\test2"))

Related

VB - Writing to a file, closing and Object existance

I am writing a program that writes data to a text file at different points in my code, for example in different subroutines, functions or at different parts of subroutines (being scattered around).
First, I Dim the file writer:
Dim CurrentHisWriter As System.IO.StreamWriter
I tell it where to write to:
CurrentHisWriter = New System.IO.StreamWriter("C:\ProgramData\Japanese Conjugation Helper\LastSearch.txt")
Then, I actually write things:
CurrentHisWriter.Writeline("thing to write")
The problem is that I have to change to a different subroutine and then keep on writing to a file, so I have to close the writer and then dim another one in another subroutine:
CurrentHisWriter.Close
NewSubroutine()
[NewSubroutine]:
Dim CurrentHisWriter As System.IO.StreamWriter
CurrentHisWriter = New System.IO.StreamWriter("C:\ProgramData\Japanese Conjugation Helper\LastSearch.txt")
But then when I do this, I gives me one of a couple errors:
The program is has an instance of the file running
Some thing to do with there being no object (I don't remember exactly)
What is a reliable way programming the writing to files without having to worry about closing the writer at every point I change subroutines. I'm not sure about how objects and instances work and so the only thing I can do now is make a catch loop around every single line that uses the "CurrentHisWriter.Writeline" but this isn't really working too.
I know my lack of knowledge in this doesn't help explain, but I tried my best.
The naive approach would be like:
Sub Main()
MethodA()
MethodB()
End Sub
Sub MethodA()
Log("Starting method A")
End Sub
Sub MethodB()
Log("Starting method B")
End Sub
Sub Log(message as String)
System.IO.File.AppendAllText("C:\temp\my.log", message)
End Sub
File.AppendAllText is pretty good at closing things off so you can subsequently write to it elsewhere
A better approach would be to have a class whose job it is to build this file, and it builds it all into a stringbuilder and then writes it once. Multiple of your methods use that class, build that file... The class can either implement some timed/periodic dumping of data to disk (if it's like logging, never ending, thousands of events per second.. but then perhaps you'd just use a logging framework rather than reinvent the wheel), or it has a write method that saves the rendering of it to disk
If there is another specialized application of your data at work here, for example if you're generating XML or JSON you should look at specific serialization approaches for those (wheels that have already been invented)
I use
FileOpen(1, "file.txt", OpenMode.Append)
Now you can write from any other subroutine
PrintLine(1, "text to write")
Until the file is closed
FileClose(1)
But maybe you could solve your problem this way:
Define CurrentHisWriter outside of subroutine as
Private CurrentHisWriter As System.IO.StreamWriter = ....
Then you won't have to close and reopen the writer, all your Subs and functions will have access to it.

How to double check if folder is empty`?

I can't find a solution for my problem. My Code is deleting empty folders and in general working fine, but there is one exception. It goes through every path one time, but if there was a Folder (A) that only has empty Folder (B) in it, then it would only delete Folder(B), since Folder (A) was not at empty at the time. How can I make it, so that it understands that Folder (A) is gonna be empty, once Folder (B) is deleted?
I thought DeleteEmptyFolder(folder.FullName) would solve the problem, but it is not working, since it doesn't repeat the same path it already went through. Removing directory.GetDirectories.Count = 0 doesn't work either, since it would delete any folder that doesn't have a file in it (even if there is another folder with files in it)
Private Sub DeleteEmptyFolder(ByVal sDirectoryPath As String)
If IO.Directory.Exists(sDirectoryPath) Then
Dim directory As New IO.DirectoryInfo(sDirectoryPath)
If directory.GetDirectories.Count = 0 AndAlso directory.GetFiles.Count = 0 Then
directory.Delete(True)
Return
End If
For Each folder As IO.DirectoryInfo In directory.GetDirectories()
DeleteEmptyFolder(folder.FullName)
Next
End If
End Sub
I am fairly new to VB.Net, so pardon if it is an obvious answer that I don't see.
Here's how the code ought to look:
Private Sub DeleteEmptyFolder(folderPath As String)
If Directory.Exists(folderPath) Then
For Each subFolderPath In Directory.EnumerateDirectories(folderPath)
DeleteEmptyFolder(subFolderPath)
Next
If Directory.EnumerateFiles(folderPath).Any() OrElse
Directory.EnumerateDirectories(folderPath).Any() Then
Return
End If
Directory.Delete(folderPath)
End If
End Sub
There's no point using DirectoryInfo if you need no other information about files and folders other than path. You should use EnumerateFiles and EnumerateDirectories over GetFiles and GetDirectories unless you specifically need to get an array of entries up front. In this case, you definitely don't. Let's say that you had a folder with 1000 files in it. This:
directory.GetFiles.Count = 0
would create an array containing an element for all 1000 files first, then check the number of elements in it. On the other hand, this:
Directory.EnumerateFiles(folderPath).Any()
would return True as soon as it encountered the first file, ignoring the other 999. You only care whether there's any files in the folder, not how many there are.
Please try this:
Private Sub deleteEmptyFolders(ByRef folder As String)
'Does exist such a path?
If IO.Directory.Exists(folder) Then 'yes
'Loop over all directories
For Each subFolder In IO.Directory.GetDirectories(folder)
'Delete all empty folders
deleteEmptyFolders(subFolder)
Next
'Delete folder if nothing remained in it
Try
My.Computer.FileSystem.DeleteDirectory(folder, FileIO.DeleteDirectoryOption.ThrowIfDirectoryNonEmpty)
Catch ex As Exception
End Try
End If
End Sub
I think this does what you want in a simple way.
I solved the problem by moving some of the code around.
Private Sub DeleteEmptyFolder(ByVal sDirectoryPath As String)
If IO.Directory.Exists(sDirectoryPath) Then
Dim directory As New IO.DirectoryInfo(sDirectoryPath)
For Each folder As IO.DirectoryInfo In directory.GetDirectories()
DeleteEmptyFolder(folder.FullName)
Next
If directory.GetDirectories.Count = 0 AndAlso directory.GetFiles.Count = 0 Then
directory.Delete(True)
Return
End If
End If
End If

IO.File.Move doesn't work for files (VB.NET)

I am making a Program where you add files to an ListBox, and when you click the Install-Button it should move the files that got added to the ListBox, to an other folder. But this doesn't work, and i don't know how to fix. Here is my current Code:
Private Sub MoveFileBackgroundWorker(sender As Object, e As DoWorkEventArgs) Handles mfb.DoWork
For Each i As String In ListBox1.Items 'For each Items in ListBox1.Items, move.
IO.File.Move(i, mcpath_ & "\mods\")
Next
End Sub
Any help is really appreciated! PS: Sorry if my English isn't good, i am German :)
Move works in the following way:
IO.File.Move("C:\\myfile1.txt", "D:\\myfile2.txt")
It takes the source file as the first argument, and the target file as the second argument. In other words, the line above will move the file C:\myfile1.txt to a file named D:\myfile2.txt
So your line should be
IO.File.Move(i, IO.Path.Combine(mcpath_, "mods", IO.Path.GetFileName(i))
Which means: move file stored in i to the folder mcpath & "\mods\" with the same file name and extension
That's how i fixed it:
IO.File.Move(i, IO.Path.Combine(mcpath_.Trim, "mods", IO.Path.GetFileName(i)))
You need to add at mcpath_ .Trim!

How to rename directory with WinSCP .NET assembly?

I want to be able to rename directory whether it contains something or not. I do not see such option. For instance this is how I create directory, but how to rename it?:
Public Sub CreateDirectory(path As String)
If session IsNot Nothing Then
session.CreateDirectory(path)
End If
End Sub
Use the Session.MoveFile method:
session.MoveFile("/path/directory", "/path/new_name")

Handling Error While Compiling Using CodeDom

So after fixing my problem while compiling code using CodeDom, I've encountered another problem relating to the code. This is confusing because the code works perfectly fine when I run it - it only happens when I try to compile it.
My code does this:
For every file in the directory C:\temp\ - if the file name contains "123" it adds it to a list of strings.
Dim file_list As New List(Of String)
Dim temp_directory As New IO.DirectoryInfo("C:\temp\")
Dim get_file_info As IO.FileInfo() = temp_directory.GetFiles()
Dim item As IO.FileInfo
For Each item In get_ssfn_files
If item.ToString.Contains("123") Then
file_list.Add(item.ToString)
End If
Next
Then, it will do something with each file in a for each statement.
For Each file_found in file_list
'Do Something
Next
The error seems to happen on this line:
For Each file_found in file_list
I dont know why, because like I said, the code works fine when I'm not compiling it with CodeDom. Anyone know how to go about fixing this? Thanks in advance.
If the code is being compiled with Option Infer Off, you need to specify a type for file_found.
For Each file_found As String In file_list
'Do Something
Next