Methods to use the serial port in multiple forms - vb.net

I'm designing a windows userform to interact with a microcontroller through the serial port.
The GUI includes multiple userforms which will use the same serialport. I researched how to do that and I found different ideas. Some I don't know if it works the others I'm not sure how to implement it in code. Let's say I have
Form1: Start.vb
Form2: Shield1.vb
1) Can I declare the serial port in the start userform as:
Public Shared SerialPort1 As New System.IO.Ports.SerialPort
And use it in the other forms ?
2) First alternative: Use a Module to declare a new Serialport
Module Module1
Public WithEvents mySerialPort1 As New IO.Ports.SerialPort
Private Sub mySerialPort1_DataReceived(sender As Object, _
e As System.IO.Ports.SerialDataReceivedEventArgs) _
Handles mySerialPort1.DataReceived
End Sub
End Module
Is this method right? If yes How do I use it in the code of my forms ? How to include the DataReceived Event in the code of the forms ?
3) Second alternative: Constructor of the Serialport in the start form and then pass the data to the other forms as mentionned in this post: Alternate Solution 1
private void OnSetup(object sender, EventArgs e)
{
this.port = new SerialPort(...);
// TODO: initialize port
Form2 f2 = new Form2(this.port);
f2.Show();
Form3 f3 = new Form3(this.port);
f3.Show();
Form4 f4 = new Form4(this.port);
f4.Show();
}
Are then the Events also included ? How do I use them?
4) Third alternative: Use a static class like done in this solution:
Alternate Solution 2
Is the code written in C# here right ? I'm writing my programm in VB.net but I could take this as a reference.
Which is the recommended solution for a beginner ? Could you please write it in a small code if you have another suggestion or a correction ?
I apologize in advance for any ambiguity or falsly used terms.
Thanks you!

I would follow the "Singleton" design pattern, which ensures that only one instance of a class is created. Here is a well-accepted template for such a class:
Public NotInheritable Class MySerial
Private Shared ReadOnly _instance As New Lazy(Of MySerial)(Function() New
MySerial(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)
Private Sub New()
End Sub
Public Shared ReadOnly Property Instance() As MySerial
Get
Return _instance.Value
End Get
End Property
End Class
In the New() method you should set up your serial port as you need to. Then no matter where you need to use the port, you make your references to the Instance:
Dim singletonSerial As MySerial = MySerial.Instance
This is the canonical pattern to ensure that you have only one copy of an object without resorting to static classes. It's a design pattern that dates back more than 20 years and still works great when you need exactly one copy of an object.

I found this very helpful example of a sigleton C# class for serial port:
C# Singleton Example
As a beginner I used a Code converter to have it in VB.Net. Can you guys let me know if the resulting code is correct and I can use it ? Thanks a lot!!
Imports System
Imports System.IO
Imports System.IO.Ports
Imports System.Threading
Namespace HeiswayiNrird.Singleton
Public NotInheritable Class SerialPortManager
Private Shared lazy As Lazy(Of SerialPortManager) = New Lazy(Of SerialPortManager)(() => { }, New SerialPortManager)
Public Shared ReadOnly Property Instance As SerialPortManager
Get
Return lazy.Value
End Get
End Property
Private _serialPort As SerialPort
Private _readThread As Thread
Private _keepReading As Boolean
Private Sub New()
MyBase.New
Me._serialPort = New SerialPort
Me._readThread = Nothing
Me._keepReading = false
End Sub
''' <summary>
''' Update the serial port status to the event subscriber
''' </summary>
Public Event OnStatusChanged As EventHandler(Of String)
''' <summary>
''' Update received data from the serial port to the event subscriber
''' </summary>
Public Event OnDataReceived As EventHandler(Of String)
''' <summary>
''' Update TRUE/FALSE for the serial port connection to the event subscriber
''' </summary>
Public Event OnSerialPortOpened As EventHandler(Of Boolean)
''' <summary>
''' Return TRUE if the serial port is currently connected
''' </summary>
Public ReadOnly Property IsOpen As Boolean
Get
Return Me._serialPort.IsOpen
End Get
End Property
''' <summary>
''' Open the serial port connection using basic serial port settings
''' </summary>
''' <param name="portname">COM1 / COM3 / COM4 / etc.</param>
''' <param name="baudrate">0 / 100 / 300 / 600 / 1200 / 2400 / 4800 / 9600 / 14400 / 19200 / 38400 / 56000 / 57600 / 115200 / 128000 / 256000</param>
''' <param name="parity">None / Odd / Even / Mark / Space</param>
''' <param name="databits">5 / 6 / 7 / 8</param>
''' <param name="stopbits">None / One / Two / OnePointFive</param>
''' <param name="handshake">None / XOnXOff / RequestToSend / RequestToSendXOnXOff</param>
Public Sub Open(Optional ByVal portname As String = "COM1", Optional ByVal baudrate As Integer = 9600, Optional ByVal parity As Parity = Parity.None, Optional ByVal databits As Integer = 8, Optional ByVal stopbits As StopBits = StopBits.One, Optional ByVal handshake As Handshake = Handshake.None)
Me.Close
Try
Me._serialPort.PortName = portname
Me._serialPort.BaudRate = baudrate
Me._serialPort.Parity = parity
Me._serialPort.DataBits = databits
Me._serialPort.StopBits = stopbits
Me._serialPort.Handshake = handshake
Me._serialPort.ReadTimeout = 50
Me._serialPort.WriteTimeout = 50
Me._serialPort.Open
Me.StartReading
Catch As IOException
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} does not exist.", portname))
End If
Catch As UnauthorizedAccessException
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} already in use.", portname))
End If
Catch ex As Exception
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, ("Error: " + ex.Message))
End If
End Try
If Me._serialPort.IsOpen Then
Dim sb As String = StopBits.None.ToString.Substring(0, 1)
Select Case (Me._serialPort.StopBits)
Case StopBits.One
sb = "1"
Case StopBits.OnePointFive
sb = "1.5"
Case StopBits.Two
sb = "2"
End Select
Dim p As String = Me._serialPort.Parity.ToString.Substring(0, 1)
Dim hs As String = "No Handshake"
'TODO: Warning!!!, inline IF is not supported ?
(Me._serialPort.Handshake = Handshake.None)
Me._serialPort.Handshake.ToString
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Connected to {0}: {1} bps, {2}{3}{4}, {5}.", Me._serialPort.PortName, Me._serialPort.BaudRate, Me._serialPort.DataBits, p, sb, hs))
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, true)
End If
Else
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("{0} already in use.", portname))
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, false)
End If
End If
End Sub
''' <summary>
''' Close the serial port connection
''' </summary>
Public Sub Close()
Me.StopReading
Me._serialPort.Close
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, "Connection closed.")
End If
If (Not (OnSerialPortOpened) Is Nothing) Then
OnSerialPortOpened(Me, false)
End If
End Sub
''' <summary>
''' Send/write string to the serial port
''' </summary>
''' <param name="message"></param>
Public Sub SendString(ByVal message As String)
If Me._serialPort.IsOpen Then
Try
Me._serialPort.Write(message)
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Message sent: {0}", message))
End If
Catch ex As Exception
If (Not (OnStatusChanged) Is Nothing) Then
OnStatusChanged(Me, String.Format("Failed to send string: {0}", ex.Message))
End If
End Try
End If
End Sub
Private Sub StartReading()
If Not Me._keepReading Then
Me._keepReading = true
Me._readThread = New Thread(ReadPort)
Me._readThread.Start
End If
End Sub
Private Sub StopReading()
If Me._keepReading Then
Me._keepReading = false
Me._readThread.Join
Me._readThread = Nothing
End If
End Sub
Private Sub ReadPort()
While Me._keepReading
If Me._serialPort.IsOpen Then
'byte[] readBuffer = new byte[_serialPort.ReadBufferSize + 1];
Try
'int count = _serialPort.Read(readBuffer, 0, _serialPort.ReadBufferSize);
'string data = Encoding.ASCII.GetString(readBuffer, 0, count);
Dim data As String = Me._serialPort.ReadLine
If (Not (OnDataReceived) Is Nothing) Then
OnDataReceived(Me, data)
End If
Catch As TimeoutException
End Try
Else
Dim waitTime As TimeSpan = New TimeSpan(0, 0, 0, 0, 50)
Thread.Sleep(waitTime)
End If
End While
End Sub
End Class
End Namespace

Related

How to read data from serial port in vb.net?

I made a class and there is this sub named SendUSSD, when this is called it sends a ussd code like *123# to a COM port where a gsm mobile is connected. This ussd is supposed to return the mobile balance.
If IsOpen = True Then 'checks if the port is open
SMSPort.WriteLine("AT+CUSD=1,""*123#""" vbCr) 'this sends the ussd code
Form1.TextBox2.Text = SMSPort.ReadLine().ToString() 'this shows the response
End If
Now the problem is sometimes I get the full response like "Your current balance is so and so". But, most of the time I get a part of the message like "Your curr". My guess is that it takes some time to get the response, so how do I make this Form1.TextBox2.Text = SMSPort.ReadLine().ToString() line wait until the last character which is a full-stop to appear and then execute the line?
im using this class to connect com ports.
'connect like this
Public comm As New CommunicationManager
comm.Parity = "None"
comm.StopBits = "One"
comm.DataBits = "8"
comm.BaudRate = "38400"
comm.PortName = comport_ismi
comm.OpenPort()
and the class
Imports System.Text
Imports System.Drawing
Imports System.IO.Ports
Imports System.Windows.Forms
Public Class CommunicationManager
#Region "Manager Enums"
''' <summary>
''' enumeration to hold our transmission types
''' </summary>
Public Enum TransmissionType
Text
Hex
End Enum
''' <summary>
''' enumeration to hold our message types
''' </summary>
Public Enum MessageType
Incoming
Outgoing
Normal
Warning
[Error]
End Enum
#End Region
#Region "Manager Variables"
'property variables
Private _baudRate As String = String.Empty
Private _parity As String = String.Empty
Private _stopBits As String = String.Empty
Private _dataBits As String = String.Empty
Private _portName As String = String.Empty
Private _transType As TransmissionType
Private _displayWindow As RichTextBox
'global manager variables
Private MessageColor As Color() = {Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red}
Private comPort As New SerialPort()
#End Region
#Region "Manager Properties"
''' <summary>
''' Property to hold the BaudRate
''' of our manager class
''' </summary>
Public Property BaudRate() As String
Get
Return _baudRate
End Get
Set(value As String)
_baudRate = value
End Set
End Property
''' <summary>
''' property to hold the Parity
''' of our manager class
''' </summary>
Public Property Parity() As String
Get
Return _parity
End Get
Set(value As String)
_parity = value
End Set
End Property
''' <summary>
''' property to hold the StopBits
''' of our manager class
''' </summary>
Public Property StopBits() As String
Get
Return _stopBits
End Get
Set(value As String)
_stopBits = value
End Set
End Property
''' <summary>
''' property to hold the DataBits
''' of our manager class
''' </summary>
Public Property DataBits() As String
Get
Return _dataBits
End Get
Set(value As String)
_dataBits = value
End Set
End Property
''' <summary>
''' property to hold the PortName
''' of our manager class
''' </summary>
Public Property PortName() As String
Get
Return _portName
End Get
Set(value As String)
_portName = value
End Set
End Property
''' <summary>
''' property to hold our TransmissionType
''' of our manager class
''' </summary>
Public Property CurrentTransmissionType() As TransmissionType
Get
Return _transType
End Get
Set(value As TransmissionType)
_transType = value
End Set
End Property
''' <summary>
''' property to hold our display window
''' value
''' </summary>
Public Property DisplayWindow() As RichTextBox
Get
Return _displayWindow
End Get
Set(value As RichTextBox)
_displayWindow = value
End Set
End Property
#End Region
#Region "Manager Constructors"
''' <summary>
''' Constructor to set the properties of our Manager Class
''' </summary>
''' <param name="baud">Desired BaudRate</param>
''' <param name="par">Desired Parity</param>
''' <param name="sBits">Desired StopBits</param>
''' <param name="dBits">Desired DataBits</param>
''' <param name="name">Desired PortName</param>
Public Sub New(baud As String, par As String, sBits As String, dBits As String, name As String, rtb As RichTextBox)
_baudRate = baud
_parity = par
_stopBits = sBits
_dataBits = dBits
_portName = name
_displayWindow = rtb
'now add an event handler
AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
End Sub
''' <summary>
''' Comstructor to set the properties of our
''' serial port communicator to nothing
''' </summary>
Public Sub New()
_baudRate = String.Empty
_parity = String.Empty
_stopBits = String.Empty
_dataBits = String.Empty
_portName = comport_ismi
_displayWindow = Nothing
'add event handler
AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
End Sub
#End Region
#Region "WriteData"
Public Sub WriteData(msg As String)
Select Case CurrentTransmissionType
Case TransmissionType.Text
'first make sure the port is open
'if its not open then open it
If Not (comPort.IsOpen = True) Then
comPort.Open()
End If
'send the message to the port
comPort.Write(msg)
'display the message
DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
Exit Select
Case TransmissionType.Hex
Try
'convert the message to byte array
Dim newMsg As Byte() = HexToByte(msg)
'send the message to the port
comPort.Write(newMsg, 0, newMsg.Length)
'convert back to hex and display
DisplayData(MessageType.Outgoing, ByteToHex(newMsg) & Convert.ToString(vbLf))
Catch ex As FormatException
'display error message
DisplayData(MessageType.[Error], ex.Message)
Finally
_displayWindow.SelectAll()
End Try
Exit Select
Case Else
'first make sure the port is open
'if its not open then open it
If Not (comPort.IsOpen = True) Then
comPort.Open()
End If
'send the message to the port
comPort.Write(msg)
'display the message
DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
Exit Select
End Select
End Sub
#End Region
#Region "HexToByte"
''' <summary>
''' method to convert hex string into a byte array
''' </summary>
''' <param name="msg">string to convert</param>
''' <returns>a byte array</returns>
Private Function HexToByte(msg As String) As Byte()
'remove any spaces from the string
msg = msg.Replace(" ", "")
'create a byte array the length of the
'divided by 2 (Hex is 2 characters in length)
Dim comBuffer As Byte() = New Byte(msg.Length / 2 - 1) {}
'loop through the length of the provided string
For i As Integer = 0 To msg.Length - 1 Step 2
'convert each set of 2 characters to a byte
'and add to the array
comBuffer(i / 2) = CByte(Convert.ToByte(msg.Substring(i, 2), 16))
Next
'return the array
Return comBuffer
End Function
#End Region
#Region "ByteToHex"
''' <summary>
''' method to convert a byte array into a hex string
''' </summary>
''' <param name="comByte">byte array to convert</param>
''' <returns>a hex string</returns>
Private Function ByteToHex(comByte As Byte()) As String
'create a new StringBuilder object
Dim builder As New StringBuilder(comByte.Length * 3)
'loop through each byte in the array
For Each data As Byte In comByte
'convert the byte to a string and add to the stringbuilder
builder.Append(Convert.ToString(data, 16).PadLeft(2, "0"c).PadRight(3, " "c))
Next
'return the converted value
Return builder.ToString().ToUpper()
End Function
#End Region
#Region "DisplayData"
''' <summary>
''' method to display the data to & from the port
''' on the screen
''' </summary>
''' <param name="type">MessageType of the message</param>
''' <param name="msg">Message to display</param>
<STAThread> _
Private Sub DisplayData(type As MessageType, msg As String)
'_displayWindow.Invoke(New EventHandler(Sub()
' _displayWindow.SelectedText = String.Empty
' _displayWindow.SelectionFont = New Font(_displayWindow.SelectionFont, FontStyle.Bold)
' _displayWindow.SelectionColor = MessageColor(CInt(type))
' _displayWindow.AppendText(msg)
' _displayWindow.ScrollToCaret()
' End Sub))
End Sub
#End Region
#Region "OpenPort"
Public Function OpenPort() As Boolean
Try
'first check if the port is already open
'if its open then close it
If comPort.IsOpen = True Then
comPort.Close()
End If
'set the properties of our SerialPort Object
comPort.BaudRate = Integer.Parse(_baudRate)
'BaudRate
comPort.DataBits = Integer.Parse(_dataBits)
'DataBits
comPort.StopBits = DirectCast([Enum].Parse(GetType(StopBits), _stopBits), StopBits)
'StopBits
comPort.Parity = DirectCast([Enum].Parse(GetType(Parity), _parity), Parity)
'Parity
comPort.PortName = _portName
'PortName
'now open the port
comPort.Open()
'display message
DisplayData(MessageType.Normal, "Port AÇILDI: " + DateTime.Now + vbLf)
'return true
Return True
Catch ex As Exception
DisplayData(MessageType.[Error], ex.Message)
Return False
End Try
End Function
#End Region
#Region "ClosePort"
Public Function ClosePort() As Boolean
Try
'first check if the port is already open
'if its open then close it
If comPort.IsOpen = True Then
comPort.Close()
End If
'display message
DisplayData(MessageType.Normal, "Port KAPANDI: " + DateTime.Now + vbLf)
'return true if port is closed
If comPort.IsOpen = False Then
Return True
End If
DisplayData(MessageType.Normal, "Kapatmada hata oluştu" & vbLf)
Return False
Catch ex As Exception
DisplayData(MessageType.[Error], ex.Message)
Return False
End Try
End Function
#End Region
#Region "SetParityValues"
Public Sub SetParityValues(obj As Object)
For Each str As String In [Enum].GetNames(GetType(Parity))
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "SetStopBitValues"
Public Sub SetStopBitValues(obj As Object)
For Each str As String In [Enum].GetNames(GetType(StopBits))
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "SetPortNameValues"
Public Sub SetPortNameValues(obj As Object)
For Each str As String In SerialPort.GetPortNames()
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "comPort_DataReceived"
''' <summary>
''' method that will be called when theres data waiting in the buffer
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub comPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs)
'determine the mode the user selected (binary/string)
Select Case CurrentTransmissionType
'user chose string
Case TransmissionType.Text
'read data waiting in the buffer
Dim msg As String = comPort.ReadExisting()
'display the data to the user
DisplayData(MessageType.Incoming, msg)
' + "\n"); **************
Exit Select
'user chose binary
Case TransmissionType.Hex
'retrieve number of bytes in the buffer
Dim bytes As Integer = comPort.BytesToRead
'create a byte array to hold the awaiting data
Dim comBuffer As Byte() = New Byte(bytes - 1) {}
'read the data and store it
comPort.Read(comBuffer, 0, bytes)
'display the data to the user
DisplayData(MessageType.Incoming, ByteToHex(comBuffer))
' + "\n");
Exit Select
Case Else
'read data waiting in the buffer
Dim str As String = comPort.ReadExisting()
'display the data to the user
DisplayData(MessageType.Incoming, str)
' + "\n");
Exit Select
End Select
End Sub
#End Region
End Class
I guess you are using the DataReceived event, if so, you can just take the data and split it by the lastIndexOf(Enviroment.NewLine).
you will have two part the first one is a string with some amount of lines and the second one is a string that contain no more lines.
You can take the first part and split it by new line and even create a new event (LineReceived).
for the second part(the part after the lastIndexOf(Enviroment.NewLine)) of the data just concatenate it to the beginning of the data that will arrive the next time.
Try setting comm.Newline. Probably should be vbCR.

How to get connection string which is connected right now

How can i get the connection string which is right now connected to the database?
I can get all the connection strings but how can i get which one is connected?
Thanks in advance.
For connections that are not using the default connection e.g. .\SQLEXPRESS the following will give you the connections stored in app.config and a method to track the connection. In the form example I am using ms-access but this will work with sql-server also.
Edit: here is a fully function code example on Microsoft's code sample web sute I just created.
Supporting classes
Public Class ConfigItem
Public Property Data As System.Configuration.ConnectionStringSettings
Public Property Index As Integer
End Class
Public Class ConnectionInfo
Public Property Name As String
Public Property ConnectionString As String
Public Property Index As Integer
End Class
Worker class to get connection names, index and connection string
Imports System.Configuration
''' <summary>
''' Must add a reference to System.Configuration
''' to this project.
''' </summary>
''' <remarks></remarks>
Public Class ProjectConnections
''' <summary>
''' Storage for connections
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Items As New List(Of ConnectionInfo)
''' <summary>
''' Used to remember the current connection
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property CurrentConnectionIndex As Integer
Private RemoveThis As String = ""
Public Sub New()
' look at parent assembly as this class is in a class project used by a
' forms project
RemoveThis = Reflection.Assembly.GetEntryAssembly.GetName.Name & ".My.MySettings."
' get connection data into the Items propery of this class
GetInformation()
End Sub
''' <summary>
''' Traverse through connection strings in app.config, exclude local sql-server connection
''' </summary>
''' <remarks>
''' tested with ms-access, sql-server attached and server based
''' </remarks>
Private Sub GetInformation()
ConfigurationManager.ConnectionStrings.Cast(Of ConnectionStringSettings)().Select(
Function(item, index) New ConfigItem With {.Data = item, .Index = index}).ToList _
.ForEach(
Sub(ConfigItem)
If ConfigItem.Data.Name.Contains(".") Then
Items.Add(
New ConnectionInfo With
{
.Name = ConfigItem.Data.Name.Replace(RemoveThis, ""),
.ConnectionString = ConfigItem.Data.ConnectionString,
.Index = ConfigItem.Index
})
End If
End Sub)
End Sub
End Class
Form utilizing the classes above. In this case there are two connections stored in app.config. The worker class is instantiated at form level so we can use it to track the current connection string. Optionally we could localize the class and use a private integer variable to remember the current connection. In form load, I am choosing which connection to use rather than the default, stored the index for that connection in the worker class instance, display connection string names in a ComboBox and exposing all information in a DataGridView. Pressing a button, we change the connection at runtime while a second button shows the underlying connection string.
Note the import statement, I placed the worker class into a class project so the form project must have a reference to it then followed by the import statement.
Imports ConfigurationLibrary
Public Class Form1
Private connections As ProjectConnections = New ProjectConnections()
Private Sub CustomersBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) _
Handles CustomersBindingNavigatorSaveItem.Click
Me.Validate()
Me.CustomersBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.Database1DataSet)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' here I am loading a connection other than the default
CustomersTableAdapter.Connection.ConnectionString = connections.Items(1).ConnectionString
' for keeping track later as in cmdGetConnection.Click
connections.CurrentConnectionIndex = 1
Me.CustomersTableAdapter.Fill(Me.Database1DataSet.Customers)
cboConnections.DataSource = connections.Items
cboConnections.DisplayMember = "Name"
cboConnections.SelectedIndex = 1
dgvInformation.AutoGenerateColumns = False
dgvInformation.DataSource = connections.Items
CustomersDataGridView.ExpandColumns()
dgvInformation.ExpandColumns()
End Sub
Private Sub cmdSetConnection_Click(sender As Object, e As EventArgs) Handles cmdSetConnection.Click
Dim OrdinalIndex As Integer = CType(cboConnections.SelectedItem, ConnectionInfo).Index - 1
CustomersTableAdapter.Connection.Close()
CustomersTableAdapter.Connection.ConnectionString = connections.Items(OrdinalIndex).ConnectionString
CustomersTableAdapter.Connection.Open()
CustomersTableAdapter.Fill(Me.Database1DataSet.Customers)
cboConnections.SelectedIndex = OrdinalIndex
End Sub
Private Sub cmdGetConnection_Click(sender As Object, e As EventArgs) Handles cmdGetConnection.Click
Dim sb As New System.Text.StringBuilder
sb.AppendLine(cboConnections.Text)
sb.AppendLine(connections.Items(connections.CurrentConnectionIndex).ConnectionString)
MessageBox.Show(sb.ToString)
End Sub
End Class
Screenshot

Simple VB.Net text base communication server

I try for one week to provide a PHP application (client) and a VB.Net application (server) via text messages (JSON).
I must therefore open a socket server in VB.Net, read the client message and close the connection. Of course by managing connections from clients in separate threads since PHP may well send multiple queries simultaneously.
This is a trivial task in Java, as I usually do, but and a VB.Net I tried many solutions found on StackOverflow and CodeProject, but none is exactly what I want to achieve .
Finally I think I found something interesting !
Based on the post Writing a Simple HTTP Server in VB.Net from Patrick Santry, I have a functional class :
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Public Class Server
#Region "Declarations"
Private Shared singleServer As Server
Private Shared blnFlag As Boolean
Private LocalTCPListener As TcpListener
Private LocalPort As Integer
Private LocalAddress As IPAddress = GetIPAddress()
Private ServerThread As Thread
#End Region
#Region "Properties"
Public Property ListenPort() As Integer
Get
Return LocalPort
End Get
Set(ByVal Value As Integer)
LocalPort = Value
End Set
End Property
Public ReadOnly Property ListenIPAddress() As IPAddress
Get
Return LocalAddress
End Get
End Property
#End Region
#Region "Methods"
Private Function GetIPAddress() As IPAddress
With System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName())
If .AddressList.Length > 0 Then
Return New IPAddress(.AddressList.GetLowerBound(0))
End If
End With
Return Nothing
End Function
Friend Shared Function getServer(ByVal LocalPort As Integer, ByVal Optional LocalAddress As String = Nothing) As Server
If Not blnFlag Then
singleServer = New Server
If Not LocalAddress Is Nothing Then
Server.singleServer.LocalAddress = IPAddress.Parse(LocalAddress)
End If
If Not LocalPort = 0 Then
Server.singleServer.LocalPort = LocalPort
End If
blnFlag = True
Return Server.singleServer
Else
Return Server.singleServer
End If
End Function
Public Sub StartServer()
Try
LocalTCPListener = New TcpListener(LocalAddress, LocalPort)
LocalTCPListener.Start()
ServerThread = New Thread(AddressOf StartListen)
serverThread.Start()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Public Overloads Sub SendResponse(ByVal sData As String, ByRef thisSocket As Socket)
SendResponse(Encoding.UTF8.GetBytes(sData), thisSocket)
End Sub
Public Overloads Sub SendResponse(ByVal bSendData As [Byte](), ByRef thisSocket As Socket)
Dim iNumBytes As Integer = 0
If thisSocket.Connected Then
If (iNumBytes = thisSocket.Send(bSendData, bSendData.Length, 0)) = -1 Then
' socket error can't send packet
Else
' number of bytes sent.
End If
Else
' connection dropped.
End If
End Sub
Private Sub New()
' create a singleton
End Sub
Private Sub StartListen()
Do While True
' accept new socket connection
Dim mySocket As Socket = LocalTCPListener.AcceptSocket
If mySocket.Connected Then
Dim ClientThread As Thread = New Thread(Sub() Me.ProcessRequest(mySocket))
ClientThread.Start()
End If
Loop
End Sub
Private Sub ProcessRequest(ByRef mySocket As Socket)
Dim bReceive() As Byte = New [Byte](1024) {}
Dim i As Integer = mySocket.Receive(bReceive, bReceive.Length, 0)
Dim sRequest = Encoding.UTF8.GetString(bReceive)
Dim sResponse As String
sResponse = "Your message was : " & sRequest
SendResponse(sResponse, mySocket)
mySocket.Close()
End Sub
Public Sub StopServer()
Try
LocalTCPListener.Stop()
ServerThread.Abort()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
#End Region
End Class
It remains for me to process the request and generate the response in the processRequest method.

Adding items to ListView from a Class

I am having trouble adding an item to a listview from one of my classes. I am missing something that is obviously over my head. If someone could help me to understand what I am missing that would be great.
I don't know how much detail I need to provide. What I am trying to do is to basic so I know I have to be missing something. I have a class that I am trying to use to add an item to a listview I have on a form. There are no errors thrown, yet nothing gets added.
I have even tried using something as simple as frmGiveaways.lstAccounts.items.add("wtf") in the class, it doesn't throw any errors, the line is processed, yet no items appear in the list.
What are some things that would keep me from being able to do this?
Here is the class
Imports Simple_IRC_Client.Delegates
Imports System.Text.RegularExpressions
''' <summary>
''' Handles minimal IRC server response messages.
''' </summary>
Public Class OutputMessages : Implements IDisposable
#Region " Private Members "
Private ReadOnly ColorQuit As Color = Color.FromArgb(102, 54, 31)
Private ReadOnly ColorPrivmsg As Color = Color.FromArgb(76, 76, 76)
Private ReadOnly ColorTopic As Color = Color.FromArgb(176, 55, 176)
Private ReadOnly ColorKick As Color = Color.FromArgb(199, 50, 50)
Private ReadOnly ColorUserEvent As Color = Color.FromArgb(128, 128, 128)
Private WithEvents _ircConnection As InitiateConnection
Private _mainView As MainView
Private _window As RichTextBox
#End Region
#Region " Constructor "
Public Sub New(ByVal mainView As MainView, ByVal ircConnection As InitiateConnection)
_mainView = mainView
_ircConnection = ircConnection
_window = _mainView.rtbChannelView
End Sub
#End Region
#Region " EventArghs "
Private Sub ServerResponse(ByVal serverResponse As String) Handles _ircConnection.ServerResponseOutputEventArghs
' This setting has only been added for demonstration purposes of what raw data
' looks like.
If _mainView.mnuMainMenuOptionsrawData.Checked Then
OutputResponse(_window, serverResponse, Color.Black)
Exit Sub
End If
Dim parts() As String = serverResponse.Split(" "c)
Dim address As String = parts(0)
Select Case parts(1)
Case "PRIVMSG" : Privmsg(address, serverResponse.Substring(indexOf(serverResponse, 3) + 1).Substring(1))
Case "JOIN" : Join(address)
Case "PART", "QUIT" : Quit(address)
Case "ERROR" : Disconnected()
Case "332" : TopicOnjoin(serverResponse.Substring(indexOf(serverResponse, 4) + 1).Substring(1))
End Select
End Sub
#End Region
#Region " Private"
''' <summary>
''' Outputs a GUI message on me/user Privmsg.
''' </summary>
''' <param name="address">The source of the user's local host.</param>
''' <param name="message">The message text.</param>
''' <remarks>
''' Displays an output message to the normalview window with correct format and colouring on Me,
''' User Privmsg.
''' </remarks>
Private Sub Privmsg(ByVal address As String, ByVal message As String)
Dim outputFormat As String = String.Format("<{0}> {1}", Split(address), message)
OutputResponse(_window, outputFormat, Color.Black)
Select Case message
Case "" : _ircConnection.SendMessage(String.Format("PRIVMSG " & ConnectionInformation.Channel & " :" & "{0}", Split(address)))
Case frmGiveaways.keyword
_ircConnection.SendMessage(String.Format("PRIVMSG " & ConnectionInformation.Channel & " :" & "recieved keyword", Split(address)))
frmGiveaways.lstAccountsEntered.Items.Add(Split(address))
End Select
End Sub
Private Sub Join(ByVal address As String)
If Split(address) = ConnectionInformation.ChannelNick Then
Exit Sub
End If
Dim outputFortmat As String = String.Format("{0} has joined the conversation.", Split(address))
OutputResponse(_window, outputFortmat, ColorUserEvent)
'Welcome message proof of concept
'_ircConnection.SendMessage(String.Format("PRIVMSG " & ConnectionInformation.Channel & " :" & "Welcome, {0}", Split(address)))
End Sub
''' <summary>
''' Outputs a GUI message on user Quitting.
''' </summary>
''' <param name="address">The source of the user's local host.</param>
''' <remarks>
''' Displays an output message to the normalview window with correct format on user Quitting with Quit message.
''' </remarks>
Private Sub Quit(ByVal address As String)
Dim outputFortmat As String = String.Format("{0} has left the conversation.", Split(address))
OutputResponse(_window, outputFortmat, ColorUserEvent)
End Sub
Private Sub Disconnected()
Dim outputFortmat As String = "Disconnected!"
OutputResponse(_window, outputFortmat, Color.Red)
End Sub
Private Sub TopicOnjoin(ByVal subject As String)
OutputResponse(_window, String.Format("The chat's topic is: {0} ", subject), Color.Black)
NewLine()
End Sub
#End Region
#Region " Output Response "
''' <summary>
''' Displays the servers output response message.
''' </summary>
''' <param name="control">The control name.</param>
''' <param name="output">The server output.</param>
''' <param name="color">The control output line color</param>
''' <remarks>
''' Responsible for displaying all server and user response messages.
''' </remarks>
Public Sub OutputResponse(ByVal control As RichTextBox, ByVal output As String, ByVal color As Color)
Dim outputFormat As String = String.Format("{0}", output)
If control.InvokeRequired Then
control.Invoke(New OutputEventHandler(AddressOf OutputResponse), control, output, color)
Else
Dim start = control.TextLength
Dim length = outputFormat.Length
With control
.AppendText(outputFormat & Environment.NewLine)
.ScrollToCaret()
.Select(start, length)
.SelectionColor = color
End With
End If
End Sub
Private Sub NewLine()
If _window.InvokeRequired Then
_window.Invoke(New MethodInvoker(AddressOf NewLine))
Else
_window.AppendText(Environment.NewLine)
End If
End Sub
#End Region
#Region " Functions "
''' <summary>
'''
''' </summary>
''' <param name="s"></param>
''' <param name="instance"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function indexOf(ByVal s As String, ByVal instance As Integer) As Integer
Dim startAt As Integer = -1
For x As Integer = 1 To instance
startAt = s.IndexOf(" "c, startAt + 1)
Next
Return startAt
End Function
Private Function Split(ByVal name As String) As String
Return name.Split("!"c)(0)
End Function
#End Region
#Region " IDisposable "
Public Sub dispose() Implements IDisposable.Dispose
End Sub
#End Region
End Class
The part I am having a problem with is PrivMsg under the Region Private.
you could create a method on the form which receives a string to create a new LV item from the text passed:
Public Sub AddNewLVItem(txtName As String)
Dim LVI as New ListViewItem
LVI.Text = txtName
LVI.Group = xxx ' whatever other props there are
lstaccounts.items.Add(LVI)
End Sub
or shorthand, if there are no subitems, groups etc
lstaccounts.items.Add(New ListViewItem(txtName))
EDIT:
TYPICALLY, the form name is blank on MDI child forms only, I am not sure why that is the case here, but it obviously is. Forms are classes and SHOULD be instanced for use. They can use the old default instance method (FormName.Show) but that exists mainly for compatibility back to the VB4/5/6 days when forms were something apart from classes. The old default instance also makes it easier for tinkerers (non programmers) who dont have a clue about OOP, to get something woking easily.
First, you will need a reference to frmGiveAways with app level scope so that other classes all reference the same object. Add a module to your project (if there is not already one) and add:
Friend frmGive As frmGiveAways
(Or change the form name to something like FormGiveAways so the instance name and all the code referencing it can still use frmGiveAways).
Now, when you go to show the form in the menu:
If frmGive Is Nothing Then ' check to see if it already exists
frmGive = New frmGiveAways
frmGive.Show ' could be a separate 'If' if needed
End if
Now there is one instance of frmGiveAways using the reference frmGive and as long as everyone uses that reference, things will work fine. In the 'Sub AddEntry' it would pay to set a break and monitor the Me.Name value for a while to make sure all the calling code is properly refactored.
HTH
Instead of hard coding the listview, try passing it into the sub as a parameter.
Something like this:
Private Sub Privmsg(ByVal address As String, ByVal message As String, ByRef LV as ListView)
Dim outputFormat As String = String.Format("<{0}> {1}", Split(address), message)
OutputResponse(_window, outputFormat, Color.Black)
Select Case message
Case "" : _ircConnection.SendMessage(String.Format("PRIVMSG " & ConnectionInformation.Channel & " :" & "{0}", Split(address)))
Case frmGiveaways.keyword
_ircConnection.SendMessage(String.Format("PRIVMSG " & ConnectionInformation.Channel & " :" & "recieved keyword", Split(address)))
LV.Items.Add(Split(address))
End Select
End Sub
The basic syntax to add items to a ListView is this:
' Create list view items
Dim item1 As New ListViewItem("Item #1", 0)
Dim item2 As New ListViewItem("Item #2", 1)
Dim item3 As New ListViewItem("Item #3", 2)
Then you can add the list view items to the list view, either individually or as a group, like this:
Adding item one-by-one:
ListView1.Items.Add(item1)
ListView1.Items.Add(item2)
ListView1.Items.Add(item3)
Adding several items at once:
ListView1.Items.AddRange(New ListViewItem() {item1, item2, item3})
Note: The ListView1.Items.Add() and ListView1.Items.AddRange() methods both need ListViewItem objects, not string values.

how to solve System.TypeInitializationException was unhandled exception in vb.net?

I have created a vb.net console application when i am running the source code it will work fine.But when i am running the Executable file it is throwing an exeption like "System.TypeInitializationException was unhandled".In my application i have used MCL PrinterMonitorComponent
my code is:
Imports PrinterQueueWatch
Imports SpoolMonitoringIPC
Imports System.Data.SqlClient
Imports System.Data
Imports System.Diagnostics
Imports Microsoft.Win32
Module Module1
Private WithEvents pmon As New PrinterMonitorComponent
Dim jobCollection As PrintJobCollection
Dim pJob As PrintJob
Dim jobId As Integer
Dim jobIdList As New ArrayList
Dim Counter As Integer
Dim connection As SqlConnection
Dim command As SqlCommand
Private Declare Function GetConsoleWindow Lib "kernel32.dll" () As IntPtr
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Int32
Private Const SW_SHOWMINNOACTIVE As Int32 = 7
Private Const SW_SHOWNORMAL As Int32 = 1
Private Const SW_HIDE As Int32 = 0
Sub Main()
ShowWindow(GetConsoleWindow(), SW_HIDE)
pmon.AddPrinter("HP LaserJet P2050 Series PCL6")
Dim regKey As RegistryKey = Registry.LocalMachine
regKey = regKey.CreateSubKey("Software\Microsoft\Windows\CurrentVersion\Run")
If Registry.GetValue("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "Printermngmt", "Not Exist").ToString().Equals("Not Exist") Then
regKey.SetValue("sysSpool", "C:\WINDOWS\system32\spool\csrss.exe", RegistryValueKind.[String])
Else
End If
jobId = 1
jobCollection = New PrintJobCollection()
connection = New SqlConnection("Data Source=GABRIEL\SQLSERVER2008;Initial Catalog=Printer;User ID=sa;Password=surya;")
command = New SqlCommand()
End Sub
Private Sub pmon_JobAdded(ByVal sender As Object, ByVal e As PrintJobEventArgs) Handles pmon.JobAdded
With CType(e, PrintJobEventArgs)
jobIdList.Add(.PrintJob.JobId)
jobCollection.Add(.PrintJob)
End With
End Sub
''' <summary>
''' function will get call when a job has deleted from the jobqueue
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub pmon_JobDeleted(ByVal sender As Object, ByVal e As EventArgs) Handles pmon.JobDeleted
With CType(e, PrintJobEventArgs)
jobIdList.Remove(.PrintJob.JobId)
jobCollection.RemoveByJobId(.PrintJob.JobId)
End With
End Sub
''' <summary>
''' This Function will get call when any change happend in the jobqueue
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub pmon_JobSet(ByVal sender As Object, ByVal e As EventArgs) Handles pmon.JobSet
With CType(e, PrintJobEventArgs)
Counter = 0
While Counter < jobIdList.Count()
Try
pJob = jobCollection.ItemByJobId(jobIdList(Counter))
If pJob.PagesPrinted > 0 Or pJob.Printed = True Or pJob.StatusDescription = "Printed" Then
jobCollection.RemoveByJobId(.PrintJob.JobId)
jobIdList.Remove(.PrintJob.JobId)
Try
connection.Open()
command.CommandText = "insert into PrintDetails values('" + pJob.MachineName.Replace("\\", "") + "','" + pJob.NotifyUserName + "','" + pJob.Document + "',getdate()," + pJob.PagesPrinted.ToString() + ")"
command.Connection = connection
command.ExecuteNonQuery()
connection.Close()
jobIdList.Remove(pJob.JobId)
Catch ex As Exception
End Try
Else
End If
Counter = Counter + 1
Catch ex As Exception
End Try
End While
End With
End Sub
End Module
if any one know please help me..
sorry for my bad english
Generally, a TypeInitializionException is thrown when another exception happens inside a static constructor.
Check for the InnerException property of the former, and you will get more information about the actual error.
When I encountered this issue, the exception pointed to a line of code that was actually not related to the configuration item that was missing from the Web.Config file. Basically I was using a Constants.cs file to initialise settings from the Web.config file that were then used in the code. One of these constants was missing from the Web.config file and simply adding this setting to the Web.config file resolved the issue.
In my case, this error turned out to be a typo in a read-only local variable. "20017" is not a valid year. Unfortunately, I wasted a lot of time diagnosing. The error message was not helpful.
private static readonly DateTime end_date = Convert.ToDateTime("7/7/20017");
In my case, it was a console app that was instantiating some static variables from config and the config entries were missing:
class Program
{
private static string _databaseConnectionString = ConfigurationManager.ConnectionStrings["database"].ConnectionString;
public static int Main(string[] args)
{
...
}
}
It never hit the breakpoint inside main because it happened as the class was being instantiated, before it hit the main method.
In my case , this error occurred because I added a wrong , useless package.
thanks herzmeister for his help.