File Being Used By .NET Mail - vb.net

I wrote a simple program written to collect files, send the files, then delete said files. I am sending them via Email using System.Net.Mail
If Label6.Text = "" Then
mail.Attachments.Add(New Attachment(zipPath))
End If
'Enables SSL, if required
ssl = Provider.ssl
If skipAhead = True Then
ssl = True
End If
If ssl = True Then
SmtpServer.EnableSsl = True
End If
'Sends the email
SmtpServer.Send(mail)
'Allows the user to either keep testing, or quit.
If skipAhead = True Then
My.Computer.FileSystem.DeleteFile(unalteredPath)
My.Computer.FileSystem.DeleteFile(unalteredPath1)
My.Computer.FileSystem.DeleteFile(zipPath)
Else
Dim keepOpen As Integer = MsgBox("The Email was sent. You can keep testing if you would like to. Press ok to close, and cancel to keep testing", MsgBoxStyle.OkCancel)
If keepOpen = 1 Then
Close()
End If
End If
As seen in line 2, the attachment is added to the email, and I do not attempt to delete the attachment until after the email is sent, however when the code is running, it throws an error that the file is being used by another process.
I am also wondering if this could be lingering from the .zip being created itself. Here is the code that does that:
Public Sub Zipping()
'Copies files to the folder where they will be zipped from
My.Computer.FileSystem.CopyFile(unalteredPath, outputs & "\ExIpOutput.txt")
My.Computer.FileSystem.CopyFile(unalteredPath1, outputs & "\IpConfig.txt")
'Deletes the old output files
My.Computer.FileSystem.DeleteFile(unalteredPath)
My.Computer.FileSystem.DeleteFile(unalteredPath1)
'Starts the zip Sub
ZipFile.CreateFromDirectory(outputs, zipPath, CompressionLevel.Fastest, True)
My.Computer.FileSystem.DeleteDirectory(outputs, FileIO.DeleteDirectoryOption.DeleteAllContents)
End Sub
Here is the CreateFromDirectory sub:
Public Shared Sub CreateFromDirectory(sourceDirectoryName As String, destinationArchiveFileName As String, compressionLevel As Compression.CompressionLevel, includeBaseDirectory As Boolean)
End Sub
Is there something I'm missing here, or do I need to have the program sleep for a bit to let the email send, then delete the .zip file?

You can load the file into an array: File.ReadAllBytes(String) Method.
Then get a MemoryStream from that: How do I convert struct System.Byte byte[] to a System.IO.Stream object in C#?
And finally, you can use a MemoryStream for an attachment: Attach a file from MemoryStream to a MailMessage in C#.
As the data to be sent is in memory, you should be able to delete the file. Note that if there is a crash, the data is gone.
The examples are in C#, but if you have problems using the methods in VB.NET, please edit your question to show how far you've got and tell us what the problem is.

A better solution to this issue is to dispose the Attachment object that is locking the file. Any object you create that has a Dispose method should have that method called when you're done with the object and an Attachment is no different.
Dim fileAttachment As Attachment
If Label6.Text = "" Then
fileAttachment = New Attachment(zipPath)
mail.Attachments.Add(fileAttachment)
End If
'...
SmtpServer.Send(mail)
If fileAttachment IsNot Nothing Then
fileAttachment.Dispose()
End If

Related

Hangman System.IO.IOException' occurred in mscorlib.dll

i am creating a hangman game that is to be used on a few computers, i have created the hangman game itself but i am using the "load form" function to create the list when the program first starts, but i am having this issue.
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'h:\Bryson\words.txt' because it is being used by another process.
Using sw As StreamWriter = File.CreateText("h:\Bryson\words.txt")
^^that line is where the error pops up^^
I have inserted some in code Comments to make life easier. If anyone can help thanks in advance :)
'USED TO CREATE HANGMAN FILE IF NOT FOUND
Private Sub main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
fofound = False
fifound = False
MsgBox("remove this and change file path and fix qu2 quiz")
'DESIGNER USE
Dim path As String = "h:\Bryson\words.txt"
'CREATE VAR FOR PATH
If System.IO.Directory.Exists("h:\Bryson") Then
'CHECKS IF FOLDER EXISTS
fofound = True
Else
'IF IT DOES THEN IT MOVES ON
System.IO.Directory.CreateDirectory("h:\Bryson")
'IF NOT IT CREATES THE FOLDER
fofound = True
If File.Exists("h:\Bryson\test\words.txt") Then
'CHECKS IF FILE EXISTS
fifound = True
Else
'IF IT DOES IT MOVES ON
IO.File.Create("h:\Bryson\words.txt")
'IF NOT IT CREATES IT
FileClose()
End If
End If
If fofound And fifound = True Then
Else
Using sw As StreamWriter = File.CreateText("h:\Bryson\words.txt")
'CRASH POINT The process cannot access the file 'C:\Bryson\words.txt'
'because it Is being used by another process.
sw.WriteLine("Hangman")
sw.WriteLine("computer")
sw.WriteLine("electrode")
sw.WriteLine("independent")
sw.WriteLine("stream")
sw.WriteLine("enforcing")
End Using
'WRITES TO FILE
MsgBox("file created")
'DESIGNER USE
FileClose()
'CLOSES FILE
End If
End Sub
FileClose() is a legacy function from VB6 and will not affect anything in the System.IO namespace. To close a file you need to call .Close() or .Dispose() on the stream that has opened the file (wrapping the stream in a Using block does this automatically).
Your problem is this line:
IO.File.Create("h:\Bryson\words.txt")
The method creates a new file and opens a FileStream to it which locks the file. Since you never close the returned FileStream your file will remain locked until you close your application.
The File.Create() call is completely unnecessary though because File.CreateText() will create the file if it doesn't exist. So you should just remove the above line.

" A Sharing Violation occured" error when editing images in Paint using VB.NET

I have written a program in VB.NET to monitor file changes to recent saved screenshots taken from the tool.
I have a custom FileSystemWatcher class written (shared by someone on the internet,just customized) and have an instance invoked in my program.
The basic issue or objective is that when i capture a screen area using my program, I want it to immediately copy it over to clipboard. There are times when I would want to edit the captured image, in which case any editing made and saved, after saving the edited image must automatically be copied over to clipboard.
I use the below code to copy the image over to clipboard
'Subroutine to Copy the captured screenshot
'Added 15/09/2014
Sub CopyImageCapture(ByVal ImgPath)
Dim ThreadA As Thread
ThreadA = New Thread(AddressOf Me.MyAsyncTask)
'Setting ApartmentState.STA as this is needed for Clipboard related functionalities
ThreadA.SetApartmentState(ApartmentState.STA)
ThreadA.Start(ImgPath)
End Sub
'Threading to handle the Clipboard copy function
'Copy the screenshot to Clipboard
'Added 15/09/2014
Private Sub MyAsyncTask(ByVal ImgPath)
Clipboard.Clear()
Clipboard.SetImage(ImgPath)
End Sub
And when i choose to edit the image, the below code takes care to monitor the file changes
Sub MonitorFileChange(ByVal FolderPath, ByVal ItemName)
Try
Dim sFolder As String
Dim sFile As String
sFolder = FolderPath
sFile = ItemName
If IO.Directory.Exists(sFolder) Then
objWatcher.FolderToMonitor = sFolder
objWatcher.FileToMonitor = sFile
'objWatcher.NotifyFilter = (NotifyFilters.FileName Or NotifyFilters.Size)
objWatcher.StartWatch()
Else
MessageBox.Show("Folder does not exist!")
End If
Catch ex As Exception
MsgBox("Encountered an exception in MonitorFileChange subroutine. Details - " + ex.Message)
End Try
End Sub
'Subrountine to capture FileChanged events (esp. when captured image is edited in Paint and Saved)
'Works in sync with custom class 'clsFSW' for this purpose.
'ADDED: 15/09/2014
Private Sub objWatcher_FileChanged(ByVal FullPath As String) Handles objWatcher.FileChanged
'Try
Dim lastWriteTime As DateTime
lastWriteTime = File.GetLastWriteTime(FullPath)
Debug.Print(lastWriteTime)
If (lastWriteTime <> lastRead) Then
objWatcher.EnableRaisingEvents = False
'QuickCopy for changes files. BUG FIX
If (QuickSaveToolStripMenuItem.Checked) Then
Debug.Print("File Changed: " & FullPath & vbCrLf)
Dim tempI As System.Drawing.Bitmap = New System.Drawing.Bitmap(FullPath)
Dim tempI2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(tempI, tempI.Width, tempI.Height)
CopyImageCapture(tempI2)
tempI.Dispose()
End If
lastRead = lastWriteTime
End If
'Catch ex As Exception
' MsgBox("Encountered an exception in objWatcher_FileChanged subrountine. Details - " + ex.Message)
' 'Finally
' 'objWatcher.EnableRaisingEvents = True
'End Try
End Sub
The problem is sometimes when I open the captured image and make quick saves or press save a couple of times real quick I get a "A Sharing violation occured" error
Can anyone help resolve the above issue? Which part of the code or logic is causing this to happen?
Also, if you check the above snippet, sometimes (havent seen any particular pattern) but the catch block in objWatcher_FileChanged is triggered and the error is "Parameter not found"
Can someone please help into this too?
Thanks in advance! Please let me know if any info more is required.
EDIT: Please note, the sharing violation error seems invoked from the Paint application itself and not my program, but why does it happen randomly, is a mystery to me. Is there nay loophole in the logic? Any alternative logic to what I want to achieve?
Try disposing tempI2. Windows may be locking the file used with tempI, and keeping it locked since it is assigned to tempI2. If so, it may remain locked until tempI2 is disposed.

FtpWebRequest.GetRequestStream hang up and fails.

I have wrote a web service, in a nutshell it uses openpop to get email messages does stuff with the content to insert into databases and saves attachments which are images. That works fine when i save images locally, it does exactley what it is suppose to. Now an added requirment was to save images to an FTP directory, so i can create my folders dynamically (they are created based upon timestamp) and that works well. My problem comes from when i try to save them to the ftp. Yes my user name and password are correct, otherwise i wouldn't be creating the directory.
Private Sub UploadFile(ByVal fileToSave As FileInfo, ByVal path As String)
Dim UploadRequest As FtpWebRequest = DirectCast(WebRequest.Create("ftp://UserName:Passowrd#999.99.999.9" & path), FtpWebRequest)
UploadRequest.Credentials = New NetworkCredential("PicService", "grean.matching18")
UploadRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
UploadRequest.UseBinary = True
UploadRequest.UsePassive = True
' Const BufferSize As Integer = 2048
' Dim content(BufferSize - 1) As Byte, dataRead As Integer
Dim bFile() As Byte = System.IO.File.ReadAllBytes(fileToSave.ToString)
'UploadRequest.ContentLength = content.Length
Using FileStream1 As FileStream = fileToSave.OpenRead()
Try
'open request to send
Using RequestStream As Stream = UploadRequest.GetRequestStream
End Using
Catch ex As Exception
Finally
'ensure file closed
FileStream1.Close()
End Try
End Using
End Sub
I have tried using Passive False and Binary False as well, i did more research on my stack trace.
And found this article but no solution as of yet. Any input would be appreciated, i am also posting another question on windows services for different issue. If you would like to take a shot at it, the other question isnt about ftp but permissions for a service on windows server 2003
This may not be the solution but I've found that the URI string has to be 'just right' and that what is 'just right' varies by the ftp server.
So ftp://server/directory/file works on some servers but needs to be ftp://server//directory/file to work on others (note the double slash after the server name)
Aso, your URI has 'password' spelled incorrectly: ftp://UserName:Passowrd#999.99.999.9 and you are supplying the credentials in a separate code line as well.

ususual problem with system.net.mail attachment

I have an ususual problem with my attachment memorystream on a VB.net project. I am calling a shared member (SendMail) passing in a customer object and a memorystream of a file to be sent as an attachment. Within the "SendMail" it calls two separate functions to prepare one regular email and another for a digitally signed email. The problem I have is I recieve the digitally signed email perfect, however, in the regular email, the attachment is blank and the file name has appended (64 B). If I disable the part of the digitally signing the regular mails works fine. It looks like somewhere the memorystream is changed in the digital signing.
Here his how I make the calls
mailHelper.SendMail(cust, attachment)
withing the mailHelper CLASS
Public Shared Sub SendEmail(ByVal cust As Customer, ByVal attachment As MemoryStream)
Dim messages As New List(Of MailMessage)
messages.Add(CreateUnSignedMail(cust,attachment)
messages.Add(CreateSignedMail(cust,attachment)
SendSMTPMail(messages)
End Sub
Private Shared Function CreateUnSignedMail(ByVal cust As Customer, ByVal attachment As MemoryStream) As MailMessage
Dim eMail As New MailMessage()
With eMail
.//Normal properties set (like to, from etc)
.Attachments.Add(New Attachment(attachment, "someFilename.doc")
End With
Return eMail
End Function
Private Shared Function CreateSignedMail(ByVal cust As Customer, ByVal attachment As MemoryStream) As MailMessage
Dim eMail As New SecureMailMessage()
With eMail
.//Normal properties set (like to, from etc)
.Attachments.Add(New SecureAttachment(attachment, "someFilename.doc")
End With
Return eMail
End Function
Private Shared Sub SendSMTPMail(ByVal messages As List(Of System.Net.Mail.MailMessage))
Dim smtp As New SmtpClient("myServer")
Try
With smtp
.//Additional properties set
For Each email In messages
.Send(email)
Next
End With
Catch ex As Exception
//Log error to file.
Logger.Log.Error("SMTP Error", ex)
Throw
End Try
End Sub
If I try the following it works fine, however, is this the proper solution?
messages.Add(SendUnSignedMail(cust, New MemoryStream(attachment.ToArray())))
messages.Add(SendSignedMail(cust, New MemoryStream(attachment.ToArray())))
Assume you already fixed this given the delay in getting an answer but here is my attempt anyhow...
There are quite a few overloads to create an Attachment, none of them match the way you initialised the Attachment.
When creating an Attachment the second parameter needs to be either NULL or identify a valid MIME-type for your attachment.
Hope this helps.

Can I add an Outlook Attachment from a PictureBox image?

I have an image in my VB.NET Picture box. I would like to attach it to the email message I'm sending through Outlook without having to save it to the drive anywhere. Is it possible to do such a thing?
Here's what I have so far (taken from here):
Public Class email
Dim app As Microsoft.Office.Interop.Outlook.Application
Dim appNameSpace As Microsoft.Office.Interop.Outlook._NameSpace
Dim memo As Microsoft.Office.Interop.Outlook.MailItem
Dim outbox As Microsoft.Office.Interop.Outlook.MAPIFolder
Public Sub New(ByVal attachment)
Try
app = New Microsoft.Office.Interop.Outlook.Application
appNameSpace = app.GetNamespace("MAPI")
appNameSpace.Logon(Nothing, Nothing, False, False)
memo = app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem)
memo.To = "notmy#realemailaddress.com"
memo.Subject = "Testing"
memo.Body = "Hello there"
memo.Attachments.Add(attachment, Microsoft.Office.Interop.Outlook.OlAttachmentType.olByValue)
memo.Send()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
End Class
When I comment out the attachment line it works perfectly fine, otherwise it throws a COMError. I haven't been able to find any real good information about attaching an email that way, or if it's even possible. If I can't do it this way I plan on just saving the file to some random(ish) name in C:\TEMP\, but it would be nicer if I didn't have to worry about that.
Thanks for any help
Here are your options: Attachment Types
The source information here can help also:Attachment Add Function