Copying same file to multiple locations / drives with progress bar - vb.net

I am trying to make a vb.net appliaction designed to copy one file to multiple locations at the same time. But I can't figure out how to stop the System.IO.IOException I am receiving because multiple threads are trying to access the file. Here is my current code:
Dim parts As String() = targ.Split(New Char() {"\"c})
Dim filename As String = parts(parts.Count - 1) 'target folder name
Dim dir_path As String = "" 'directory without target folder name
Dim FolderList As New List(Of String)
Dim copied As Integer = 0<
For f As Integer = 0 To parts.Count - 2
dir_path += parts(f) + "\"
Next
Dim counter As Integer = IO.Directory.GetFiles(targ, "*.*", IO.SearchOption.AllDirectories).Length 'counts the number of files
newitm.SubItems(4).Text = "Copied (0/" + counter.ToString + ")" 'displays the amount of copied files
FolderList.Add(targ) 'Set first folder
Do While True
Dim FoldersInsideDirectory As New List(Of String)
If FolderList.Count = 0 Then
Exit Do 'If there is no folder to copy Exit Do
Else
For l As Integer = 0 To FolderList.Count - 1
Dim fileSystemInfo As System.IO.FileSystemInfo
Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(FolderList(l))
Dim dest As String = FolderList(l).Replace(dir_path, "")
If (Not System.IO.Directory.Exists(des + "\" + dest)) Then 'create subFolder inside directory
System.IO.Directory.CreateDirectory(des + "\" + dest)
End If
For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos
Dim destinationFileName As String = System.IO.Path.Combine(des + "\" + dest, fileSystemInfo.Name)
If TypeOf fileSystemInfo Is System.IO.FileInfo Then
Dim streamRead As New System.IO.FileStream(fileSystemInfo.FullName, System.IO.FileMode.Open)
Dim streamWrite As New System.IO.FileStream(des + "\" + dest + "\" + fileSystemInfo.Name, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
Dim lngLen As Long = streamRead.Length - 1
newitm.SubItems(3).Text = "Copy bytes : (0/" + (lngLen * 100).ToString + ")"
Dim byteBuffer(1048576) As Byte 'our stream buffer
Dim intBytesRead As Integer 'number of bytes read
While streamRead.Position < lngLen 'keep streaming until EOF
newitm.SubItems(3).Text = "Copy bytes : (" + CInt(streamRead.Position).ToString + "/" + (lngLen * 100).ToString + ")"
intBytesRead = (streamRead.Read(byteBuffer, 0, 1048576))
streamWrite.Write(byteBuffer, 0, intBytesRead)
streamRead.Flush()
End While
'Clean up
streamWrite.Flush()
streamWrite.Close()
streamRead.Close()
copied += 1
newitm.SubItems(4).Text = "Copied (" + copied.ToString + "/" + counter.ToString + ")"
Else
FoldersInsideDirectory.Add(fileSystemInfo.FullName)
End If
Next
Next
FolderList.Clear()
FolderList = FoldersInsideDirectory
End If
MsgBox("Done")
Loop

You need to specify FileShare.Read in the FileStream's constructor:
Read
Allows subsequent opening of the file for reading. If this flag is not specified, any request to open the file for reading (by this process or another process) will fail until the file is closed.
Dim streamRead As New System.IO.FileStream(fileSystemInfo.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)

Related

I Want to add a Timestamp with the original Name of the Folders name that is being Copied (in vb.net)

I found some Code to Copy a Folder with all its contents to another folder. the Folder name that is being copied to another folder is the same as the original folder in its original path. I want to add a timestamp with a date and time to show you the most recent 'copy' of the folder you copied.
An example would be:
Original Folder: Rage 2 ;
Copied Folder: Rage 2 - 3/11/2021 - 7:37
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim parts As String() = directoryTargetLocation.Split(New Char() {"\"c})
Dim filename As String = parts(parts.Count - 1) 'target folder name
Dim dir_path As String = "" 'directory without target folder name
For f As Integer = 0 To parts.Count - 2
dir_path += parts(f) + "\"
Next
Dim copied As Integer = 0
Dim counter As Integer = IO.Directory.GetFiles(directoryTargetLocation, "*.*", IO.SearchOption.AllDirectories).Length 'counts the number of files
SetProgressbar(counter, ProgressBar2) 'Sets ProgressBar maximum to number of files
setLabelTxt("Copied (0/" + counter.ToString + ")", Label4) 'displays the amount of copied files
Dim FolderList As New List(Of String)
FolderList.Add(directoryTargetLocation) 'Set first folder
Do While True
If (BackgroundWorker1.CancellationPending = True) Then 'cancel loop
e.Cancel = True
Exit Do
End If
Dim FoldersInsideDirectory As New List(Of String)
If FolderList.Count = 0 Then
Exit Do 'If there is no folder to copy Exit Do
Else
For l As Integer = 0 To FolderList.Count - 1
If (BackgroundWorker1.CancellationPending = True) Then 'stop for loop
e.Cancel = True
Exit For
End If
Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(FolderList(l))
Dim dest As String = FolderList(l).Replace(dir_path, "")
If (Not System.IO.Directory.Exists(Destinydirectory + "\" + dest)) Then 'create subFolder inside directory
System.IO.Directory.CreateDirectory(Destinydirectory + "\" + dest)
End If
Dim fileSystemInfo As System.IO.FileSystemInfo
For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos
If (BackgroundWorker1.CancellationPending = True) Then
e.Cancel = True
Exit For
End If
Dim destinationFileName As String = System.IO.Path.Combine(Destinydirectory + "\" + dest, fileSystemInfo.Name)
If TypeOf fileSystemInfo Is System.IO.FileInfo Then
Dim streamRead As New System.IO.FileStream(fileSystemInfo.FullName, System.IO.FileMode.Open)
setLabelTxt(fileSystemInfo.FullName.ToString, LabelProgress)
Dim streamWrite As New System.IO.FileStream(Destinydirectory + "\" + dest + "\" + fileSystemInfo.Name, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
Dim lngLen As Long = streamRead.Length - 1
setLabelTxt("Copy bytes : (0/" + (lngLen * 100).ToString + ")", Label10)
Dim byteBuffer(1048576) As Byte 'our stream buffer
Dim intBytesRead As Integer 'number of bytes read
While streamRead.Position < lngLen 'keep streaming until EOF
If (BackgroundWorker1.CancellationPending = True) Then
e.Cancel = True
Exit While
End If
BackgroundWorker1.ReportProgress(CInt(streamRead.Position / lngLen * 100))
setLabelTxt("Copy bytes : (" + CInt(streamRead.Position).ToString + "/" + (lngLen * 100).ToString + ")", Label10)
intBytesRead = (streamRead.Read(byteBuffer, 0, 1048576))
streamWrite.Write(byteBuffer, 0, intBytesRead)
End While
'Clean up
streamWrite.Flush()
streamWrite.Close()
streamRead.Close()
addProgress(1, ProgressBar2)
copied += 1
setLabelTxt("Copied (" + copied.ToString + "/" + counter.ToString + ")", Label4)
Else
FoldersInsideDirectory.Add(fileSystemInfo.FullName)
End If
Next
Next
FolderList.Clear()
FolderList = FoldersInsideDirectory
End If
Loop
End Sub
Before:
Dim streamWrite As New System.IO.FileStream(Destinydirectory + "\" + dest + "\" + fileSystemInfo.Name, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
After:
dim fnbase as string = Path.GetFileNameWithoutExtension(fileSystemInfo.Name)
dim fnexten as string = path.getextension(fileSystemInfo.Name)
dim fndate as string = DateTime.Now.ToString("yyyyMMdd HHmmss")
dim fn as string = $"{fnbase} - {fndate}{fnexten}"
Dim streamWrite As New System.IO.FileStream(Destinydirectory + "\" + dest + "\" + fn, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
I broke this down the way I did just so it was really easy for you to see the different pieces of it. You could just as easily put all of this together dynamically as the value you pass to System.IO.FileStream.
As an aside, you're doing the copy itself the complicated way. Maybe you need to use that method for a specific reason, but if not, maybe consider File.Copy next time.

Calling SSRS from SSIS: Some the PDF files gets corrupted

I am calling SSRS from SSIS Script task and stores the report in PDF format.
Below is my code in Script task:
Protected Sub SaveFile(ByVal url As String, ByVal localpath As String)
Dim loRequest As System.Net.HttpWebRequest
Dim loResponse As System.Net.HttpWebResponse
Dim loResponseStream As System.IO.Stream
Dim loFileStream As New System.IO.FileStream(localpath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
Dim laBytes(256) As Byte
Dim liCount As Integer = 1
Try
loRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
loRequest.Credentials = System.Net.CredentialCache.DefaultCredentials
loRequest.Timeout = 7200
loRequest.Method = "GET"
loResponse = CType(loRequest.GetResponse, System.Net.HttpWebResponse)
loResponseStream = loResponse.GetResponseStream
Do While liCount > 0
liCount = loResponseStream.Read(laBytes, 0, 256)
loFileStream.Write(laBytes, 0, liCount)
Loop
loFileStream.Flush()
loFileStream.Close()
Catch ex As Exception
End Try
End Sub
Public Sub Main()
Dim url, destination, Todaydate, FolderName, DestinationError As String
Try
Todaydate = Dts.Variables("TodayDate").Value.ToString
FolderName = Dts.Variables("FolderName").Value.ToString
destination = Dts.Variables("DestFolder").Value.ToString + "\" + Todaydate + "\" + FolderName + "\" + Dts.Variables("CurrentReport").Value.ToString + "_" + Dts.Variables("CurrentParamID").Value.ToString + "_" + Format(Now, "yyyyMMdd") + ".pdf"
url = "http://server-name/ReportServer?/ReportPath/AUTOMATED/" + Dts.Variables("CurrentReport").Value.ToString + "&rs:Command=Render&Param=" + Dts.Variables("CurrentParamID").Value.ToString + "&rs:Format=PDF"
Dts.Variables("User::GeneratedPDFpath").Value = destination
SaveFile(url, destination)
End Try
Dts.TaskResult = ScriptResults.Success
End Sub
This code works fine and generates report in PDF. But, sometimes it generates PDF file with size of 0 KB. When that PDF is opened, it displays an error for Corrupted File.
P.S. I have used Execute SQL task which stores a resultset. Using that resultset in Foreach Loop container, it initially created folder for today's date and stores the respective PDF in folder.
Would appreciate if someone could provide some help on this.

How can I improve the efficiency of my simple file-splitting program

I have a simple program that reads a .txt file, and then splits it up into many files of "pMaxRows" number of rows. These .txt files are huge - some are nearly 25Gb. Right now it is not running fast enough for my liking, I feel that there should be a way to improve the efficiency by maybe reading/writing multiple lines at once, but I am not very experienced with vb.net streamreader/streamwriter.
Code is below:
Public Sub Execute(ByVal pFileLocation As String, _
ByVal pMaxRows As Int32)
Dim sr As IO.StreamReader
Dim Row As String
Dim SourceRowCount As Int64
Dim TargetRowCount As int64
Dim TargetFileNumber As Int32
''Does the file exist in that location?
If IO.File.Exists(pFileLocation) = False Then
Throw New Exception("File does not exist at " & pFileLocation)
End If
''Split FileLocation into FileName and Folder Location
Dim arrFileLoc() As String = pFileLocation.Split("\")
Dim i As Integer = arrFileLoc.Length - 1
Dim FileName As String = arrFileLoc(i)
Dim FileLocationLength As Integer = pFileLocation.Length
Dim FileNameLength As Integer = FileName.Length
Dim Folder As String = pFileLocation.Remove(FileLocationLength - FileNameLength, FileNameLength)
''Read the file
sr = New IO.StreamReader(pFileLocation)
SourceRowCount = 0
TargetRowCount = 0
TargetFileNumber = 1
''Create First Target File Name
Dim TargetFileName As String
TargetFileName = TargetFileNumber & "_" & FileName
''Open streamreader and start reading lines
Do While Not sr.EndOfStream
''if it hits the target number of rows:
If (TargetRowCount = pMaxRows) Then
''Advance target file number
TargetFileNumber += 1
''Create New file with target file number
TargetFileName = TargetFileNumber & "_" & FileName
''Set target row count back to 0
TargetRowCount = 0
End If
''Read line
Row = sr.ReadLine()
''Write line
Using sw As New StreamWriter(Folder & TargetFileName, True)
sw.WriteLine(Row)
End Using
SourceRowCount += 1
TargetRowCount += 1
Loop
End Sub
Anyone have any suggestions? Even directing me to the right place if this has been answered before would be much appreciated

system.io.ioexception the process cannot access because it is being used by another process

i am getting this problem in some systems, some systems working properly, here my code is,
Dim fileName As String = "FaultTypesByMonth.csv"
Using writer As IO.StreamWriter = New IO.StreamWriter(fileName, True, System.Text.Encoding.Default) '------------ rao new ----
Dim Str As String
Dim i As Integer
Dim j As Integer
Dim headertext1(rsTerms.Columns.Count) As String
Dim k As Integer = 0
Dim arrcols As String = Nothing
For Each column As DataColumn In TempTab.Columns
arrcols += column.ColumnName.ToString() + ","c
k += 1
Next
writer.WriteLine(arrcols)
For i = 0 To (TempTab.Rows.Count - 1)
For j = 0 To (TempTab.Columns.Count - 1)
If j = (TempTab.Columns.Count - 1) Then
Str = (TempTab.Rows(i)(j).ToString)
Else
Str = (TempTab.Rows(i)(j).ToString & ",")
End If
writer.Write(Str)
Next
writer.WriteLine()
Next
writer.Close()
writer.Dispose()
End Using
Dim FileToDelete As String = Nothing
Dim sd As New SaveFileDialog
sd.Filter = "CSV Files (*.csv)|*.csv"
sd.FileName = "FaultTypesByMonth"
If sd.ShowDialog = Windows.Forms.DialogResult.OK Then
FileCopy(fileName, sd.FileName)
MsgBox(" File Saved in selected path")
FileToDelete = fileName
If System.IO.File.Exists(FileToDelete) = True Then
System.IO.File.Delete(FileToDelete)
End If
End If
FileToDelete = fileName
If System.IO.File.Exists(FileToDelete) = True Then
System.IO.File.Delete(FileToDelete)
End If
when i am trying to save this file in desired path, then i am getting this error.
if save in shared folder i am not getting this error
system.io.ioexception the process cannot access because it is being used by another process...
what i am doing wrong,Help me

Load Image files from folder

I have a checked list box and a thumbnail area to display them where I am trying to load only images from a specific folder and need to display in thumbnails area but the problem is there is a thumbs.db file which is also being added to the checked list box which I don't need it.
So how do I actually load only the image files without the thumbs.db file.
Here is my code:
Private Sub LoadProjectToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LoadProjectToolStripMenuItem.Click
Using ofdlg As New Windows.Forms.OpenFileDialog
ofdlg.DefaultExt = "trk"
ofdlg.Filter = "Project|*.trk"
ofdlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
If ofdlg.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim SaveData As New gCanvasData
Using objStreamReader As New StreamReader(ofdlg.FileName)
Dim x As New XmlSerializer(GetType(gCanvasData))
SaveData = CType(x.Deserialize(objStreamReader), gCanvasData)
objStreamReader.Close()
End Using
With SaveData
'gTSSizer_gAZoom.Value = 100
GCanvas1.ImageXYReset()
GCanvas1.Image = .Image
GCanvas1.gAnnotates = .gAnnotates
GCanvas1.RebuildAll()
GCanvas1.AssembleBitmap()
End With
Dim fullpath As String
fullpath = Application.StartupPath + "\" & System.IO.Path.GetFileNameWithoutExtension(ofdlg.FileName) + "\"
For Each fi As FileInfo In New DirectoryInfo(fullpath).GetFiles
CheckedListBox1.Items.Add(Application.StartupPath + "\" & System.IO.Path.GetFullPath(ofdlg.FileName))
For i As Integer = 0 To CheckedListBox1.Items.Count - 1
CheckedListBox1.SetItemChecked(i, True)
ThumbControl1.AddFolder(fullpath, True)
Next i
Next
End If
End Using
End Sub
Either filter it inside of the For Each Loop:
For Each fi As FileInfo In New DirectoryInfo(fullpath).GetFiles
If Not {".jpg", ".png", ".bmp"}.Contains(fi.Extension) Then Continue For
' ...
Next
or do it in the GetFiles:
DirectoryInfo(fullpath).GetFiles(".jpg")
Found the solution at last:
Dim fullpath As String
fullpath = Application.StartupPath & "\" & System.IO.Path.GetFileNameWithoutExtension(ofdlg.FileName) + "\"
Dim FileDirectory As New IO.DirectoryInfo(fullpath)
Dim FileJpg As IO.FileInfo() = FileDirectory.GetFiles("*.jpg")
Dim FileGif As IO.FileInfo() = FileDirectory.GetFiles("*.gif")
Dim FileBmp As IO.FileInfo() = FileDirectory.GetFiles("*.bmp")
For Each File As IO.FileInfo In FileJpg
CheckedListBox1.Items.Add(File.FullName)
Dim str As String
str = Directory.GetCurrentDirectory() & "\" & "Backup\"
Next
For Each File As IO.FileInfo In FileGif
CheckedListBox1.Items.Add(File.FullName)
Dim str As String
str = Directory.GetCurrentDirectory() & "\" & "Backup\"
Next
For Each File As IO.FileInfo In FileBmp
CheckedListBox1.Items.Add(File.FullName)
Dim str As String
str = Directory.GetCurrentDirectory() & "\" & "Backup\"
Next
For i As Integer = 0 To CheckedListBox1.Items.Count - 1
CheckedListBox1.SetItemChecked(i, True)
Next i
Change DirectoryInfo(fullpath).GetFiles to DirectoryInfo(fullpath).EnumerateFiles() And add a search pattern for the image file extensions you want. http://msdn.microsoft.com/en-us/library/dd383574.aspx