Geting MAC address by using VB.NET 2010 - vb.net

I have tried to get the MAC address of each network interface card on a machine by using the below function in VB.NET, but I just realized that this function doesn't work in Windows XP:
Function getMacAddress()
Dim nics() As NetworkInterface = NetworkInterface.GetAllNetworkInterfaces()
Return nics(1).GetPhysicalAddress.ToString
End Function
How can I make this code to run on Windows XP? What other alternatives exist to get the list of MAC addresses on Windows XP?

I did some digging when connecting to different VPNs. So far the below seems pretty reliable. Relying on 0 or 1 for the actual physical adapter as suggested above does not work in many cases. In some cases my actual Ethernet adapter was the 3rd adapter. Excluding the loopbacks, tunnels, and ppp adapters should narrow it down. I found that many of my non physical adapters have the string "00000000000000E0" as the mac address.
Private Function getMacAddress() As String
Try
Dim adapters As NetworkInterface() = NetworkInterface.GetAllNetworkInterfaces()
Dim adapter As NetworkInterface
Dim myMac As String = String.Empty
For Each adapter In adapters
Select Case adapter.NetworkInterfaceType
'Exclude Tunnels, Loopbacks and PPP
Case NetworkInterfaceType.Tunnel, NetworkInterfaceType.Loopback, NetworkInterfaceType.Ppp
Case Else
If Not adapter.GetPhysicalAddress.ToString = String.Empty And Not adapter.GetPhysicalAddress.ToString = "00000000000000E0" Then
myMac = adapter.GetPhysicalAddress.ToString
Exit For ' Got a mac so exit for
End If
End Select
Next adapter
Return myMac
Catch ex As Exception
Return String.Empty
End Try
End Function

Works for me on XP, except I've got a few interfaces and my first (0th) is my "real" MAC address, and it corresponds to the MAC address reported by a non-.NET program.

Related

Connect to selected wifi VB

I successfully list out remembered wifi in my windows profile using Native WI-FI from Nuget package. This is my code load list of WI-FI
Private Sub loadWifi()
listWifi.Items.Clear()
Dim wlan As WlanClient = New WlanClient()
Dim connectedSsids As List(Of String) = New List(Of String)()
For Each wlanIface As WlanClient.WlanInterface In wlan.Interfaces
For Each profileinfo As Wlan.WlanProfileInfo In wlanIface.GetProfiles()
listWifi.Items.Add(profileinfo.profileName)
Next
Next
End Sub
My intention is how can I get the selected WI-FI from combo box listWifi and connect to the network.
Then im using netsh command to connect with the network. Take from the combo box. It does not work
Private Sub ConnectTo(ByVal name As String)
Dim p = "netsh.exe"
Dim sInfo As New ProcessStartInfo(p, "wlan connect " & name)
sInfo.CreateNoWindow = True
sInfo.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(sInfo)
End Sub
I made decision to use SimpleWIFI API rather than Native since it will cause my application to crash (Exception: cannot be marshaled error).
To connect the network just simply netsh wlan disconnect first and connect the network using codes above. It works but with minor error (not all available network scanned sometimes) rather than my apps to close itself unexpectedly.

Already running application now gets socket error 10013

I have an application done in VB.NET that listen on a specific UDP port and answer through the same port to the IP that send the packet.
It was working ok from a couple of years to the last month; now when try to answer crash due to socket error 10013.
I even try an older version that I know it was working too and get the same crash.
I try disabling Microsoft Security Essentials real time protection and Windows firewall and didn't work.
In the code I have the line
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)
I have no clue about what to do, I'm lost.
Any idea how to solve this?
Edit:
Here's the code
#Region "UDP Send variables"
Dim GLOIP As IPAddress
Dim GLOINTPORT As Integer
Dim bytCommand As Byte() = New Byte() {}
#End Region
Dim MyUdpClient As New UdpClient()
Private Sub StartUdpBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartUdpBtn.Click
If StartUdpBtn.Tag = 0 Then
' If Not UdpOpen Then
StartUdpReceiveThread(CInt(ListeningPortLbl.Text))
'End If
Else
If ThreadReceive.IsAlive Then
ThreadReceive.Abort()
MyUdpClient.Close()
PrintLog("UDP port closed")
StartUdpBtn.Tag = 0
UdpOpen = False
StartUdpBtn.Text = "Start UDP"
End If
End If
If UdpOpen Then
StartUdpBtn.Tag = 1
StartUdpBtn.Text = "Stop UDP"
Else
StartUdpBtn.Tag = 0
StartUdpBtn.Text = "Start UDP"
TimerUDP.Enabled = False
TiempoUDP.Stop()
TiempoUdpLbl.Text = "--:--:--"
End If
End Sub
Private Sub StartUdpReceiveThread(ByVal Port As Integer)
Dim UdpAlreadyOpen As Boolean = False
Try
If Not UdpOpen Then
MyUdpClient = New UdpClient(Port)
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)
UdpAlreadyOpen = True
Else
Me.Invoke(Sub()
TiempoUDP.Restart()
If TimerUDP.Enabled = False Then
TimerUDP.Enabled = True
End If
End Sub)
End If
ThreadReceive = New System.Threading.Thread(AddressOf UdpReceive)
ThreadReceive.IsBackground = True
ThreadReceive.Start()
UdpOpen = True
If UdpAlreadyOpen Then
PrintLog(String.Format("UDP port {0} opened, waiting data...", Port.ToString))
End If
Catch ex As Exception
PrintErrorLog(ex.Message)
PrintErrorLog(ex.StackTrace)
End Try
End Sub
Private Sub UdpReceive()
Dim receiveBytes As [Byte]() = MyUdpClient.Receive(RemoteIpEndPoint)
DstPort = RemoteIpEndPoint.Port
IpRemota(RemoteIpEndPoint.Address.ToString)
Dim BitDet As BitArray
BitDet = New BitArray(receiveBytes)
Dim strReturnData As String = System.Text.Encoding.ASCII.GetString(receiveBytes)
If UdpOpen Then
StartUdpReceiveThread(CInt(ListeningPortLbl.Text))
End If
PrintLog("From: " & RemoteIpLbl.Text & ":" & ListeningPortLbl.Text & " - " & strReturnData)
AnswersProcessor(strReturnData)
End Sub
Private Sub UdpSend(ByVal txtMessage As String)
Dim pRet As Integer
GLOIP = IPAddress.Parse(RemoteIpLbl.Text)
'From UDP_Server3_StackOv
Using UdpSender As New System.Net.Sockets.UdpClient()
Dim RemoteEndPoint = New System.Net.IPEndPoint(0, My.Settings.UDP_Port)
UdpSender.ExclusiveAddressUse = False
UdpSender.Client.SetSocketOption(Net.Sockets.SocketOptionLevel.Socket, Net.Sockets.SocketOptionName.ReuseAddress, True)
UdpSender.Client.Bind(RemoteEndPoint)
UdpSender.Connect(GLOIP, DstPort)
bytCommand = Encoding.ASCII.GetBytes(txtMessage)
pRet = UdpSender.Send(bytCommand, bytCommand.Length)
End Using
PrintLog("No of bytes send " & pRet)
End Sub
10013 is WSAEACCES, which is documented as follows:
Permission denied.
An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).
Another possible reason for the WSAEACCES error is that when the bind function is called (on Windows NT 4.0 with SP4 and later), another application, service, or kernel mode driver is bound to the same address with exclusive access. Such exclusive access is a new feature of Windows NT 4.0 with SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE option.
In the comments you mentioned:
I tried the program on a XP x32 and works ok but on Windows 7 x32/x64 don't, even if I disable the firewall and Microsoft Security Essentials Live Protection.
Maybe it sounds almost obvious but you could try to start your program in all of the available Windows XP compatibility modes. You didn't say that you already tried this but maybe you're lucky and the problem will be "solved" by this workaround.
If the problem still exists afterwards and considering the error code of 10013, I would try or check the following things:
I know you disabled "Microsoft Security Essentials" and the Windows Firewall, but double check whether there are other security related programs/services like anti virus protection, anti malware tools etc. running. It really sounds like something is blocking your socket creation/bind.
In case your program created log output/data which allows you to see exactly when it started to fail:
Any new software installed at that time?
Were Windows Updates (maybe automatically) installed at that time? Especially security updates regarding network security?
Any other noticeable changes in your environment? What about log entries in your Windows system log?
Just as a little test to verify if the error occurs only with your UDP socket: Try to use a TCP socket instead of UDP.
Start the machine in Windows Safe Mode with network support and execute your program from there.
Run your program on another Windows 7 machine and see if the same problem occurs there. It could be a valuable starting point (in terms of localization) to know if the problem occurs only on specific versions of Windows.
Single step through your code with a debugger and carefully watch what happens. Perhaps this can reveal some additional info on what's going wrong.
Maybe some of the ideas above can help you to track down the problem a little bit more. Good luck!

how to identify application instance name along with its user in vb.net 3.5?

I am using the below code to identify instance of the application also if we need to check that which user is using this application what will be the code for it?
Function PrevInstance() As Boolean
If Ubound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
Return True
Else
Return False
End If
End Function
My requirement is if same user tries to open the application then it should display pop up message like "application already opened".
Please advice...
abhay
Thanks a lot guys.... solution on my problem as follows:
> Function PrevInstance() As Boolean
> If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName))
> > 0 Then
> Dim CurUser As Boolean = GetProcessOwner(Diagnostics.Process.GetCurrentProcess.ProcessName)
> Return CurUser
> Else
> Return False
> End If
> End Function
Function GetProcessOwner(ByVal ProcessName As String) As Boolean
Dim boolVal As Boolean
Dim CurUserName As String
Dim CountInstance As Integer
CountInstance = 0
CurUserName = System.Environment.UserName
Dim selectQuery As SelectQuery = New SelectQuery("Select * from Win32_Process Where Name = '" + ProcessName + ".exe' ")
Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher(selectQuery)
Dim y As System.Management.ManagementObjectCollection
y = searcher.Get
For Each proc As ManagementObject In y
Dim s(1) As String
proc.InvokeMethod("GetOwner", CType(s, Object()))
Dim n As String = proc("Name").ToString()
If n = ProcessName & ".exe" Then
If s(0) = CurUserName Then
CountInstance = CountInstance + 1
If CountInstance > 1 Then
boolVal = True
End If
End If
End If
Next
Return boolVal
End Function
I have called PrevInstance() in my Form_Load() and its working perfectly.
PrevInstance Property
Returns a value indicating whether a previous instance of an application is already running.
Syntax
object.PrevInstance
The object placeholder represents an object expression that evaluates to an object in the Applies To list.
Remarks
You can use this property in a Load event procedure to specify whether a user is already running an instance of an application. Depending on the application, you might want only one instance running in the Microsoft Windows operating environment at a time.
Note Since a computer running Windows NT can support multiple desktops, if you use a component designed to work with distributed COM, it can result in the following scenario:
A client program in a user desktop requests one of the objects the component provides. Because the component is physically located on the same machine, the component is started in the user desktop.
Subsequently, a client program on another computer uses distributed COM to request one of the objects the component provides. A second instance of the component is started, in a system desktop.
There are now two instances of the component running on the same NT computer, in different desktops.
This scenario is not a problem unless the author of the component has placed a test for App.PrevInstance in the startup code for the component to prevent multiple copies of the component from running on the same computer. In this case, the remote component creation will fail.
Send feedback to MSDN.Look here for MSDN Online resources.
Session
The above tells you if it's already running. This tells you what session. An interactive user is always session1 on Vista and later. 0 for XP and earlier.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
msgbox objitem.name & " PID=" & objItem.ProcessID & " SessionID=" & objitem.sessionid
Next
PS
The rules for single instance programs is just before you exit you switch windows to the previous instance.
PPS
Due to problems introduced by 32 bit computing previnstance (Win32's one rather than VB's) becomes less meaningful. The common way to do this now is to open and lock a file on startup (Windows also has memory constructs you can use such as mailslots, pipes, etc). If a program can't lock then another is already running.

Find serial port where my device is connected

I'm starting to work with a pinpad.
I need that my program find the port where the pinpad is connected without user interaction.
I tried with:
Dim searcher As New ManagementObjectSearcher("root\cimv2","SELECT * FROM Win32_SerialPort")
For Each queryObj As ManagementObject In searcher.Get()
MsgBox(queryObj("Name"))
Next
but this only give me "COM1" and "COM2" as an answer (My device is connected to COM4)
and with
Dim searcher As New ManagementObjectSearcher("root\cimv2", "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0")
For Each queryObj As ManagementObject In searcher.Get()
MsgBox(queryObj("Name"))
Next
With this one I can see my device friendly name but I donĀ“t know how to get the port (I receive the names like 'HP printer')
Any idea of how can I get the port that I need?
Thanks in advance
Based on the comments it sounds like your device is a USB device that has a driver that causes it to appear to be (emulates) a serial port attached device. In that case I would use:
My.Computer.Ports.SerialPortNames
to enumerate and loop over all serial ports. Then, one at a time try to open each one and send a command to the device that you know it responds to. Most devices have some kind of heartbeat or keep alive message that they will respond to. Whichever port you get a response on is the port you need to use.
I want to point 2 matters:
1: here is a solution i used for this problem (efficiancy corrections will be appreciated)
I used this soution i used to figure out on which port vx805 verifone pin pad was connected (has a unique device id):
Friend Class pinPadComLocater
Private Shared com As String
Private Const PNPDeviceID = "VID_11CA&PID_0220"
Private Const scope = "root\cimv2"
Public ReadOnly pinPadCom As String = Nothing
Sub New()
If isVX805PinPadConnected() Then
pinPadCom = com
Output.mainLog(Output.pinpadLocationMsg + com)
Else
Output.mainLog(Output.pinpadNotFoundMsg)
End If
End Sub
Private Shared Function queryCom(port As String) As Boolean
Dim query = "SELECT * FROM Win32_PnPEntity WHERE ClassGuid=""{4d36e978-e325-11ce-bfc1-08002be10318}"" AND DeviceID LIKE ""%" + PNPDeviceID + "%"" AND Caption LIKE ""%" + port + "%"""
Dim resp = New ManagementObjectSearcher(scope, query).Get
If resp.Count = 1 Then Return True
For Each queryObj As ManagementObject In resp
For Each prop In queryObj.Properties 'print all data for development purposes
Try
Console.writeline(prop.Name + " : " + queryObj(prop.Name).ToString)
catch ex As Exception
End Try
Next
Next
Return False
End Function
Private Shared Function isVX805PinPadConnected() As Boolean
For Each port In My.Computer.Ports.SerialPortNames
Try
If queryCom(port) Then
com = port
Return True
End If
Catch err As ManagementException
Throw New ConstraintException("An error occurred while querying for WMI data: " & err.Message)
End Try
Next
Throw New ConstraintException("Pin Pad Com Port could not be located")
Return False
End Function
End Class
2: would love more clarifiaction on that:
Then, one at a time try to open each one and send a command to the device that you know it responds to. Most devices have some kind of heartbeat or keep alive message that they will respond to
I would love to see a code example of how you send such a heartbeat check to a pinpad

How do I check if an ftp server is online and get the error that it generates if it is not connected?

I am new to programming in vb.net. I have come a long ways in my development and understanding of vb, but there is one hurtle I can not seem to fix. I am hosting an ftp server on my pc and I am making an app for it to connect to my server and download files. The problem with all the sample code is that everyone ASSUMES the server WILL be ONLINE. My pc may not be running 24/7 and I also may not have the ftp service running.In the first case it shouldnt even register that it is connected. In the second case, it WILL say that is connected b/c the pc is on, but it will return that the machine ou are trying to connect to is actively refusing the connection. Is there a way to TRULY check if the program is indeed connected to the server WITHOUT generating a bunch of Exceptions in the debugger? All I want is a call like:
Dim ftponline As Boolean = False 'Set default to false
ftponline = checkftp()
If ftponline Then
'continue program
Else
'try a different server
End If
So it would be a function called checkftp that returns a boolean value of true or false.
Here is my info:
Using Visual Studio 2010 Pro
Using .Net framework 4
Can anyone help?
Thanks!
I have tried the rebex ftp pack as well as the Ultimate FTP Pack.
Here is the updated code:
Public Function CheckConnection(address As String) As Boolean
Dim logonServer As New System.Net.Sockets.TcpClient()
Try
logonServer.Connect(address, 21)
Catch generatedExceptionName As Exception
MessageBox.Show("Failed to connect to: " & address)
End Try
If logonServer.Connected Then
MessageBox.Show("Connected to: " & address)
Return True
logonServer.Close()
Else
Return False
End If
End Function
Public Sub ConnectFtp()
types.Clear()
models.Clear()
ListBox1.Items.Clear()
ListBox2.Items.Clear()
TextBox2.Clear()
Dim request As New Rebex.Net.Ftp
If CheckConnection(*) Then
Dim tempString As String()
request.Connect(*)
request.Login(*, *)
request.ChangeDirectory("/atc3/HD_Models")
Dim list As Array
list = request.GetNameList()
Dim item As String = ""
For Each item In list
tempString = item.Split(New Char() {" "c})
If types.Contains(tempString(0)) = False Then
types.Add(tempString(0))
End If
If models.Contains(item) = False Then
models.Add(item)
End If
Next
request.Disconnect()
request.Dispose()
ElseIf CheckConnection(*) Then
request.Connect(*)
request.Login(*, *)
request.ChangeDirectory(*)
Dim list2 As Array
list2 = request.GetNameList()
Dim item2 As String = ""
Dim tempString2 As String()
For Each item2 In list2
MessageBox.Show(item2)
tempString2 = item2.Split(New Char() {" "c})
If types.Contains(tempString2(0)) = False Then
types.Add(tempString2(0))
End If
If models.Contains(item2) = False Then
models.Add(item2)
End If
Next
request.Disconnect()
request.Dispose()
End If
End Sub
No matter what I do, the second server will not connect. I even put a messagebox to show what items were being returned in the second server, but there are no messageboxes apearing when I run the program with my server offline. Is there anyone who can help?
If your code is designed with proper exception catching, it shouldn't be generating a "bunch" of exceptions. The first exception you catch should be your indication that the connection failed and your code should cease attempting to communicate at that point. If for some reason you really need to check the connectivity before attempting the FTP connection, you should be able to simply attempt to synchronously open a TCP socket to the FTP server's port. If that works, it's up and running.
You could simply open a socket to the server's IP address on Port 21 (assuming default FTP port).
I'm not much of a VB.Net programmer, but here's a link to sample code:
http://vb.net-informations.com/communications/vb.net_Client_Socket.htm
If you can establish the socket connection, you know that something is listening on that port (though you have not yet proven it's an FTP server, or that it will accept your login credentials...).
If you wish to simply avoid exceptions in the debugger, you could place the connection code in a method and apply the DebuggerHidden attribute to that method.