My code won't work to read from a text file - vb.net

My Visual Basic code works to write to the file, but not to read from it. Reading from the file needs to be part of the splash screen, so I can't move it to the main KMFile class. Can you help me figure out what's wrong with this code?
Imports System.IO
Public Class SplashScreen1
'TODO: This form can easily be set as the splash screen for the application by going to the "Application" tab
' of the Project Designer ("Properties" under the "Project" menu).
Private Sub SplashScreen1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Set up the dialog text at runtime according to the application's assembly information.
'Open the yacht type list to read from it.
'TODO: Customize the application's assembly information in the "Application" pane of the project
' properties dialog (under the "Project" menu).
'Application title
Dim YachtTypeString As String = "YachtTypes.txt"
Try
'Open the file.
Dim YachtsListStreamReader As StreamReader = New StreamReader("YachtTypes.txt")
' Read all elements into the list.
Do Until YachtsListStreamReader.Peek = -1
YachtTypeString = YachtsListStreamReader.ReadLine()
KMFile.YachtTypeComboBox.Items.Add(YachtTypeString)
Loop
'Close the file.
YachtsListStreamReader.Close()
Catch ex As Exception
'File missing.
MessageBox.Show("The yacht types file is not found.", "Enter yacht types manually to save", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Try
If My.Application.Info.Title <> "" Then
ApplicationTitle.Text = My.Application.Info.Title
Else
'If the application title is missing, use the application name, without the extension
ApplicationTitle.Text = System.IO.Path.GetFileNameWithoutExtension(My.Application.Info.AssemblyName)
End If
'Format the version information using the text set into the Version control at design time as the
' formatting string. This allows for effective localization if desired.
' Build and revision information could be included by using the following code and changing the
' Version control's designtime text to "Version {0}.{1:00}.{2}.{3}" or something similar. See
' String.Format() in Help for more information.
'
' Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor, My.Application.Info.Version.Build, My.Application.Info.Version.Revision)
Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor)
'Copyright info
Copyright.Text = My.Application.Info.Copyright
End Sub
End Class

Here:
Catch ex As Exception
'File missing.
MessageBox.Show("The yacht types file is not found.", "Enter yacht types manually to save", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Try
you swallow all exceptions and show a generic error message. Don't do that. Include ex.Message in your displayed message or only catch FileNotFoundExceptionss.
That way, you will see the real error message, leading you to the real cause of the problem you are experiencing.

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.

Startup Folder Permissions in VB.NET

I am building an app which installs all the company's bespoke software at the click of a button. Included in the list is an asset tracker/reporting tool which must run at startup for everyone. Our standard build (I have no control over this whatsoever) is Windows 10, and we also have some legacy Windows 7 machines around, but in each case the startup registry keys are locked down so I started to create shortcuts in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup.
If the startup folder doesn't exist, then it creates the folder. Logged on as local admin, I can create the startup folder manually without UAC popping up, take ownership of the folder and assign Everyone to have modify access, creating a shortcut in there. When I log off/on, the software runs. However when I code this, I get permissions errors.
Here's the code:
Sub DetectFolders()
Dim sFolder1 As String = "C:\My Apps\"
Dim sFolder2 As String = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\"
Dim sFolder3 As String = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\"
If Not Directory.Exists(sFolder1) Then
Directory.CreateDirectory(sFolder1)
End If
If Not Directory.Exists(sFolder2) Then
Try
' create folder
TakeOwnership(sFolder3)
Application.DoEvents()
AddDirectorySecurity(sFolder3, "MyDomain\" & Environment.UserName, FileSystemRights.FullControl, AccessControlType.Allow)
Application.DoEvents()
Directory.CreateDirectory(sFolder2)
Application.DoEvents()
TakeOwnership(sFolder2)
' everyone has modify access // TEST
AddDirectorySecurity(sFolder2, "Everyone", FileSystemRights.Modify, AccessControlType.Allow)
Catch ex As Exception
MessageBox.Show(ex.Message, "Config", MessageBoxButtons.OK, MessageBoxIcon.Error)
Me.Close()
End Try
End If
End Sub
Sub TakeOwnership(ByVal sfolder As String)
' take ownership
Try
Dim ds As System.Security.AccessControl.DirectorySecurity
Dim account As System.Security.Principal.NTAccount
ds = System.IO.Directory.GetAccessControl(sfolder, System.Security.AccessControl.AccessControlSections.Owner)
account = New System.Security.Principal.NTAccount(System.Security.Principal.WindowsIdentity.GetCurrent.Name)
ds.SetOwner(account)
System.IO.Directory.SetAccessControl(sfolder, ds)
Application.DoEvents()
Catch ex As Exception
MessageBox.Show("" & ex.Message & "", "Take Ownership", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Sub AddDirectorySecurity(ByVal FileName As String, ByVal Account As String, ByVal Rights As FileSystemRights, ByVal ControlType As AccessControlType)
Try
' Create a new DirectoryInfoobject.
Dim dInfo As New DirectoryInfo(FileName)
' Get a DirectorySecurity object that represents the
' current security settings.
Dim dSecurity As DirectorySecurity = dInfo.GetAccessControl()
' Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(New FileSystemAccessRule(Account, Rights, ControlType))
' Set the new access settings.
dInfo.SetAccessControl(dSecurity)
Catch ex As Exception
MessageBox.Show("" & ex.Message & "", "Add Security", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
The first two Errors that appear is: Attempted to perform an unauthorized Operation, generated from the first time that AddDirectorySecurity and TakeOwnership are called.
I then get an error which states:
Access to the path 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup' is denied.
This is generated from the directory.createdirectory line in DetectFolders sub
I'm rapidly beginning to run out of ideas to get this working. Is it something in my code? Am I missing something, or does windows 10 not work in this way. Any constructive help will be gratefully received.

" 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.

Is there a difference between MsgBox and MessageBox.Show?

Is there a difference between the following two?
msgbox()
messagebox.show()
Some tutorials use msgbox(), and some use the other, messagebox.show()---I see that both can have an editable style, but I was wondering: Why are there two?
Is it to accommodate older programmers (who have learnt on an older version of Visual Basic)?
So in that case, which one should I use in Visual Basic 2010 (Visual Studio 2010)?
MsgBox() is the same as Messagebox.Show().
It exists for VB6 programmers who are used to it.
There are no rules on which one to use, but since MsgBox simply ends up delegating to MessageBox, I personally would go directly with MessageBox.
Here is the source code for Msgbox. As you can see it doesn't do anything particularly interesting before calling MessageBox.Show.
<MethodImpl(MethodImplOptions.NoInlining), HostProtection(SecurityAction.LinkDemand, Resources:=HostProtectionResource.UI)> _
Public Shared Function MsgBox(ByVal Prompt As Object, ByVal Optional Buttons As MsgBoxStyle = 0, ByVal Optional Title As Object = new Object()) As MsgBoxResult
Dim owner As IWin32Window = Nothing
Dim text As String = Nothing
Dim titleFromAssembly As String
Dim vBHost As IVbHost = HostServices.VBHost
If (Not vBHost Is Nothing) Then
owner = vBHost.GetParentWindow
End If
If ((((Buttons And 15) > MsgBoxStyle.RetryCancel) OrElse ((Buttons And 240) > MsgBoxStyle.Information)) OrElse ((Buttons And &HF00) > MsgBoxStyle.DefaultButton3)) Then
Buttons = MsgBoxStyle.OkOnly
End If
Try
If (Not Prompt Is Nothing) Then
[text] = CStr(Conversions.ChangeType(Prompt, GetType(String)))
End If
Catch exception As StackOverflowException
Throw exception
Catch exception2 As OutOfMemoryException
Throw exception2
Catch exception3 As ThreadAbortException
Throw exception3
Catch exception9 As Exception
Throw New ArgumentException(Utils.GetResourceString("Argument_InvalidValueType2", New String() { "Prompt", "String" }))
End Try
Try
If (Title Is Nothing) Then
If (vBHost Is Nothing) Then
titleFromAssembly = Interaction.GetTitleFromAssembly(Assembly.GetCallingAssembly)
Else
titleFromAssembly = vBHost.GetWindowTitle
End If
Else
titleFromAssembly = Conversions.ToString(Title)
End If
Catch exception4 As StackOverflowException
Throw exception4
Catch exception5 As OutOfMemoryException
Throw exception5
Catch exception6 As ThreadAbortException
Throw exception6
Catch exception13 As Exception
Throw New ArgumentException(Utils.GetResourceString("Argument_InvalidValueType2", New String() { "Title", "String" }))
End Try
Return DirectCast(MessageBox.Show(owner, [text], titleFromAssembly, (DirectCast(Buttons, MessageBoxButtons) And DirectCast(15, MessageBoxButtons)), (DirectCast(Buttons, MessageBoxIcon) And DirectCast(240, MessageBoxIcon)), (DirectCast(Buttons, MessageBoxDefaultButton) And DirectCast(&HF00, MessageBoxDefaultButton)), (DirectCast(Buttons, MessageBoxOptions) And DirectCast(-4096, MessageBoxOptions))), MsgBoxResult)
End Function
There is a difference when you are attempting to mix icons with different buttons. MsgBox has predefined styles (there may be a way to create new styles).
For example:
MsgBox("Do you wish to save changes?", MsgBoxStyle.YesNoCancel, "Save Changes")
^ This will display a box with Yes, No and Cancel buttons without an icon.
MsgBox("Do you wish to save changes?", MsgBoxStyle.Question, "Save Changes")
^ This will display a box with a Question mark icon but with ONLY an OK button.
MessageBox.Show("Do you wish to save changes?", "Save Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
^ This will display a box with Yes, No and Cancel buttons AND a Question mark icon.
As you can see, using MessageBox.Show enables you to have any buttons you want with any icon.
But the really nice thing about MsgBox is that it can be SystemModal e.g. If MsgBox("There is a new Quick Message!" & Environment.NewLine & "Do you want to read it now?", MsgBoxStyle.Information + MsgBoxStyle.YesNo + MsgBoxStyle.SystemModal, "Quick Message") = MsgBoxResult.Yes Then...
I couldn't find a simple way of making If MessageBox.Show(... to be SystemModal.
My messages now get full prominence on screen. Yippee.
According to this site and the answers so far to my own question (see remark), as well my inability to display a specific help file using the msgbox function, I'd have to say use messagebox rather than msgbox if you want to show help. The msgbox function displays a help button, but apparently there is no way to put a helpfile in it! I'm showing the code I played around with below, and there is also a good code sample on the first link.
Imports Microsoft.visualbasic 'have to have this namespace to use msgbox
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Helpfilepath As String = "C:\Windows\Help\mui\0409\aclui.chm"
Dim msgresult As Byte
'BTW, Must use 0 for BLANK PARAMETER. Using messageboxoptions.defaultdesktoponly errors out with help btn.
msgresult = MessageBox.Show("Text", "Messagebox", 0, _
0, 0, 0, Helpfilepath)
'displays help button, but how do you display the help file?
msgresult = MsgBox("Text", MsgBoxStyle.MsgBoxHelp, "msgbox")
'BTW, must use dialogresult rather than messageboxresult with windows forms
If msgresult = DialogResult.Yes Then
'etc
End If
End Sub
End Class
The message box created using MsgBox() has a title of the form which created it, whereas the message box window created by MessageBox.Show() does not have any title.

How to know if MS Chart Controls are installed on client workstation?

I developed a ClickOnce application using MS Chart Controls. It works fine for the charting part.
But, as Chart Control needs to be installed beforehand (with admin rights and not with classic ClickOnce deployment), I need to detect if the component is available on the machine.
So I tried to create a new Chart and to handle the possible Exception but it seems it is not possible to catch it (too low level Exception?) :
Try
Dim oChart as New Chart
Catch
' Some user-friendly message to ask the user to contact the helpdesk
End Try
This code is never executed: I get a unhandled Exception as soon as I enter the event this code is in.
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
***** Exception Text ******* System.IO.FileNotFoundException: Could not load file or assembly
'System.Windows.Forms.DataVisualization, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its
dependencies. The system cannot find the file specified. File name:
'System.Windows.Forms.DataVisualization, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35' at
SIPReportingControl.Main.expMain_SelectedGroupChanged(Object sender,
GroupEventArgs e) at
Infragistics.Win.UltraWinExplorerBar.SelectedGroupChangedEventHandler.Invoke(Object
sender, GroupEventArgs e)
Do you have some ideas in order to:
be able to deploy MS Chart Controls with ClickOnce (I do not think it is possible).
detect if Chart Controls are installed or not.
catch this strange Exception.
Thanks in advance.
Edit
The calling method (the exception is generated even if I click in another group than Reporting):
Private Sub expMain_SelectedGroupChanged(sender As Object, e As Infragistics.Win.UltraWinExplorerBar.GroupEventArgs) Handles expMain.SelectedGroupChanged
Try
If blnDoEvent Then
CleanControls()
Select Case e.Group.Key
Case "Search"
DisplayGrid(True)
Case "AddEdit"
DisplayAddEdit(Nothing)
Case "Reporting"
Dim oChart As New Chart
End Select
End If
Catch ex As Exception
MsgBox(ex.Message & vbCrLf & ex.StackTrace)
End Try
End Sub
I have seen a interesting answer about an exception been thrown in generated MSIL code for a function call, unfortunately it has been deleted and I cannot add a comment to it.
I have understood that your code is not responsible for firing the event. I would suggest to put the whole statement in a sub and to call it enclosed by a try catch this way :
Private Sub expMain_SelectedGroupChanged(sender As Object, e As Infragistics.Win.UltraWinExplorerBar.GroupEventArgs) Handles expMain.SelectedGroupChanged
Try
RedirectTo(e.Group.Key)
Catch ex As Exception
MsgBox(ex.Message & vbCrLf & ex.StackTrace)
End Try
End Sub
Sub RedirectTo(Screen as string)
If blnDoEvent Then
CleanControls()
Select Case Screen
Case "Search"
DisplayGrid(True)
Case "AddEdit"
DisplayAddEdit(Nothing)
Case "Reporting"
Dim oChart As New Chart
End Select
End If
End Sub
Is it better ?