Dealing with an error related to deleting a directory - error-handling

Following is a very simple program I wrote, using Visual Studio 2012, that clearly shows the error:
Imports System.Drawing.Imaging
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Using bmp As New Bitmap(800, 200)
Dim gr As Graphics = Graphics.FromImage(bmp)
For n = 0 To 3
Dim fileName As String = "D:\Users\Gerry\Desktop\TmpImages\SmileFace" + CStr(n) + ".jpg"
Using tmpBmp As Bitmap = New Bitmap(Image.FromFile(fileName))
gr.DrawImage(tmpBmp, n * 200, 0)
End Using
Next
gr.Dispose()
Dim finalName As String = "D:\Users\Gerry\Desktop\Combined.jpg"
bmp.Save(finalName, ImageFormat.Jpeg)
End Using
Directory.Delete("D:\Users\Gerry\Desktop\TmpImages", True)
Application.Exit()
End Sub
End Class
The problem, which happens both in debug and stand alone modes, is that the folder TmpImages does not get deleted. The following is the error text:
System.IO.IOException: The process cannot access the file
'SmileFace0.jpg' because it is being used by another process. at
System.IO.Directory.DeleteHelper(String fullPath, String userPath,
Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound,
WIN32_FIND_DATA& data) at System.IO.Directory.Delete(String fullPath,
String userPath, Boolean recursive, Boolean checkHost) at
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectoryInternal(String
directory, DeleteDirectoryOption onDirectoryNotEmpty, UIOptionInternal
showUI, RecycleOption recycle, UICancelOption onUserCancel) at
Microsoft.VisualBasic.MyServices.FileSystemProxy.DeleteDirectory(String
directory, DeleteDirectoryOption onDirectoryNotEmpty) at
bmpSave.Form1.Form1_Load(Object sender, EventArgs e) in
C:\Users\Gerry\Documents\Visual Studio 2012\Projects\Learning and
Testing\bmpSave\bmpSave\Form1.vb:line 22 at
System.EventHandler.Invoke(Object sender, EventArgs e)
One experiment I tried was to add the statement Close after the statement gr.Dispose. The error is no longer thrown, but the directory is not deleted. Note that in the code, I tried both Directory.Delete and FileSystem.DeleteDirectory and had the same result both times. The error relates to one of the files in the folder TmpImages that is simply opened for reading.
Please suggest that which I should do to resolve this issue. Thanks.

Related

vb.net winforms download without blocking

I'm downloading files .mp3 and my goal is not to have even a minimum GUI freezing during downloading.
My aim is also to display the bites received in a progress bar and through labels.
This code is working, but sometimes is freezing without any reason, sometimes the progress bar doesn't work until file is completely done.
So far, this is the "best" code I found online for a completely working progress bar during a download, but still gets problems.
How do you think I can increase performances? How can I make a resistant and reliable working progressbar? How can I download also large file without GUI freezing? I tried (curiosity) to download a 600 mb file and it completely freeze, not responding and not giving any issue back.
Thanks
EDIT1: I'm trying with this,eventhough I'm lost on high waves.. Any idea on how can I use this code and insert it into Jimi Answer? Answer
Imports System.IO
Imports System.IO.Path
Imports System.Net
Public Class Form1
Private downloader As MyDownloader = Nothing
Private Sub btnStartDownload_Click(sender As Object, e As EventArgs) Handles btnStartDownload.Click
Dim progress = New Progress(Of String)(
Sub(data)
MsgBox("we are on the UI thread here")
End Sub)
Dim url As Uri = New Uri(TextBox1.Text)
downloader = New MyDownloader()
'How can I remove this second? I don't need download from url every 1 second.
downloader.StartDownload(progress, url, 1)
End Sub
And
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Net
Imports System.Net.Http
Imports System.Text.RegularExpressions
Imports System.Threading
Public Class MyDownloader
Private Shared ReadOnly client As New HttpClient()
client.DownloadProgressChanged += AddressOf Client_DownloadProgressChanged
client.DownloadFileCompleted += AddressOf Client_DownloadFileCompleted
Private interval As Integer = 0
Private Sub Client_DownloadFileCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
System.Windows.Forms.MessageBox.Show("Download OK!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Public Sub StartDownload(progress As IProgress(Of String), url As Uri, intervalSeconds As Integer)
interval = intervalSeconds * 1000
Task.Run(Function() DownloadAsync(progress, url))
End Sub
Private Sub Client_DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
ProgressBar1.Minimum = 0
Dim receive As Double = Double.Parse(e.BytesReceived.ToString())
Dim total As Double = Double.Parse(e.TotalBytesToReceive.ToString())
Dim percentage As Double = receive / total * 100
label2.Text = $"{String.Format("{0:0.##}", percentage)}%"
ProgressBar1.Value = Integer.Parse(Math.Truncate(percentage).ToString())
End Sub
Private Async Function DownloadAsync(progress As IProgress(Of String), url As Uri) As Task
Dim pattern As String = "<(?:[^>=]|='[^']*'|=""[^""]*""|=[^'""][^\s>]*)*>"
Dim downloadTimeWatch As Stopwatch = New Stopwatch()
downloadTimeWatch.Start()
Do
Try
Dim response = Await client.GetAsync(url, HttpCompletionOption.ResponseContentRead)
Dim data = Await response.Content.ReadAsStringAsync()
data = WebUtility.HtmlDecode(Regex.Replace(data, pattern, ""))
progress.Report(data)
Dim delay = interval - CInt(downloadTimeWatch.ElapsedMilliseconds)
Await Task.Delay(If(delay <= 0, 10, delay))
downloadTimeWatch.Restart()
Catch ex As Exception
End Try
Loop
End Function
End Class
I'm Seriously lost on it, I tried to delete cancel download as I am not going to stop any download and I tried also to delete Download from url every 1 second as I just need one time download for every link.
Thanks

Passing Download complete Event with parameter to another class

I have an application whose main window upon click of a button gives users an option to load a list of files in the cloud.
Private Sub ImportCloudContent()
Dim cloudForm As Form_CloudImport
cloudForm = New Form_CloudImport()
cloudForm.Show()
cloudForm.populateDataGrid()
AddHandler cloudForm._DownloadComplete, New EventHandler(AddressOf OpenProject)
cloudForm.DownloadNotifier(FullPathOfContent)
End Sub
Ideally I should be able to get the value of the FullPathOfContent variable and pass it onto Open Project, but I am not sure how to go about it.
In the new Window users can click and download the file they want. Below is the section of code that handles the download in the Form_CloudImport class :
Private Async Sub Btn_download_Click(sender As Object, e As EventArgs) Handles Btn_download.Click
Dim fileNameRows As DataGridViewSelectedRowCollection = datagridview_cloudContent.SelectedRows
Dim fileName As String
Dim fileType As String = Cloud.CONTENT
Dim FullPathOfContent As String
For Each fileNameRow As DataGridViewRow In fileNameRows
fileName = fileNameRow.Cells(0).Value.ToString() & ".zip"
Try
FullPathOfContent = CloudToCCT(fileName, fileType)
Catch ex As Exception
CSMessageBox.ShowError("Content Import failed : ", ex)
End Try
Next
Me.Close()
DownloadNotifier(FullPathOfContent)
End Sub
Once the download is complete, the main window needs to call some of its methods. I am new to VB and have created a custom event to facilitate this(again in the Form_CloudImport class)
Public Event _DownloadComplete(e As String)
Public Sub DownloadNotifier(FullPathOfContent As String)
RaiseEvent _DownloadComplete(FullPathOfContent)
End Sub
According to what have read, once the download method is complete, it will fire the DownloadNotifier method, which will raise the _DownloadComplete event and the MainWindow should trigger the following events.
However, I receive the below errors in the MainWindow part of the code :
Value of type 'MainWindow.EventHandler' cannot be converted to 'Form_CloudImport._DownloadCompleteEventHandler'
and
'FullPathOfContent' is not declared. It may be inaccessible due to its protection level.
This question seems to be very long but any help would be appreciated. Thank you in advance!
First things first, you should create a type and event with proper names and signature and raise it properly.
Public Class CloudImportForm
Public Event DownloadComplete As EventHandler(Of DownloadCompleteEventArgs)
Protected Overridable Sub OnDownloadComplete(e As DownloadCompleteEventArgs)
RaiseEvent DownloadComplete(Me, e)
End Sub
'...
End Class
Public Class DownloadCompleteEventArgs
Inherits EventArgs
Public Sub New(contentPath As String)
Me.ContentPath = contentPath
End Sub
Public ReadOnly Property ContentPath As String
End Class
In that form, you would have code that performed a download and then raised that event.
'...
Dim contentPath = GetContentPath()
'Perform download here.
'Raise event.
OnDownloadComplete(New DownloadCompleteEventArgs(contentPath))
In your main form you would create and configure the download form, which includes handling the event, and then display it.
Dim cloudForm As New CloudImportForm
AddHandler cloudForm.DownloadComplete, AddressOf CloudImportForm_DownloadComplete
cloudForm.PopulateDataGrid()
cloudForm.Show()
The method you specify as the event handler should have the appropriate signature and it should retrieve the content path from the e parameter.
Private Sub CloudImportForm_DownloadComplete(sender As Object, e As DownloadCompleteEventArgs)
Dim contentPath = e.ContentPath
'Use contentPath here.
End Sub

file deletion exception on vb.net

My VB.NET junk cleaner cannot delete aria-Debug-10144.log since it is used by another process.
I tried this:
Imports System.Collections.ObjectModel
Imports System.IO
Public Class Form1
Dim TempDirs As ReadOnlyCollection(Of String)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TempDirs = (My.Computer.FileSystem.GetDirectories("C:\Users\Aitor\AppData\Local\Temp"))
Dim ListDirs As List(Of String) = TempDirs.ToList
Dim directoryName As String = "C:\Users\Aitor\AppData\Local\Temp"
For Each deleteFile In Directory.GetFiles(directoryName, "*.*", SearchOption.TopDirectoryOnly)
If Not deleteFile.ToString = "aria-Debug-10144.log" Then
File.Delete(deleteFile)
End If
Next
MsgBox("Clean completed!", MsgBoxStyle.OkOnly + MsgBoxStyle.Information, "Results")
End Sub
End Class
But it still tries to do it.
Can anybody help me?
There are two reasons:
Firstly, the selected file is being occupied by another program. In this case, you need to determine whether the selected file is occupied before deleting it. Here is a small example.
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("kernel32.dll")>
Public Shared Function _lopen(ByVal lpPathName As String, ByVal iReadWrite As Integer) As IntPtr
End Function
<DllImport("kernel32.dll")>
Public Shared Function CloseHandle(ByVal hObject As IntPtr) As Boolean
End Function
Public Const OF_READWRITE As Integer = 2
Public Const OF_SHARE_DENY_NONE As Integer = &H40
Public Shared ReadOnly HFILE_ERROR As IntPtr = New IntPtr(-1)
Public Shared Function IsFileOccupied(ByVal filePath As String) As Boolean
Dim vHandle As IntPtr = _lopen(filePath, OF_READWRITE Or OF_SHARE_DENY_NONE)
CloseHandle(vHandle)
Return If(vHandle = HFILE_ERROR, True, False)
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If (IsFileOccupied("C:\Users\juliex\AppData\Local\Temp\aria-debug-13836.log")) Then
MessageBox.Show("File is already occupied")
Else
MessageBox.Show("File is not occupied")
'Then do some delete operation.
End If
End Sub
End Class
Secondly, the selected file is a temporary file and is currently locked. If you want to clear the temporary files it owns, you need to have full control to unlock these files and then delete them!
You should be very careful if you want to delete the TEMP file, whether it is owned by the application or by another owner. The original application may have applied the lock because it wanted to use the file!
At this time you can refer to this link below:
1.How can I unlock a file that is locked by a process in .NET
2.https://social.msdn.microsoft.com/Forums/vstudio/en-US/9e2044c5-ae5d-4552-a335-01cc567dfc58/how-to-unlock-a-file-used-by-other-process?forum=csharpgeneral

Event 'Load' cannot be found

Getting the error "Event 'Load' cannot be found" referring to "Handles MyBase.Load" Please see attached code. Any help much appreciated!
I have many other applications set up the same way and they all work. However, these were in an older version of Visual Studio.
Option Explicit On
Option Strict On
Imports System, System.IO
Imports System.Text
Public Class Form1
Private Sub cleanXMLDialog_Load(ByVal eventSender As System.Object, ByVal
eventArgs As System.EventArgs) Handles MyBase.Load
Main()
End
End Sub
Public Sub Main()
Dim directories() As String = Directory.GetDirectories("C:\")
Dim files() As String = Directory.GetFiles("C:\", "*.dll")
DirSearch("c:\")
End Sub
Sub DirSearch(ByVal sDir As String)
Dim d As String
Dim f As String
Try
For Each d In Directory.GetDirectories(sDir)
For Each f In Directory.GetFiles(d, "*.xml")
'Dim Response As String = MsgBox(f)
Debug.Write(f)
Next
DirSearch(d)
Next
Catch excpt As System.Exception
Debug.WriteLine(excpt.Message)
End Try
End Sub
End Class
Load should happen without this error.
This is the class declaration:
Public Class Form1
It looks like you intend this to inherit from a windows Form type, but there's nothing here to make that happen.
You may want this:
Public Class Form1 Inherits System.Windows.Forms.Form
but even this is unlikely to really accomplish anything. It's not enough just to inherit from the Form type if you don't have any controls are properties set and don't ever show the form.
Did you accidentally create a Console or Class Library project when you mean to create a WinForms project?

Object reference not set to an instance of object - vb.net

First a little background information: The purpose of this application is to capture images and save them automatically to a network directory that will be either created or appended using the input of the text box. This code DOES work on my computer (windows 7 home 64 bit). I've created it using microsoft visual basic express 2010.
However..... when attempting to run the application on a windows 10 tablet, I get the follow errors:
On form load:
An error occurred while capturing the image. The video capture will now be terminated.
Object reference not set to an instance of an object.
On button2_Click Event:
Object reference not set to an instance of an object.
Below is the entirety of the code.
Form2.vb
Public Class Form2
Public scanIsSet As Boolean
Private webcam As WebCam
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
webcam = New WebCam()
webcam.InitializeWebCam(imgVideo)
webcam.Start()
scanIsSet = False
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim CFGfile As String
Dim SaveDir As String
Dim imgIndex As Integer
Dim existingImages() As String
SaveDir = "C:\somepath\"
'save image to directory with index number
Try
imgCapture.Image.Save(SaveDir & OrderNumber.Text & "\" & CStr(imgIndex) & ".jpg")
Catch ex As Exception
MsgBox("error while accessing object imgCapture" & ex.Message)
End Try
imgIndex = imgIndex + 1
Else
Beep()
MsgBox("Please scan or type in order number first")
End If
End Sub
End Class
WebCam.vb
Imports System
Imports System.IO
Imports System.Linq
Imports System.Text
Imports WebCam_Capture
Imports System.Collections.Generic
Imports ZXing
Imports ZXing.OneD
'Design by Pongsakorn Poosankam
Class WebCam
Public scanz As Boolean
Public Sub setScan(ByVal x As Boolean)
scanz = x
End Sub
Private webcam As WebCamCapture
Private _FrameImage As System.Windows.Forms.PictureBox
Private FrameNumber As Integer = 30
Public Sub InitializeWebCam(ByRef ImageControl As System.Windows.Forms.PictureBox)
webcam = New WebCamCapture()
webcam.FrameNumber = CULng((0))
webcam.TimeToCapture_milliseconds = FrameNumber
AddHandler webcam.ImageCaptured, AddressOf webcam_ImageCaptured
_FrameImage = ImageControl
End Sub
Private Sub webcam_ImageCaptured(ByVal source As Object, ByVal e As WebcamEventArgs)
_FrameImage.Image = e.WebCamImage
If scanz = True Then
Dim BCreader As New ZXing.BarcodeReader
'BCreader.Options.TryHarder = True
Try
Dim resu As Result = BCreader.Decode(e.WebCamImage)
Form2.OrderNumber.Text = resu.Text
setScan(False)
Form2.Label2.Text = ""
Beep()
Catch ex As Exception
'do nothing
End Try
End If
End Sub
Public Sub Start()
webcam.TimeToCapture_milliseconds = FrameNumber
webcam.Start(0)
End Sub
Public Sub [Stop]()
webcam.[Stop]()
End Sub
Public Sub [Continue]()
' change the capture time frame
webcam.TimeToCapture_milliseconds = FrameNumber
' resume the video capture from the stop
webcam.Start(Me.webcam.FrameNumber)
End Sub
Public Sub ResolutionSetting()
webcam.Config()
End Sub
Public Sub AdvanceSetting()
webcam.Config2()
End Sub
End Class
As you can see toward the end of Form2.vb, I've wrapped imgCapture.Image.Save(SaveDir & OrderNumber.Text & "\" & CStr(imgIndex) & ".jpg") in a Try-Catch block because I suspect it's some sort of problems with the pictureBox objects. The try catch block does indeed catch the exception, but I still have no idea what the problem is, why it happens on the tablet and not the PC, or how to fix it.
I've found similar questions, but none with a solution I can make use of.
Since you are using a library, EasyWebCam, that is outdated and not compatible with Win10, I would suggest switching libraries. Other options out there:
DirectX.Capture
Windows.Media.Capture
I FOUND THE SOLUTION BUT I DON'T KNOW IF YOU NEED IT NOW ANYWAY THE PROBLEM IS IF YOU HAVE CHANGED THE PICTUREBOX NAME THEN IN REFENCES USE THE EXACT NAME YOU HAVE CHANGED TO. EXAMPLE IF I CHANGE ALL MY PICTUREBOX NAMES AS -
PictureBox_A1 , PictureBox_A2 ,... and so on then my refence should be as -
Dim r As DataRow
For Each r In t1.Rows
CType(Controls("PictureBox_" & r(2)), PictureBox).Image = bookedicon
Next
MY REFERENCE IS - "PictureBox_"