vb.net How to declare thread and call functions with it - vb.net

I'm trying to use a thread to translate every text found in the Windows Forms to make my system multi-language.
I have a separate class named 'Language' with a sub and a function, sub reads a language source file, and function translates by receiving and returning a string.
Then I have my first Windows Form where I declare my thread:
Dim ThreadTraductor As New Thread(AddressOf ...) 'don't know how to do it
Dim cultureInfo As New System.Globalization.CultureInfo(ConfigurationManager.AppSettings('en').ToString)
ThreadTraductor.CurrentCulture = cultureInfo
ThreadTraductor.CurrentUICulture = cultureInfo
Basically I'm creating this thread to have a background process translating every Windows Form that's opened during execution, problem is I don't know how to declare it properly since I don't want to include any parameter when declaring, but I want the thread to be called from different Forms with parameters to translate, and also I want the thread to use my translate method inside Language class, is that possible? How?
Please assist, I haven't use threads before.

Public Class Lenguaje 'Class used to read language source file and translate strings
Public dicIdioma As New Dictionary(Of String, String)
Public Sub LeerArchivo(ByVal Culture As String)
Dim vectorAux() As String
dicIdioma.Clear()
Try
Dim LectorArchivo As New StreamReader("C:\Users\Joaqo\Desktop\Dorian VB\DorianBdBv1.0\UI\bin\Debug\" + Culture + ".txt")
Dim line As String
While Not LectorArchivo.Peek = -1
line = LectorArchivo.ReadLine()
vectorAux = line.Split(":")
dicIdioma.Add(vectorAux(0), vectorAux(1))
End While
Catch ex As System.IO.FileNotFoundException
MessageBox.Show("No se encuentra el archivo de idioma.")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Public Function Traducir(ByRef frase As String) As String
Dim StringAux As String
For Each Item As String In dicIdioma.Keys
If Item = Char.ToLower(frase(0)) & frase.Substring(1) Then
StringAux = Char.ToUpper(dicIdioma.Item(Item)(0)) & dicIdioma.Item(Item).Substring(1)
frase = StringAux.Replace("_", " ")
ElseIf Item.Replace("_", " ") = Char.ToLower(frase(0)) & frase.Substring(1) Then
StringAux = Char.ToUpper(dicIdioma.Item(Item)(0)) & dicIdioma.Item(Item).Substring(1)
frase = StringAux.Replace("_", " ")
End If
Next
Return frase
End Function
End Class
Then I iterate every text object in my Windows Forms to translate them:
For Each Item As Label In Me.Controls.OfType(Of Label)()
Item.Text = Traductor.Traducir(Item.Text)
Next
For Each Item As Button In Me.Controls.OfType(Of Button)()
Item.Text = Traductor.Traducir(Item.Text)
Next
And it works just fine, but I'd be calling Traductor, Lenguaje's instance declared on my first interface, from the whole app, isn't that wrong somehow?
I was told that I should use Culture and CultureUI for this, but I'm not familiarized with that. What do you think? Sorry if I'm missing something, it's my first question here.

Related

Call Function when User Types Certain Keyword

Okay, so I am working on a small scripting language using a VB Console Application.
I want the user to input "say('something')" and it calls the function I made named "say", is there a way to call the function and still use the following code:
Module Module1
Sub say(sayline)
Console.WriteLine(sayline)
End Sub
Sub Main()
Dim cmd As String
Console.WriteLine(">")
Do
Console.Write("")
cmd = Console.ReadLine()
If cmd IsNot Nothing Then cmd
Loop While cmd IsNot Nothing
End Sub
End Module
No, you cannot just call a method from user's string. You need to interpret the entered data.
First, you need to split your method name and arguments so that entered "say('something')" will transform to say and something. Remember that user can enter wrong data and you need to check if this call is correct - it's all about syntactic and lexical analysis. I hope you understand how to do this because it is pretty difficult.
Then, you need to check if you have a method called say. In case of plain and simple structure, switch construction will be enough. If your have such method, then pass something argument to this method. Else, output something like "unknown method".
If you wanted to call the method say upon typing the word say(something) and display the word something, then you can just have a certain condition that if the user types the word say within the input then call say method else, do whatever you want to do under else portion. Parse the input and omit the word say from the input and display it then.
You can have your code this way for example. (I just copied your code and added some codes to meet what you wanted... in my understanding)
Module Module1
Sub say(ByVal sayline)
Console.WriteLine(sayline)
End Sub
Sub Main()
Dim cmd As String
Do
Console.Write("> ")
cmd = Console.ReadLine()
Try
If cmd IsNot Nothing And cmd.Substring(0, 3).ToUpper().Equals("SAY") Then
say(parseInput(cmd))
End If
Catch ex As Exception
Console.WriteLine("message here")
End Try
Loop While cmd IsNot Nothing
End Sub
Function parseInput(ByVal cmd As String) As String
Dim input As String = ""
For index As Integer = 3 To cmd.Length - 1
If Char.IsLetter(cmd) Then
input += cmd.Substring(index, 1)
Else
input = input
End If
Next
Return input
End Function
End Module

VB.net Print to textbox from another thread

I have the following code and I am wanting to basically replicate the content of an ever changing text file and dump it into a text box display, I have the following code but it's not working at the moment.
If Not File.Exists(masterPath) Then
File.Create(masterPath).Dispose()
End If
Try
reader = New StreamReader(chatlog)
Catch
File.Create(chatlog)
bool = False
End Try
If bool Then
'Dim writer As New StreamWriter(masterPath)
Dim text As String
Do Until reader.EndOfStream
text = reader.ReadLine()
logMenu.AppendText(text & Environment.NewLine)
Loop
reader.Close()
File.Delete(chatlog)
File.Create(chatlog).Dispose()
End If
Thread.Sleep(1000)
Loop
Create a new method that uses Invoke as needed, like this:
Private Sub DisplayLogLine(ByVal text As String)
If logMenu.InvokeRequired Then
logMenu.Invoke(AddressOf DisplayLogLine, {text})
Return
End If
logMenu.AppendText(text & Environment.NewLine)
End Sub
Then call it with DisplayLogLine(reader.ReadLine()) in the loop.
Answer based on quick referencing Modifying the properties of controls from another thread in VB.net; it's been a while since I wrote multithreaded UI code in .NET.

VB.Net Threading and Saving Results

I'm working on the program for work, where the user is able to search AD for a asset tag of a certain computer. If it is found it will give them a list in a listbox. I have all of that working, but when they do the search the UI freezes. I'm new to VB and OO for that matter. I understand that it is freezing because the search is running on the same thread as the UI, but I cannot for the life of me get another thread to do the work. When I tried to do the search in another thread I can't update the listbox because its not on the same thread. Any help would be greatly appreciated.
Function that searches AD:
Private Function searchAd()
'clear the results from previous entries
' AdResultListBox.Items.Clear()
Try
Dim rootEntry As New DirectoryEntry("GC://mydomaininfo")
Dim searcher As New DirectorySearcher(rootEntry)
'selects the Computer Name property
searcher.PropertiesToLoad.Add("cn")
Dim compname As String = PropertyTagTextbox.Text
'searches using wildcards
compname = "*" + compname + "*"
searcher.Filter = "(&(name=" + compname + ")(objectcategory=moreADinformation))"
Dim results As SearchResultCollection
results = searcher.FindAll()
Dim result As SearchResult
For Each result In results
'this is the part i'm having trouble with
Me.AdResultListBox.Items.Add(result.Properties("cn")(0)
Next
Catch ex As Exception
End Try
End Function
Private Sub ADSearchButton_Click(sender As Object, e As RoutedEventArgs) Handles ADSearchButton.Click
AdResultListBox.Items.Clear()
'create the new thread for searching
Dim SearchThread As New Thread(AddressOf searchAd)
SearchThread.Start()
End Sub
There happens to be an MSDN article "Using System.DirectoryServices to Search the Active Directory" which shows running it in another thread at http://msdn.microsoft.com/en-us/library/ms973834.aspx#dotnetadsearch_topic9.
This is how I typically do it. The Invoke function is part of the control and that passes a delegate to the UI thread so it can be processed in the correct thread.
Invoke(Sub
Me.AdResultListBox.Items.Add(result.Properties("cn")(0)
End Sub)
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

VB.Net Sockets Invoke

I am using vb.net 2010 and I have created a program that uses sockets to transfer data between our windows server and a unix server. The code was originally from a Microsoft sample project hence my little understanding of it.
Everything was fine until I had the idea of changing the program into a service. The Invoke command is not accessable from a service. I think I understand why but more importantly how do I get around it or fix it?
' need to call Invoke before can update UI elements
Dim args As Object() = {command, data}
Invoke(_processInStream, args)
Someone please help I am desperate to finish this program so I can move on :)
Below is the rest of the class, there is a server socket class too but I didnt want to complicate things?
Public Class srvMain
' start the InStream code to receive data control.Invoke callback, used to process the socket notification event on the GUI's thread
Delegate Sub ProcessSocketCommandHandler(ByVal command As NotifyCommandIn, ByVal data As Object)
Dim _processInStream As ProcessSocketCommandHandler
' network communication
Dim WithEvents _serverPRC As New ServerSocket
Dim _encryptDataIn() As Byte
Dim myConn As SqlConnection
Dim _strsql As String = String.Empty
Protected Overrides Sub OnStart(ByVal args() As String)
' watch for filesystem changes in 'FTP Files' folder
Watch()
' hookup Invoke callback
_processInStream = New ProcessSocketCommandHandler(AddressOf ProcessSocketCommandIn)
' listen for Ultimate sending signatures
_serverPRC.Start(My.Settings.listen_port_prc)
myConn = New SqlConnection(My.Settings.Mill_SQL_Connect)
End Sub
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.
End Sub
' this is where we will break the data down into arrays
Private Sub processDataIn(ByVal data As Object)
Try
If data Is Nothing Then
Throw New Exception("Stream empty!")
End If
Dim encdata As String
' decode to string and perform split(multi chars not supported)
encdata = Encoding.Default.GetString(data)
_strsql = encdata
myConn.Open()
Dim commPrice As New SqlCommand(_strsql, myConn)
Dim resPrice As SqlDataReader = commPrice.ExecuteReader
'********************************THIS MUST BE DYNAMIC FOR MORE THAN ONE NATIONAL
If resPrice.Read = True And resPrice("ats" & "_price") IsNot DBNull.Value Then
'If resPrice("ats" & "_price") Is DBNull.Value Then
' cannot find price so error
'natPrice = ""
'natAllow = 2
'End If
natPrice = resPrice("ats" & "_price")
natAllow = resPrice("ats" & "_allow")
Else
' cannot find price so error
natPrice = ""
natAllow = 2
End If
myConn.Close()
' substring not found therefore must be a pricing query
'MsgBox("string: " & encdata.ToString)
'natPrice = "9.99"
Catch ex As Exception
ErrHandle("4", "Process Error: " + ex.Message + ex.Data.ToString)
Finally
myConn.Close() ' dont forget to close!
End Try
End Sub
'========================
'= ServerSocket methods =
'========================
' received a socket notification for receiving from Ultimate
Private Sub ProcessSocketCommandIn(ByVal command As NotifyCommandIn, ByVal data As Object)
' holds the status message for the command
Dim status As String = ""
Select Case command
Case NotifyCommandIn.Listen
'status = String.Format("Listening for server on {0} ...", CStr(data))
status = "Waiting..."
Case NotifyCommandIn.Connected
'status = "Connected to Ultimate" ' + CStr(data)
status = "Receiving..."
Case NotifyCommandIn.Disconnected
status = "Waiting..." ' disconnected from Ultimate now ready...
Case NotifyCommandIn.ReceivedData
' store the encrypted data then process
processDataIn(data)
End Select
End Sub
' called from socket object when a network event occurs.
Private Sub NotifyCallbackIn(ByVal command As NotifyCommandIn, ByVal data As Object) Handles _serverPRC.Notify
' need to call Invoke before can update UI elements
Dim args As Object() = {command, data}
Invoke(_processInStream, args)
End Sub
End Class
Any help is appreciated
Many thanks
Invoke is a member of System.Windows.Forms.Form, and it is used to make sure that a certain method is invoked on the UI thread. This is a necessity in case the method in question touches UI controls.
In this case it looks like you simply can call the method directly, i.e.
instead of
Dim args As Object() = {command, data}
Invoke(_processInStream, args)
you can simply write
ProcessSocketCommandIn(command, data)
Also, in this case you can get rid of the _processInStream delegate instance.

Coderush plugin not generating correct try catch end try block

We've created a little plugin to add a block of xml comment and create a try-catch to a function. (we simply add this to each and every function we write)
But with the latest devexpress update I'm having a problem with the following code.
Private Sub cpAddComment_Apply(ByVal sender As System.Object, ByVal ea As DevExpress.CodeRush.Core.ApplyContentEventArgs) Handles cpAddXMLCommentAndTryCatch.Apply
' create elementbuilder and add current code to it
Dim objMethod As New Method
objMethod = objOldMethod.Clone()
objElementBuilder.AddStatement(Nothing, objMethod)
' add try
Dim objTry As DevExpress.CodeRush.StructuralParser.Try = objElementBuilder.AddTry(objMethod)
Dim objCatch As DevExpress.CodeRush.StructuralParser.Catch = objElementBuilder.AddCatch(objMethod, "Exception", "ex")
' add exception
Dim strErrorString As String = """Error in " + objMethod.Location + """, ex"
Dim objThrow As New DevExpress.CodeRush.StructuralParser.Throw
Dim objException As New DevExpress.CodeRush.StructuralParser.TypeReferenceExpression("Exception")
Dim objExceptionString As New DevExpress.CodeRush.StructuralParser.PrimitiveExpression(strErrorString)
Dim objNewException As New DevExpress.CodeRush.StructuralParser.ObjectCreationExpression(objException)
objNewException.AddArgument(objExceptionString)
objThrow.Expression = objNewException
'objThrow.AddFooter(" ") 'This isnt working either
objElementBuilder.AddThrow(objCatch, objThrow)
' substitute code
Dim newCode As String = objElementBuilder.GenerateCode()
ea.TextDocument.Replace(objOldMethod.Range, newCode, "Update Method", True)
end sub
Instead of generating a correct Try-catch block it generates the following incorrect code:
Try
Catch ex As Exception
Throw New Exception("Error in test", ex)End Try
Strangely enough the following code seems to work(its about the same code but then for event handlers to show a messagebox instead of an exception)
If not CodeRush.Language.ActiveExtension.DotNetLanguageType = DotNetLanguageType.CSharp Then
Dim objExceptionString As New DevExpress.CodeRush.StructuralParser.PrimitiveExpression("Messagebox.Show(" + strErrorString + ")" + vbCrLf)
objElementBuilder.AddStatement(objCatch, objExceptionString)
Else
This problem exists in Vb.Net but in C# the brackets are correctly placed.
I have reproduced your issue and registered it in DevExpress Support Center. You are welcome to track its status here. Once it is fixed, you can request a build containing the fix from the Support Team at support # devexpress.com. For now, as a work-around, you can replace this line of code:
objThrow.Expression = objNewException
into this:
objThrow.Expression = New SnippetExpression(CodeRush.Language.GenerateExpressionCode(objNewException) + vbCrLf)
This will generate the try/catch block correctly in Visual Basic.