Getting User Count From IRC - vb.net

I am making IRC chat client and I am wanting to grab the user list or simply the user count, how can I go about doing this. This is the method I'm using to connect to the IRC:
Private Sub IRCConnect()
Dim stream As NetworkStream
Dim irc As TcpClient
Dim reader As StreamReader
Try
irc = New TcpClient(SERVER, PORT)
stream = irc.GetStream()
reader = New StreamReader(stream)
writer = New StreamWriter(stream)
' Start PingSender thread
Dim ping As New PingSender
ping.Start()
writer.WriteLine(USER)
writer.Flush()
writer.WriteLine("NICK " & Config.Nickname)
writer.Flush()
writer.WriteLine("JOIN " & Config.Channel & " " & Config.ChanPass)
writer.Flush()
txtView.Text = txtView.Text & ">Connected successfully." & vbNewLine
HighlightPhrase(txtView, "Connected successfully.", Color.Lime)
Thread.Sleep(2000)
Catch Ex As Exception
' Show the exception, sleep for a while and try to establish a new connection to irc server
txtView.Text = txtView.Text & ">ERROR: Unexpected error occured: " & Ex.ToString & vbNewLine
HighlightPhrase(txtView, "Unexpected error occured: " & Ex.ToString, Color.Red)
End Try
End Sub
I have no idea where to start, any help would be much appreciated.

The IRC-protocol is defined in RFC2812: https://www.rfc-editor.org/rfc/rfc2812
Send the "NAMES #currentchannel" - command ( https://www.rfc-editor.org/rfc/rfc2812#section-3.2.5 ) and you will receive a list of all visible users. This list can be counted and voilĂ  - there you got your user-count

Start by reading the the specification for IRC, it is RFC 2812.
You'll want to use the NAMES message. Here is the appropriate section from the RFC.

Related

process.Start() won't work with Microsoft Edge or Internet Explorer

I recently updated my application to use oauth for a swagger interface, which requires opening a webpage to a specific URL and getting the user to authorize access. I then listen for the response sent to the local host and process the access token, etc. To do this I just call process.Start(URL)
Here is my code:
Private Sub GetAuthorizationfromWeb()
Try
' Build the authorization call
Dim URL As String = ESIAuthorizeURL & "?response_type=code" & "&redirect_uri=http://"
URL &= LocalHost & ":" & LocalPort & "&client_id=" & ClientID & "&scope=" & ScopesString
Process.Start(URL)
Dim mySocket As Socket = Nothing
Dim myStream As NetworkStream = Nothing
Dim myReader As StreamReader = Nothing
Dim myWriter As StreamWriter = Nothing
myListner.Start()
mySocket = myListner.AcceptSocket() ' Wait for response
Debug.Print("After socket listen")
myStream = New NetworkStream(mySocket)
myReader = New StreamReader(myStream)
myWriter = New StreamWriter(myStream)
myWriter.AutoFlush = True
Do
AuthStreamText &= myReader.ReadLine & "|"
If AuthStreamText.Contains("code") Then
Exit Do
End If
Loop Until myReader.EndOfStream
myWriter.Write("Login Successful!" & vbCrLf & vbCrLf & "You can close this window.")
myWriter.Close()
myReader.Close()
myStream.Close()
mySocket.Close()
myListner.Stop()
Application.DoEvents()
Catch ex As Exception
Application.DoEvents()
End Try
End Sub
All of it works fine with Firefox and to some extent Chrome when they are set as the default browser. However, when I try to launch the URL with Edge or Internet Explorer set as my default browser, it just opens a blank web page or the home page. There is no attempt to navigate to the URL set as the argument.
I tried to find another way to do this but basically process.Start seems to be the only option. I'm not going to embed a webbrowser in my code for security reasons.
Any thoughts?

Dynamically creating multiple background workers and passing them arguments

I've written an app that basically does constant pings to a list of hosts and logs the results.
I have a function...
Public Function doping(ByRef host As String)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Dim ResponseTime As Long
Dim timestamp As String = System.DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss")
Try
Result = SendPing.Send(host, 300)
ResponseTime = Result.RoundtripTime
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
DynaLogging(timestamp & " - Reply from " & host & ": bytes=32 time=" & ResponseTime.ToString & " TTL=??", host & ".log")
TextBox2.Text = timestamp & " - Reply from " & host & " : time =" & ResponseTime.ToString & br & TextBox2.Text
Else
DynaLogging(timestamp & " - No reply received from " & host, host & ".log")
TextBox2.Text = timestamp & " - No reply received from " & host & br & TextBox2.Text
End If
Catch ex As Exception
End Try
End Function
And I've got a timer, which currently fires off the following in a background worker...
On Error Resume Next
For Each hostyhost As String In ListBox1.Items
doping(hostyhost)
Next
This works a treat until one of the hosts in the list is not responding, then the backgroundworker waits because it can only process one ping at a time and so if one host is delayed, the remaining hosts have to wait before they are checked and the whole process slows down.
I could do with somehow dynamically creating multiple background workers at runtime but I do not know how to create a background worker dynamically which can be passed an argument.
I looked at this post about creating bgw's at runtime, but have no idea how to deploy this for what I need.
Can anyone point me in the right direction?
Why not a Parallel ForEach?
Dim Items As List(Of String) = New List(Of String)
For Each item As String In ListBox1.Items
Items.Add(item.ToString())
Next
Parallel.ForEach(Items, Sub(hostyhost)
doping(hostyhost)
End Sub)
It's included in the .NET Framework 4.0 under the System.Threading namespace and will take care of almost everything, without writing a million lines of code.

Timer to skip to connect to next computer in for each loop while connecting remotely using RegistryKey.OpenRemoteBaseKey

I built a tool (with Visual Studio 2015 Express - Visual Basic) that will check the mcafee dat version and date from the registry on computers input either manually, in a text file, or selected from active directory. The tool works it successfully returned all the information for 714 out of 970 computers/laptops. The majority of the failures were either because they could not be resolved in DNS or weren't pingable and the tools identifies those and successfully logs them. It took a little over 15 minutes for the tool to retrieve the information and log it in a spreadsheet. The issue is that on 19 of the failures I got one of the two following errors and those 19 took the majority of the 15 minutes for the tool get and log all the information:
Attempted to perform an unauthorized operation
The network path was not found
Is there a way of using a timer so that the program will attempt to connect to the registry at this point... rk1 = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, strComputer, RegistryView.Registry64) and then after a certain amount of time stop and move to the next computer in the for each loop? I have only been programming for a little over a year and I have learned exclusively through trial/error and google so please have patience with me as I am not a seasoned programmer. Here is the code:
The program works well my objective here is to improve it by making it skip to the next computer when it hangs for an extended period of time. I have filtered out the computers that can't be resolved in DNS or aren't pingable.
For Each sel In picker.SelectedObjects
Try
If HostIsResolvable(sel.Name) Then
Try
reply = ping.Send(sel.Name, 1)
If reply.Status = IPStatus.Success Then
IPAddr = reply.Address.ToString()
Try
comsys(sel.Name)
Dim rk1 As RegistryKey
Dim rk2 As RegistryKey
rk1 = RegistryKey.OpenRemoteBaseKey
(RegistryHive.LocalMachine, sel.Name,
RegistryView.Registry64)
rk2 = rk1.OpenSubKey
("SOFTWARE\Wow6432Node\McAfee\AVEngine")
mAV = rk2.GetValue("AVDatVersion").ToString
mAD = rk2.GetValue("AVDatDate").ToString
objExcel.Cells(y, 1) = sel.Name
objExcel.Cells(y, 2) = IPAddr
objExcel.Cells(y, 3) = commodel
objExcel.Cells(y, 4) = comuser
objExcel.Cells(y, 5) = "DAT Version Number: " & mAV
objExcel.Cells(y, 6) = "DAT Date: " & mAD
y = y + 1
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "-Unable to
connect. Make sure this computer is on the network,
has remote administration enabled, and that both
computers are running the remote registry service.
Error message: " & ex.Message & vbCrLf, True)
End Try
Else
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & " is not
pingable! " & vbCrLf, True)
End If
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "Ping error:
Unable to connect. Make sure this computer is on the
network, has remote administration enabled, and that
both computers are running the remote registry
service. Error message: " & ex.Message & vbCrLf, True)
End Try
Else
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & " could not be
resolved in DNS! " & vbCrLf, True)
End If
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "DNS error: Unable to
connect. Make sure this computer is on the network, has remote
administration enabled, andd that both computers are running the
remote registry service. Error message: " & ex.Message &
vbCrLf, True)
End Try
sel = Nothing
Next
You need to put your request in another thread. This thread can be aborted.
Sub Main()
Dim thrd As New Thread(AddressOf endlessLoop) 'thread with your sub
thrd.Start() 'Start thread
thrd.Join(1000) 'Block until completion or timeout
If thrd.IsAlive Then
thrd.Abort() 'abort thread
Else
'thread finished already
End If
End Sub
Sub endlessLoop()
Try
While True
'Your Code
End While
Catch ex As ThreadAbortException
'Your code when thread is killed
End Try
End Sub
Hope this helps.
'***** EDIT ***
Your code could look like this (I didn't checked if there are any variables to pass in Sub)
For Each sel In picker.SelectedObjects
Try
If HostIsResolvable(sel.Name) Then
Try
reply = ping.Send(sel.Name, 1)
If reply.Status = IPStatus.Success Then
IPAddr = reply.Address.ToString()
call timerThread 'New
Else
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & " is not
pingable! " & vbCrLf, True)
End If
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "Ping error:
Unable to connect. Make sure this computer is on the
network, has remote administration enabled, and that
both computers are running the remote registry
service. Error message: " & ex.Message & vbCrLf, True)
End Try
Else
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & " could not be
resolved in DNS! " & vbCrLf, True)
End If
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "DNS error: Unable to
connect. Make sure this computer is on the network, has remote
administration enabled, andd that both computers are running the
remote registry service. Error message: " & ex.Message &
vbCrLf, True)
End Try
sel = Nothing
Next
Sub timerThread()
Dim thrd As New Thread(AddressOf registryRequest) 'thread with your sub
thrd.Start() 'Start thread
thrd.Join(15000) 'Block until completion or timeout (15 seconds)
If thrd.IsAlive Then
thrd.Abort() 'abort thread
Else
'thread finished already
End If
End Sub
Sub registryRequest()
Try
comsys(sel.Name)
Dim rk1 As RegistryKey
Dim rk2 As RegistryKey
rk1 = RegistryKey.OpenRemoteBaseKey
(RegistryHive.LocalMachine, sel.Name,
RegistryView.Registry64)
rk2 = rk1.OpenSubKey
("SOFTWARE\Wow6432Node\McAfee\AVEngine")
mAV = rk2.GetValue("AVDatVersion").ToString
mAD = rk2.GetValue("AVDatDate").ToString
objExcel.Cells(y, 1) = sel.Name
objExcel.Cells(y, 2) = IPAddr
objExcel.Cells(y, 3) = commodel
objExcel.Cells(y, 4) = comuser
objExcel.Cells(y, 5) = "DAT Version Number: " & mAV
objExcel.Cells(y, 6) = "DAT Date: " & mAD
y = y + 1
Catch ex As ThreadAbortException
My.Computer.FileSystem.WriteAllText(Dell
& "\McAfeeDATeNumFailed.txt", sel.Name & "-Unable to
connect. Make sure this computer is on the network,
has remote administration enabled, and that both
computers are running the remote registry service.
Error message: " & ex.Message & vbCrLf, True)
End Try
End Sub
This works great but I am sure it can be improved so please respond with suggestions if you have them. Here is the code:
Try
Dim source1 As New CancellationTokenSource
Dim token As CancellationToken = source1.Token
Dim T20 As Task = Task.Factory.StartNew(Function() getping((sel.Name), token))
T20.Wait(30)
If T20.Status = TaskStatus.Running Then
source1.Cancel()
My.Computer.FileSystem.WriteAllText(Dell & "\McAfeeDATeNumFailed.txt", sel.Name & " Ping timed out. The task was disposed of at " & ex_time & "." & vbCrLf & vbCrLf, True)
End If
Dim source2 As New CancellationTokenSource
Dim token2 As CancellationToken = source2.Token
Dim T21 As Task = Task.Factory.StartNew(Function() comsys((sel.Name), token2))
T21.Wait(500)
If T21.Status = TaskStatus.Running Then
source2.Cancel()
My.Computer.FileSystem.WriteAllText(Dell & "\McAfeeDATeNumFailed.txt", sel.Name & " RPC error. The task was disposed of at " & ex_time & "." & vbCrLf & vbCrLf, True)
End If
Dim source3 As New CancellationTokenSource
Dim token3 As CancellationToken = source3.Token
Dim T22 As Task = Task.Factory.StartNew(Function() getregvalues((sel.Name), token3))
T22.Wait(600)
If T22.Status = TaskStatus.Running Then
source3.Cancel()
My.Computer.FileSystem.WriteAllText(Dell & "\McAfeeDATeNumFailed.txt", sel.Name & " Error retrieving registry value. The task was disposed of at " & ex_time & "." & vbCrLf & vbCrLf, True)
End If
IPAddr = reply.Address.ToString()
objExcel.Cells(y, 1) = sel.Name
objExcel.Cells(y, 2) = IPAddr
objExcel.Cells(y, 3) = commode
objExcel.Cells(y, 4) = comuser
objExcel.Cells(y, 5) = "DAT Version Number: " & mAV
objExcel.Cells(y, 6) = "DAT Date: " & mAD
y = y + 1
IPAddr = Nothing
reply = Nothing
commodel = Nothing
comuser = Nothing
sel = Nothing
Thread.Sleep(10)
Catch ex As Exception
End Try
I will try that and time it both ways. I added a continue for here and it cut it from 6 and a half minutes down to 3 and a half minutes (if it wasn't pingable then move on to the next computer instead of running the other 2 tasks).
If T20.Status = TaskStatus.Running Then
source1.Cancel()
Continue For
End If
I started to change the wait to a loop and I remembered that it takes that amount of time to successfully retrieve the remote information and get it into excel without missing data in the excel spreadsheet. For example I dropped the time to 10 ms and some of the computers didn't respond to the ping fast enough so that computer and it's information wasn't added to the spreadsheet. Likewise, I reduced the ms on the registry task and the registry information for that computer was missing in the spreadsheet.

Is it safe to call SmtpClient.Dispose() in .NET?

I have a scenario where I need to send 100 emails in one shot (using a loop), but also I am not allowed to send 1 email per SMTP session.
Right now all 100 emails are sharing same SMTP session.
I was thinking that calling SmtpClient.Dispose() will take care of what I need. Please correct me if I am wrong.
So, basically 3 questions:
Will SmtpClient.Dispose() take care of what I need?
If Yes, is it safe to Dispose() SmtpClient without affecting other services on the
server?
If No, What would be the right approach to achieve what I
want?
Sample Code:
Private Shared Sub SendMail(ByVal MailServer As SmtpClient, ByVal body As String, ByVal Subject As String, ByVal FromEmail As String, _
ByVal ToEmailList As String, Optional ByVal AttFile As Attachment = Nothing)
Dim message As New MailMessage
Try
message.From = New MailAddress(FromEmail)
message.Subject = Subject
message.IsBodyHtml = False
message.Body = body
message.Priority = MailPriority.High
If Not AttFile Is Nothing Then
message.Attachments.Add(AttFile)
Else
message.Attachments.Add(AttFile)
End If
MailServer.Send(message)
Catch ex As Exception
Throw New ApplicationException("SERVICE1.SendMail ERROR -- Error sending email [ERROR]:[" & ex.Message.ToString & "] " & vbCrLf & "To:" & ToEmailList & vbCrLf & "From:" & FromEmail & vbCrLf & "Subject: " & Subject & vbCrLf & "Body: " & body)
End Try
message.Dispose()
End Sub
And this is how the method is being executed:
For Each Item In ItemListCollection
m_MailServer = New SmtpClient(MailServerName)
MailServer.Credentials = New System.Net.NetworkCredential(MailServerUserName, MailServerPassword)
SendMail(WeeklyMailServer, msgBody, msgSubject, MsgFromEmail, "xyz#abc.com", rptAttachment)
Next
You could wrap it in a using statement and ensure that it is disposed when execution leaves the block. And you can call Send multiple times in a loop using the same SmtpClient.
Using client = New SmtpClient()
For i As Integer = 0 To 99
Dim message = New MailMessage()
'initialization of whatever is needed
' message creation
client.Send(message)
Next
End Using
Inside execution loop, you can enclose the code in a Using block. This will use a separate smtpclient for each email and will dispose / close it properly.
For Each Item In ItemListCollection
using m_MailServer as New SmtpClient(MailServerName)
MailServer.Credentials = New System.Net.NetworkCredential(MailServerUserName, MailServerPassword)
SendMail(WeeklyMailServer, msgBody, msgSubject, MsgFromEmail, "xyz#abc.com", rptAttachment)
end using
Next

Creating and appending text to txt file in VB.NET

Using VB.NET, I am trying to create a text file if it doesn't exist or append text to it if exists.
For some reason, though it is creating the text file I am getting an error saying process cannot access file.
And when I run the program it is writing text, but how can I make it write on a new line?
Dim strFile As String = "C:\ErrorLog_" & DateTime.Today.ToString("dd-MMM-yyyy") & ".txt"
Dim sw As StreamWriter
Dim fs As FileStream = Nothing
If (Not File.Exists(strFile)) Then
Try
fs = File.Create(strFile)
sw = File.AppendText(strFile)
sw.WriteLine("Start Error Log for today")
Catch ex As Exception
MsgBox("Error Creating Log File")
End Try
Else
sw = File.AppendText(strFile)
sw.WriteLine("Error Message in Occured at-- " & DateTime.Now)
sw.Close()
End If
Try this:
Dim strFile As String = "yourfile.txt"
Dim fileExists As Boolean = File.Exists(strFile)
Using sw As New StreamWriter(File.Open(strFile, FileMode.OpenOrCreate))
sw.WriteLine( _
IIf(fileExists, _
"Error Message in Occured at-- " & DateTime.Now, _
"Start Error Log for today"))
End Using
Don't check File.Exists() like that. In fact, the whole thing is over-complicated. This should do what you need:
Dim strFile As String = $#"C:\ErrorLog_{DateTime.Today:dd-MMM-yyyy}.txt"
File.AppendAllText(strFile, $"Error Message in Occured at-- {DateTime.Now}{Environment.NewLine}")
Got it all down to two lines of code :)
This should work for you without changing program logic (by not outputting "Start error" on the top of each file) like the other answers do :)
Remember to add exception handling code.
Dim filePath As String = String.Format("C:\ErrorLog_{0}.txt", DateTime.Today.ToString("dd-MMM-yyyy"))
Dim fileExists As Boolean = File.Exists(filePath)
Using writer As New StreamWriter(filePath, True)
If Not fileExists Then
writer.WriteLine("Start Error Log for today")
End If
writer.WriteLine("Error Message in Occured at-- " & DateTime.Now)
End Using
You didn't close the file after creating it, so when you write to it, it's in use by yourself. The Create method opens the file and returns a FileStream object. You either write to the file using the FileStream or close it before writing to it. I would suggest that you use the CreateText method instead in this case, as it returns a StreamWriter.
You also forgot to close the StreamWriter in the case where the file didn't exist, so it would most likely still be locked when you would try to write to it the next time. And you forgot to write the error message to the file if it didn't exist.
Dim strFile As String = "C:\ErrorLog_" & DateTime.Today.ToString("dd-MMM-yyyy") & ".txt"
Dim sw As StreamWriter
Try
If (Not File.Exists(strFile)) Then
sw = File.CreateText(strFile)
sw.WriteLine("Start Error Log for today")
Else
sw = File.AppendText(strFile)
End If
sw.WriteLine("Error Message in Occured at-- " & DateTime.Now)
sw.Close()
Catch ex As IOException
MsgBox("Error writing to log file.")
End Try
Note: When you catch exceptions, don't catch the base class Exception, catch only the ones that are releveant. In this case it would be the ones inheriting from IOException.
Why not just use the following simple call (with any exception handling added)?
File.AppendAllText(strFile, "Start Error Log for today")
EDITED ANSWER
This should answer the question fully!
If File.Exists(strFile)
File.AppendAllText(strFile, String.Format("Error Message in Occured at-- {0:dd-MMM-yyyy}{1}", Date.Today, Environment.NewLine))
Else
File.AppendAllText(strFile, "Start Error Log for today{0}Error Message in Occured at-- {1:dd-MMM-yyyy}{0}", Environment.NewLine, Date.Today)
End If
While I realize this is an older thread, I noticed the if block above is out of place with using:
Following is corrected:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim filePath As String =
String.Format("C:\ErrorLog_{0}.txt", DateTime.Today.ToString("dd-MMM-yyyy"))
Using writer As New StreamWriter(filePath, True)
If File.Exists(filePath) Then
writer.WriteLine("Error Message in Occured at-- " & DateTime.Now)
Else
writer.WriteLine("Start Error Log for today")
End If
End Using
End Sub
Try it this way:
Dim filePath As String =
String.Format("C:\ErrorLog_{0}.txt", DateTime.Today.ToString("dd-MMM-yyyy"))
if File.Exists(filePath) then
Using writer As New StreamWriter(filePath, True)
writer.WriteLine("Error Message in Occured at-- " & DateTime.Now)
Else
writer.WriteLine("Start Error Log for today")
End Using
end if