Visual basic : Generic GDI+ error when saving file - vb.net

When I executed my program I created in visual basic. I got a GDI+ error when I tried to save an image from a picturebox.
If I run it on the PC, where I created the program(windows 10), I don't have any problems. When I run it on 2 different windows 7 PC's, I got the error.
The mapped networkdrive is the same ( Z:\ ) and writeable.
Here is the code:
Private Sub SaveImage(ByVal pathToSaveTo As String)
Try
Using bmp As New Bitmap(Picimage.Image)
bmp.Save(pathToSaveTo, Drawing.Imaging.ImageFormat.Jpeg)
End Using
Catch ex As Exception
MessageBox.Show("An error occurred:" & vbCrLf & vbCrLf & _
ex.Message, "Error Saving Image File", _
MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
End Try
End Sub
The button to start the action
Private Sub Button2_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim dt As String = My.Computer.FileSystem.SpecialDirectories.Desktop
Dim testOutput As String
testOutput = "Z:\" & naam & " " & Now.ToString("HH/mm/ss") & ".jpg"
SaveImage(testOutput)
nr.Focus()
End Sub

GDI is complaining about the filename you're using.
Here's the problem: testOutput = "Z:\" & naam & " " & Now.ToString("HH/mm/ss") & ".jpg"
You're generating a filename with slashes in the path. If those are meant to be directory names (a directory for each hour, minute and second respectively) then those directories need to ex that won't work as GDI will not create missing directories along a path for you. If the slashes are meant to be in the filename itself then it also won't work as slashes are not a valid filename character.
Change the slashes to underscores or hyphens or other characters allowed in filenames:
testOutput = "Z:\" & naam & " " & Now.ToString("HH_mm_ss") & ".jpg"

Related

Compressing a Folder Using Rar.exe via VB.NET?

I already extracted a folder with files from a RAR archive using the Unrar.exe I then want to edit the files within the extracted folder and then Re-rar that folder back into a password protected RAR archive. Either that, or append the existing RAR archive. Either way, the main goal is to update the files within the password protected archive. But I can't seem to figure out how to compress the folder again. My code as follows:
Imports System.IO
Public Class Form1
'establish the application directory and set it as a string to plugin later when needed
Dim MAINDIR As String = AppDomain.CurrentDomain.BaseDirectory
Private Sub UNRAR()
'if extracted folder does NOT exist then
If Not (System.IO.Directory.Exists(MAINDIR & "Credentials\")) Then
'set variables
Dim SourceFile As String = MAINDIR & "Credentials.rar"
Dim PassWord As String = "locker101"
Dim DestinationFolder As String = MAINDIR
'if extracted folder does not exist then
If Not IO.Directory.Exists(DestinationFolder) Then IO.Directory.CreateDirectory(DestinationFolder)
'unrar it and create extracted folder with the files
Dim p As New Process
p.StartInfo.FileName = MAINDIR & "UnRAR.exe"
p.StartInfo.Arguments = "-p" & PassWord & " x " & Chr(34) & SourceFile & Chr(34) & " " & Chr(34) & DestinationFolder & Chr(34)
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
p.Start()
End If
End Sub
Private Sub EDIT(ByVal ACCOUNT, ByVal USER, ByVal PASS, ByVal URL)
Do Until (System.IO.Directory.Exists(MAINDIR & "Credentials\"))
'does nothing on loop and keeps checking for the folder to exist
Loop
'confirms that the folder exists then begins to write to the file(s) inside
If (System.IO.Directory.Exists(MAINDIR & "Credentials\")) Then
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter(MAINDIR & "Credentials\" & ACCOUNT & ".txt", False)
file.WriteLine(USER)
file.WriteLine(PASS)
file.WriteLine(URL)
file.Close()
MsgBox("DONE")
Else
MsgBox("FAILED")
MsgBox("END existing")
MsgBox("END LOOP")
End If
APPENDRAR()
End Sub
Private Sub APPENDRAR()
End Sub
Private Sub DELETE()
'deletes the extracted folder, leaving behind only the password protected rar archive
My.Computer.FileSystem.DeleteDirectory(MAINDIR & "Credentials", False, False)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
UNRAR()
'sets textboxes' texts as strings then sends those values to the EDIT sub
Dim btn As Button = DirectCast(sender, Button)
Dim ACCOUNT As String = TB_account.Text
Dim USER As String = TB_user.Text
Dim PASS As String = TB_pass.Text
Dim URL As String = TB_url.Text
EDIT(ACCOUNT, USER, PASS, URL)
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
End Sub
End Class
It should also be mentioned that I have the Unrar.exe and Rar.exe
files in the application folder. The same files found in the Winrar
directory. I added them to my project folder to use them.
A brief explanation of what is expected: The user will fill out 3 textboxes (username, password, website url) then they will click a button. The button takes the text in each textbox as values then creates strings of those values. It then passes these string values onto the sub which UNRARS the RAR archive, then once the folder is extracted, it either overwrites any existing file in that folder or creates a new one. Then after that, it should repack this newly edited folder back into a RAR archive with the same password as before, then deletes the extracted folder and the old RAR archive (UNLESS I can just append them back into the original archive, then I would not have to make an "updated" archive.)
UPDATE:
Dim SourceFile As String = MAINDIR & "Credentials\"
Dim PassWord As String = "locker101"
Dim DestinationFolder As String = MAINDIR
'if extracted folder does not exist then
'If Not IO.Directory.Exists(DestinationFolder) Then IO.Directory.CreateDirectory(DestinationFolder)
'unrar it and create extracted folder with the files
Dim p As New Process
Dim bbs As String = "-p" & PassWord & " u " & Chr(34) & MAINDIR & "ass.rar" & Chr(34) & " " & Chr(34) & SourceFile & Chr(34)
p.StartInfo.FileName = MAINDIR & "Rar.exe"
p.StartInfo.Arguments = bbs
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
p.Start()
This seems to work but it seems to not just add the "Credentials" folder but every folder leading up to it starting from "Projects".
I finally figured it out. Just in case anyone else needed the answer, here it is.
Dim p0 As New Process
Dim createo As String
createo = "-p" & <PASSWORD> & " u -ep " & Chr(34) & <arhive.rar> & Chr(34) & " " & Chr(34) & <FILE TO REPLACE> & Chr(34)
p0.StartInfo.FileName = "Rar.exe"
p0.StartInfo.Arguments = createo
p0.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
p0.Start()
Example for the string
createo = "-p" & TB_BIGKEY.Text & " u -ep " & Chr(34) & Form1.MAINDIR & "Users\" & TB_ID.Text & ".rar" & Chr(34) & " " & Chr(34) & Form1.MAINDIR & "Users\" & TB_ID.Text & ".txt" & Chr(34)
Which is read out 'tostring' as
-ppassyword u -ep "F:\Projects\PG\PG\bin\Debug\Users\Username.rar" "F:\Projects\PG\PG\bin\Debug\Users\Username.txt"
or <PASSWORD> <UPDATE> <EXLUDE PATHS> <RAR TO UPDATE> <FILE TO UPDATE WITH>
To not use a password, just remove the -ppassyword part.

Winform not closing Why?

I have some code to save a log in my FormClosing event that was working ok until I add code to create a Directory if it not exist such directory.
Now if I add the commented lines the application doesn't close.
I don't understand why.
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
TmrReporte.Stop()
WriteRTBLog("Finalizacion del programa. - Version " & Me.ProductVersion, Color.Blue)
Dim Fecha As String
Fecha = Now.ToShortDateString & "-" & Now.ToLongTimeString
Fecha = Fecha.Replace("/", "")
Fecha = Fecha.Replace(":", "")
Dim PathArchivo As String = Application.StartupPath & "\Logs\" & Fecha & ".logout"
'If (Not System.IO.Directory.Exists(PathArchivo)) Then
' System.IO.Directory.CreateDirectory(PathArchivo)
'End If
RTB_Log.SaveFile(PathArchivo, System.Windows.Forms.RichTextBoxStreamType.RichText)
End Sub
The problem is with the string format of the directory, you use PathArchivo for both the directory and the file while you actually only need to create the directory without filename for the directory creation:
Dim PathDir As String = Application.StartupPath & "\Logs" 'use only directory string here
Dim PathArchivo As String = Application.StartupPath & "\Logs\" & Fecha & ".logout" 'note that this is file name with .logout extension
If (Not System.IO.Directory.Exists(PathDir)) Then 'creates directory without .logout
System.IO.Directory.CreateDirectory(PathDir)
End If
RTB_Log.SaveFile(PathArchivo, System.Windows.Forms.RichTextBoxStreamType.RichText)
Note that your PathArchivo is a file path with logout extension

VB.NET Parameter is not valid

I have used dotnetbar devcomponents advanced treeview to create multiple directory trees for one of my projects. Functionality wise, everything is working fine.
I have now added images to the directory file nodes (e.g. pdf image if its a pdf file) and published the application. The application runs without any errors first time on any machine, but once I close this File Management form (I have a control panel form with buttons that is the initial startup form. The buttons take me to other forms. On button click, it hides the control panel and displays the corresponding form through showdialog - File Management form is one of those buttons) and reopen it again - I get the following error:
parameter_is_not_valid
It then fails to load the nodes and after a couple of tries, Microsoft .Net Framework window appears and ends the application.
I get the images from my resource file. Please see the code for LoadAllSubDirectoriesFiles where the error occurs:
Private Sub LoadAllSubDirectoriesFiles(ByVal uParent As DevComponents.AdvTree.Node)
' Initialise Error Checking
Dim uStackframe As New Diagnostics.StackFrame
Dim ufile As IO.FileInfo = Nothing
Try
If uParent.Name.Length <> 248 Then
Dim files As IO.FileInfo() = uParent.Tag.GetFiles()
For Each file As IO.FileInfo In files
If (Not file.Attributes.ToString.Contains("Hidden")) Then
Dim uNode As DevComponents.AdvTree.Node = New DevComponents.AdvTree.Node()
uNode.Tag = file
uNode.Name = file.FullName.ToLower
uNode.Text = file.Name
If file.Extension = ".msg" Then
uNode.Image = My.Resources.Resources.Mail3
ElseIf file.Extension = ".txt" Then
uNode.Image = My.Resources.Resources.Document
ElseIf file.Extension = ".pdf" Then
uNode.Image = My.Resources.Resources.pdf
ElseIf file.Extension = ".doc" OrElse file.Extension = ".docx" Then
uNode.Image = My.Resources.Resources.doc
ElseIf file.Extension = ".xlsx" Then
uNode.Image = My.Resources.Resources.excel
ElseIf file.Extension = ".pub" Then
uNode.Image = My.Resources.Resources.publisher
ElseIf file.Extension = ".pptx" Then
uNode.Image = My.Resources.Resources.powerpoint
ElseIf file.Extension = ".bmp" OrElse file.Extension = ".png" OrElse file.Extension = ".jpg" OrElse file.Extension = ".gif" OrElse file.Extension = ".tif" Then
uNode.Image = My.Resources.Resources.bitmap_image
ElseIf file.Extension = ".zip" OrElse file.Extension = ".rar" Then
uNode.Image = My.Resources.Resources.zip
Else
uNode.Image = My.Resources.Resources.unknown
End If
uNode.DragDropEnabled = True
uParent.Nodes.Add(uNode)
End If
Next
End If
Catch ex As Exception
' Catch Error
If Err.Number <> 0 Then
WriteAuditLogRecord(uStackframe.GetMethod.DeclaringType.FullName, uStackframe.GetMethod.Name.ToString, "Error", ex.Message & vbCrLf & vbCrLf & ex.StackTrace, 0)
MsgBox("System Error Ref: " & sAuditID & vbCrLf & uStackframe.GetMethod.DeclaringType.FullName & " / " & uStackframe.GetMethod.Name.ToString & vbCrLf & ex.Message & vbCrLf & vbCrLf & ex.StackTrace & Chr(13) & sErrDescription & vbCrLf & vbCrLf & "Press Control + C to copy this error report", MsgBoxStyle.Exclamation + MsgBoxStyle.OkOnly, "Business Management System - Unexepected Error Ref: " & sAuditID)
End If
Finally
' CleanUp
End Try
End Sub
I have spent 2 days now trying to figure out the cause and fix for this problem. There were posts that talked about the image being disposed and not being able to retrieve the image reference [ http://blog.lavablast.com/post/2007/11/29/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx ] , cloning the image before disposing etc.
I have given disposing and cloning a go, but the error still stands. Been trying couple of other things, but still unsuccessful.
Any suggestions to what is wrong?
EDIT 1
Before closing the form, I clear all the treenodes and then use Me.Close()
Private Sub tsbClose_Click(sender As Object, e As EventArgs) Handles tsbClose.Click
atRootFolder.Nodes.Clear()
atAllDirectories.Nodes.Clear()
atScannedFiles.Nodes.Clear()
atFiles.Nodes.Clear()
atInbox.Nodes.Clear()
atSent.Nodes.Clear()
Me.Close()
End Sub
EDIT 2
My treeviews have hundreds of nodes, child nodes etc. Please see the image of my File Management form ( this is the first time it was loaded, no errors) I had to hide the text due to client confidentiality, but I hope it makes sense. Each image is a node.
imgur.com/QQ2FzFV
I had tried to use GC.Collect to see if it works, and surprising it did. Sadly it worked on one machine and didn't in another. Therefore, instead of calling images directly from my resources, I have stored all required images in an image list which I have attached to my treeviews. It's working like a charm.

Getting BC31019 excepetion while compiling vb.net at runtime on Windows 10

we are generating a mass of documents very dynamically. Therefore we concatenate source code and build a dll at runtime. This is running since windows XP.
Now we are in tests of windows 10 and it fails compiling this dll with the error "BC31019: Unable to write to output file 'C:\Users[name]AppData\Local\Temp\xyz.dll': The specified image file did not contain a resource section"
For testing purposes we remove all generated source code and replace it by a rudimental class with only one function (throwing an exception with specified text) and no referenced assemblies.
This is also running on all machines except windows 10. Same error.
Can anybody guess why?
This is the rudimental method
Public Sub Compile()
Dim lSourceCode = "Namespace DynamicOutput" & vbCrLf &
" Public Class Template" & vbCrLf &
" Sub New()" & vbCrLf &
" End Sub" & vbCrLf &
" Public Sub Generate(ByVal spoolJob As Object, ByVal print As Object)" & vbCrLf &
" Throw New System.Exception(""Generate reached"")" & vbCrLf &
" End Sub" & vbCrLf &
"" & vbCrLf &
" End Class" & vbCrLf &
"End Namespace"
Dim lParams As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters
lParams.CompilerOptions = "/target:library /rootnamespace:CompanyName /d:TRACE=TRUE /optimize "
lParams.IncludeDebugInformation = True
lParams.GenerateExecutable = False
lParams.TreatWarningsAsErrors = False
lParams.GenerateInMemory = True
Dim lProviderOptions As New Dictionary(Of String, String) From {{"CompilerVersion", "v4.0"}}
Dim lResult As CodeDom.Compiler.CompilerResults = Nothing
Using provider As New VBCodeProvider(lProviderOptions)
lResult = provider.CompileAssemblyFromSource(lParams, lSourceCode)
End Using
' ... check for errors
Dim lInstance As Object = lResult.CompiledAssembly.CreateInstance("CompanyName.DynamicOutput.Template")
lInstance.GetType.GetMethod("Generate").Invoke(lInstance, New Object() {Me.SpoolJob, Me.Print})
End Sub

Executing msg.exe from Visual Basic application

I am trying to take text fields for old hostname, new hostname, username, and password and remotely change computer names. That part is working fantastic. It was all great until my manager saw it in action, since we have a policy against downloading and using freeware.
It's not freeware if I made it. Unfortunately, he sent it to my director, and know my director knows I know a little bit about Visual Basic, so he wants to loop the names from a CSV file, change the name, and send a message to the end user instructing them to save their files and reboot.
Unfortunately, net send has gone the way of XP since Vista. However, from Vista - Win8.1, there's a utility called msg.exe in C:\Windows\System32. In order to use it, the target computer has to have the registry value AllowRemoteRPC in HKLM\SYSTEM\CurrentControlSet\Control\Terminal Services set to 1.
So here's what the app does:
Reads the DWORD key AllowRemoteRPC and stores it to a variable (MyVal), changes the key to 1, attempts to send the message alerting the user they need to restart, changes the key back to MyVal, and then executes netdom renamecomputer and renames the PC. Everything works perfectly EXCEPT sending the message. I can open up a command prompt and type:
msg /server:hostname * /v /time:3600 "my message here
And it works perfectly (after manually editing the registry key to the needed value).
However, running it from VB doesn't work. Here's what I've tried:
"msg /server:" & hostname & " * /v /time:3600 ""my message here"""
"cmd.exe /D /c msg /server:" & hostname & " * /v /time:3600 ""my message here"""
Neither seems to work. I know the registry value is being changed. I put message boxes after each step in my and refreshed the regedit to actually see the value of the DWORD key, and it is changing. Everything APPEARS to be going smoothly, the message is just not getting sent.
I do have these commands running as arguments to a function I created in order to create a process so I could output the streamreader to a listbox.
Here's my code. Please keep in mind, I'm barely over 2 months into learning visual basic, so it's probably not the prettiest code out there:
Imports System
Imports System.IO
Imports System.Diagnostics
Imports System.Security.Permissions
Imports Microsoft.Win32
Public Class applicationMain
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim oldPC As String = txtOldPC.Text
Dim newPC As String = txtNewPC.Text
Dim username As String = txtUsername.Text
Dim password As String = txtPassword.Text
If oldPC <> "" And newPC <> "" And username <> "" And password <> "" Then
Dim MyReg As Microsoft.Win32.RegistryKey = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, oldPC)
Dim MyRegKey As Microsoft.Win32.RegistryKey
Dim MyVal As String
lbOutput.Items.Clear()
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server")
MyVal = MyRegKey.GetValue("AllowRemoteRPC", RegistryValueKind.DWord)
MyRegKey.Close()
lbOutput.Items.Add("Processing registry changes...")
Try
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", &H1, RegistryValueKind.DWord)
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
lbOutput.Items.Add("Success!")
lbOutput.Items.Add("Sending message to user:")
Try
ExecuteCommand("cmd.exe", "/D /c msg /SERVER:" & oldPC & ".na.int.grp * /v /TIME:3600 ""Changes have been made by IS to your computer that require a restart. Please save your files and restart your computer to avoid service interruption.""")
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", MyVal, RegistryValueKind.DWord)
Exit Sub
End Try
lbOutput.Items.Add(" Message: ""Changes have been made by IS to your computer that require a restart. Please save your files and restart your computer to avoid service interruption."" ")
lbOutput.Items.Add("Reverting registry changes...")
Try
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", MyVal, RegistryValueKind.DWord)
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
Try
ExecuteCommand("netdom", "renamecomputer " & oldPC & " /newname:" & newPC & " /userD:na\" & username & " /passwordd:" & password & " /usero:na\" & username & " /passwordo:" & password & " /Force")
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
lbOutput.Items.Add("Success!")
lbOutput.Items.Add("")
lbOutput.Items.Add("Rename successful for " & oldPC & "!")
lbOutput.Items.Add("******************************************************************")
lbOutput.Items.Add("")
End If
End Sub
Private Function ExecuteCommand(ByVal cmd As String, ByVal arguments As String)
Dim cmdProcess As New Process()
Dim cmdProcessStartInfo As New ProcessStartInfo()
Dim cmdStreamReader As IO.StreamReader
Dim output As String
cmdProcessStartInfo.UseShellExecute = False
cmdProcessStartInfo.CreateNoWindow = True
cmdProcessStartInfo.RedirectStandardOutput = True
cmdProcessStartInfo.FileName = cmd
cmdProcessStartInfo.Arguments = arguments
cmdProcess.StartInfo = cmdProcessStartInfo
cmdProcess.Start()
cmdStreamReader = cmdProcess.StandardOutput
Do While cmdStreamReader.EndOfStream = False
output = cmdStreamReader.ReadLine()
lbOutput.SelectedIndex = lbOutput.Items.Count - 1
lbOutput.Items.Add(output)
Loop
cmdProcess.WaitForExit()
cmdProcess.Close()
Return vbNull
End Function
End Class
What do you know. There's actually nothing wrong with my code at all. While trying to play around with the paths variable, I decided "Fuhgeddaboudit, I'll just add the executable to the project!". Right clicked the project, Add -> Existing Item. Selected Executable as the type, and went to C:\Windows\System32 and, get this now, msg.exe wasn't there. At all. Opened Explorer and went to System32, msg.exe was there. For whatever reason, Visual Studio cannot see the program at all. Which is in and of itself weird.
So I copied msg.exe to my desktop, added it to source, the program works like a charm now.