Receiving System.NotSupportedException when trying to make a string ProperCase (VB) - vba

Private Sub btnNewStudent_Click(sender As Object, e As EventArgs) Handles btnNewStudent.Click
Dim name As String = InputBox("Enter the Student's Name", "Name", "Student Name")
name = StrConv(name, vbProperCase)
addStudent(name)
If name = "" Then
errorMessage("Please Enter a Name")
lstStudents.Items.Remove("")
End If
End Sub
Error Description:
"System.NotSupportedException: No data is available for encoding
1252. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
Error Details:
System.NotSupportedException HResult=0x80131515 Message=No data
is available for encoding 1252. For information on defining a custom
encoding, see the documentation for the Encoding.RegisterProvider
method. Source=Microsoft.VisualBasic.Core StackTrace: at
Microsoft.VisualBasic.Strings.StrConv(String str, VbStrConv
Conversion, Int32 LocaleID) at
StudentTrackerVB.frmStudentTrackers.btnNewStudent_Click(Object sender,
EventArgs e) in E:\College\Year 2\Unit 15 - Object Oriented
Programming\Assignment
3\StudentTrackerVB\StudentTrackerVB\Form1.vb:line 11 at
System.Windows.Forms.Control.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at
System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks) at
System.Windows.Forms.Control.WndProc(Message& m) at
System.Windows.Forms.ButtonBase.WndProc(Message& m) at
System.Windows.Forms.Button.WndProc(Message& m) at
System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, WM msg,
IntPtr wparam, IntPtr lparam)
When I try to make name into ProperCase, it comes up with an error. I've done a similar thing for items in an array making them UpperCase which works perfectly. But for some reason, this doesn't?
What am I doing wrong xD

Try using Globalization
Dim ti As Globalization.TextInfo = Globalization.CultureInfo.CurrentCulture.TextInfo
name = ti.ToTitleCase(name)
Changing Case

Related

VB.NET Copying myself and then run the copy fails

I'm trying to make it possible to run my project, copy itself to update.exe and then run that update.exe for the purpose of testing the update routine.
The problem I'm having is that the exefile is copied succesfully but when update.exe is then starts, it just always crashes.
If I abort the update.exe program from the crash, but my main exe still runs, I can then just start update.exe from explorer and all works fine. I can't for life figure out why update.exe crashes if it is started after it was copied from another exefile.
Here's the code:
Public Class Updater
Public sFullname As String
Public sExename As String
Public sArguments As String
Public Sub New()
'Constructor
Me.Initiate()
Me.FakeUpdate()
Me.DoUpdate()
'MsgBox(Me.sFullname)
End Sub
Private Sub Initiate()
Dim sCmdLine As String = Environment.CommandLine()
Dim iPos = sCmdLine.IndexOf("""", 2)
Me.sFullname = sCmdLine.Substring(1, iPos - 1).Trim()
Dim iPos2 = sFullname.LastIndexOf("\")
Me.sExename = sFullname.Substring(iPos2 + 1).Trim()
Me.sArguments = sCmdLine.Substring(iPos + 1).Trim()
End Sub
Private Sub FakeUpdate()
'If we start the app with -fakeupdate parameter, copy myself to update.exe, then run update.exe to debug the update process.
If Me.sArguments = "-fakeupdate" Then
FileCopy(Me.sFullname, "update.exe")
Shell("update.exe")
End If
End Sub
Private Sub DoUpdate()
If Me.sExename = "update.exe" Then
MsgBox("DoUpdate called from update.exe")
End If
End Sub
End Class
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim Updater As New Updater
End Sub
End Class
The project is configured that it runs with parameter -fakeupdate
The code is part of a larger project, but I have commented out all other code and still receive this error.
The error I'm getting from update.exe: Length cannot be less than null. Parametername: length
System.ArgumentOutOfRangeException: Length cannot be less than null.
Parameternaam: length
bij System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
bij Todo_List.Updater.Initiate() in S:\VB Projects\Todo List\Todo List\Form1.vb:regel 19
bij Todo_List.Updater..ctor() in S:\VB Projects\Todo List\Todo List\Form1.vb:regel 8
bij Todo_List.Form1.Form1_Load(Object sender, EventArgs e) in S:\VB Projects\Todo List\Todo List\Form1.vb:regel 594
bij System.EventHandler.Invoke(Object sender, EventArgs e)
bij System.Windows.Forms.Form.OnLoad(EventArgs e)
bij System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
bij System.Windows.Forms.Control.CreateControl()
bij System.Windows.Forms.Control.WmShowWindow(Message& m)
bij System.Windows.Forms.Control.WndProc(Message& m)
bij System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bij System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
EDIT: small update, it also goes wrong if I don't even copy the file. Just shell("update.exe") goes wrong. I even created a button on the form to launch it upon click and it fails every time. But if I run it from explorer, all is fine.
This is weird behavior, possibly even a bug, but I figured it out.
Apparently, if you use shell ("program.exe") to start a program, and from within that program, you call Environment.CommandLine() it will just be program.exe, whereas if you doubleclick the program from explorer it will be C:\MyPath\program.exe instead.
In order to solve it, I had to change my code as follows:
Private Sub FakeUpdate()
Dim sShell As String
'If we start the app with -fakeupdate parameter, copy myself to update.exe, then run update.exe to debug the update process.
If Me.sArguments = "-fakeupdate" Then
FileCopy(Me.sFullname, "update.exe")
sShell = My.Computer.FileSystem.CurrentDirectory & "\update.exe"
Shell(sShell)
End If
End Sub
Now it works correctly, both from explorer AND from launching the program from within the program.

Catching a framework exception

I'm having some trouble catching and handling an exception.
My (simplified) application has a picturebox which shows a live video feed from a connected webcam. I'm using the Metrilius Metricam SDK (http://www.metrilus.de/blog/portfolio-items/metricam/) to connect to the webcam.
Using a backgroundworker, I am calling the camera.update function, grabbing the bitmap and setting the picturebox to it. Whenever the user hits Enter, the current frame is grabbed and stored.
As mentioned earlier, an exception is thrown at completely random points in time when the picturebox is being updated with the latest bmp from the camera. As you can see in the code below, I have wrapped the assignment in a try/catch block but it isn't catching it. What could I do to handle this gracefully? The exception draws a big red X on the picturebox and the program has to be closed and restarted.
The picturebox's sizemode property is set to Zoom.
Code below:
Private Sub BG1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BG1.DoWork
While Not BG1.CancellationPending
If pauseCamUpdate = False Then 'PausecamUpdate is a flag that is set to False during calls to store the current frame
i += 1
If i Mod 2 = 0 Then Continue While 'Dropping every nth frame to make the update smoother
If i > 10000 Then
i = 0
End If
Try
activeCam.Update()
pictPhoto.Image = CType(CType(activeCam, WebCam).CalcBitmap(), Bitmap)
'pictPhoto.Invalidate()
Application.DoEvents()
Catch exp As Exception
End Try
End If
End While
End Sub
The exception text minus the loaded assemblies:
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
**System.InvalidOperationException: Object is currently in use elsewhere.**
at System.Drawing.Image.get_Height()
at System.Drawing.Image.get_Size()
at
System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,
Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr
wparam, IntPtr lparam)
Thank you for any assistance.

naudio not releasing file after dispose vb.net, It's really an declaration issue I think

I only post here when I'm really stuck, so here goes.
I'm creating a program where I can edit the metadata of MP3 files (with all data pulled from a mysql db), using taglib-sharp.
If I preview an audio file using naudio, I can hear the audio no problems and I can stop it, so that is all good.
For the sake of what is happening in my code, It's a matter of choosing a file from a listbox, and then I push a 'play' button to start, and another button to stop. My error is showing up with a right click context menu when I'm trying to save metadata.
The problem is when I go to edit the metadata of that same file I just played, the error appears - as per this shown in the following example of code. When I try and call the mp3.save() line, I receive the following error:
************** Exception Text **************
System.IO.IOException: The process cannot access the file
'C:\temp\test.mp3' because it is being used by another process. at
System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess
access, Int32 rights, Boolean useRights, FileShare share, Int32
bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String
msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess
access, FileShare share) at
TagLib.File.LocalFileAbstraction.get_WriteStream() at
TagLib.File.set_Mode(AccessMode value) at
TagLib.NonContainer.File.Save() at
LinersDB_META.Form1.menuChoice(Object sender, EventArgs e) in
C:\Users\smonro\source\repos\WindowsApp1\WindowsApp1\Form1.vb:line
2281 at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key,
EventArgs e) at
System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e) at
System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) at
System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) at
System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks) at
System.Windows.Forms.Control.WndProc(Message& m) at
System.Windows.Forms.ToolStrip.WndProc(Message& m) at
System.Windows.Forms.ToolStripDropDown.WndProc(Message& m) at
System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)
etc
I know why it's happening, but I'm lost as to how to solve it.
According to this page, (which is in C#) I need to release the "Mp3FileReader".
In my case, it would be "data" - this:
Dim data As New NAudio.Wave.Mp3FileReader(file)
The problem is, it's in a private sub, as a private variable.
However, I'm struggling to see how I can make this declaration public, when I need to have file also declared, but it would also need to be known too, and reinitialized every time I choose a different audio file.
Any thoughts?
Should I just try and rearrange my program to work differently? Thanks in advance.
'...
Imports System.IO 'File Operations
Imports TagLib ' Tagging
Imports NAudio
'...
'Wave out device for playing the sound
Public Shared Wave1 As New NAudio.Wave.WaveOut 'Wave out device for playing the sound
Public Sub start_audio()
Dim file As String = "C:\test\test.mp3"
If IO.File.Exists(file) Then
Dim data As New NAudio.Wave.Mp3FileReader(file)
Wave1.Init(data)
Wave1.Play()
End If
End Sub
Public Sub Button5_Click_1(sender As Object, e As EventArgs) Handles Button5.Click
Wave1.Stop()
End Sub
Public Sub menuChoice(ByVal sender As Object, ByVal e As EventArgs)
Dim item = CType(sender, ToolStripMenuItem)
Dim selection = CInt(item.Tag)
Select Case selection
Case 1
' Remove the Artwork
'Insert Album art and save to file and dispose.
If IO.File.Exists(GLOBAL_Full_Path) Then
Wave1.Stop()
Wave1.Dispose()
System.GC.Collect()
System.GC.WaitForPendingFinalizers()
Dim mp3 As TagLib.File = TagLib.File.Create(GLOBAL_Full_Path)
' Clear the artwork from the file.. (It's a big process)
Dim pics As Picture = New Picture()
Dim picsFrame As New TagLib.Id3v2.AttachedPictureFrame(pics)
picsFrame.MimeType = System.Net.Mime.MediaTypeNames.Image.Jpeg
'set the type of picture (front cover)
picsFrame.Type = TagLib.PictureType.FrontCover
picsFrame.Description = "" ' So the Actual location of the image is not stored in the file. This would otherwise reveal internal systems to the public.
'Id3v2 allows more than one type of image, just one is needed here.
Dim pictFrames() As TagLib.IPicture = {picsFrame}
'set the pictures in the tag
mp3.Tag.Pictures = pictFrames
' ******************************************
' Error occurs here after a file has been played.
mp3.Save()
' Error occurs here
' ******************************************
mp3.Dispose()
End If
Case Else
End Select
End Sub
After #TnTinMn pointed me in the right direction, I solved the issue in the end. While this is not the full example, I've now solved this by adding and changing a couple of minor things.
Imports NAudio
' NEW/required to get the Mp3FileReader, so it can be dynamically populated.
Imports NAudio.Wave
Dim WavePlayOut As New NAudio.Wave.WaveOut 'Wave out device for playing the sound
Dim WaveFile As String = "" ' *** NEW/Declared ***
Dim WaveData As Mp3FileReader ' *** Changed ***
Public Sub start_audio()
If File_ListView.SelectedItems.Count > 0 Then
WaveFile = TxtBx_Path.Text & "\" & File_ListView.FocusedItem.Text
If WavePlayOut IsNot Nothing Then
WavePlayOut = New NAudio.Wave.WaveOut
End If
If WaveData IsNot Nothing Then
WaveData.Dispose()
WaveData = New Mp3FileReader(WaveFile)
If WaveData.Length > 1 Then
If IO.File.Exists(WaveFile) Then
WavePlayOut.Init(WaveData)
WavePlayOut.Play()
End If
End If
Else
WaveData = New Mp3FileReader(WaveFile)
If WaveData.Length > 1 Then
If IO.File.Exists(WaveFile) Then
WavePlayOut.Init(WaveData)
WavePlayOut.Play()
End If
End If
End If
End If
End Sub
To unload the audio file, use the following:
If WaveData IsNot Nothing Then
WaveData.Dispose()
End If
If WavePlayOut IsNot Nothing Then
WavePlayOut.Stop()
WavePlayOut.Dispose()
End If

Multiple Listboxes, One Selection

I have 2 List Boxes on my form, but I only want to be able to make a single selection between both, how would I go about this?
I, of course, tried doing this first...
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
ListBox2.ClearSelected()
End Sub
Private Sub ListBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox2.SelectedIndexChanged
ListBox1.ClearSelected()
End Sub
But since that causes the selected index to be changed it clears what you have just selected as well...
Thanks for any help!
You can test the reason why Selected index changed, something like that:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) {
// If listBox2 focused i.e. user clicked list box2 - do nothing:
// one should not try to clear list box2 selection
if (listBox2.Focused)
return;
listBox2.ClearSelected();
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e) {
// If list box1 is in focus that means that user just have selected itme there;
// so, do nothing: we shouldn't erase user's selection
if (listBox1.Focused)
return;
listBox1.ClearSelected();
}
First, your question is tagged as C# but the code sample is in VB.
Second, I would do it in C# as follows:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
listBox2.SelectedIndexChanged -= new System.EventHandler(this.listBox2_SelectedIndexChanged);
listBox2.ClearSelected();
listBox2.SelectedIndexChanged += new System.EventHandler(this.listBox2_SelectedIndexChanged);
}
And do the same with the other event handler.

Capturing the ctrl+V in VB.NET combobox

I am trying to remove the newline and replace with whitespace before pasting to comboBox as it ignores anything beyond a line. I am trying this:
If e.Modifiers = Keys.Control AndAlso e.KeyValue = Keys.V Then Then
Clipboard.SetText(Regex.Replace(Clipboard.GetText(TextDataFormat.UnicodeText), "\n", " "))
e.Handled = True
End If
I am performing this inside KeyDown event but it is able to capture either Ctrl or V but not both. I tried Capture CTRL+V or paste in a textbox in .NET and http://social.msdn.microsoft.com/Forums/windows/en-US/096540f4-4ad4-4d24-ae12-cfb3e1b246f3/interceptingoverriding-paste-behavior-on-combobox but no results as desired. May be there is something i am missing in my code. Please help me out.
I am getting the needed value with this Clipboard.GetText().Replace(vbCrLf, " ") when i debug but i am not able to set it. I tried using a variable to set it but even then no change. I also tried clearing the clipboard and then resetting with this variable holding the modified value.
I am using Winforms and i tried this but still no change to my clipboard:
Private Const WM_PASTE As Integer = &H302
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_PASTE Then
Dim returnText As String = Nothing
If (Clipboard.ContainsText()) Then
returnText = Clipboard.GetText().Replace(vbCrLf, " ")
Clipboard.Clear()
Clipboard.SetText(returnText)
End If
End If
MyBase.WndProc(m)
End Sub
Handling keyboard only events for intercepting pasting doesn't solve the problem, because pasting can also be done using mouse or touch interface.
Thus, if you are using WPF, then simply add the DataObject.Pasting event handler to your ComboBox, so definition of the control in XAML will look like:
<ComboBox Name="comboBox1" IsEditable="true" DataObject.Pasting="comboBox1_Pasting" ... />
And, finally, in your code handle it as (I'm adding a method here to the code-behind, which is not as nice, as using commands):
private void comboBox1_Pasting(object sender, DataObjectPastingEventArgs e)
{
// modify the clipboard content here
}
If you're using WinForms, then look here: hook on default “Paste” event of WinForms TextBox control
This piece of code worked for me:
Private Const WM_PASTE As Integer = &H302
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If keyData = (Keys.Control Or Keys.V) Or msg.Msg = WM_PASTE Then
If (Clipboard.ContainsText()) Then
Clipboard.SetText(Clipboard.GetText().Replace(vbCrLf, " "))
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Use the keydown event and alter the clipboard like this
Private Sub ComboBox1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles ComboBox1.KeyDown
If e.KeyCode = Keys.V AndAlso (e.Modifiers And Keys.Control) <> 0 Then
My.Computer.Clipboard.SetText(My.Computer.Clipboard.GetText().Replace(vbCrLf, " "))
End If
End Sub
But this example is going to alter the clipboard contents. Modify it to paste or insert yourself as you wish