Jump to content

MAC Address Stuff


Mechaflash
 Share

Recommended Posts

Thanks to I created a self-contained MAC Address-getter for the local host. Not sure if someone has a better way of doing it. Searched for information on how to query the MAC address, found the example, but it required an input (the ip address or hostname). I wanted to bypass this requirement. Also one of my first times having to utilize StringRegExp()... so not sure if they are at their simplest forms.

Also thanks to guinness for _RunStdOutRead(). Extremely useful.

EDIT: Removed the parameter for _GetLocalMAC(). Separated tracert execution into its own function.

EDIT2: Changed _Localhost() to returns the IP without additional processing if the IP instead of a hostname resolves.

#include <Constants.au3>

ConsoleWrite(_GetLocalMAC() & @CRLF)

Func _GetLocalMAC()
    Local $strComputer = _Localhost()
    Local $objWMIService, $colAdapters, $sReturn

    $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
    $colAdapters = $objWMIService.ExecQuery ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")

    For $objAdapter in $colAdapters
        If Not ($objAdapter.IPAddress) = " " Then
            For $i = 0 To UBound($objAdapter.IPAddress)
                If $objAdapter.IPAddress($i) = $strComputer Then
                    $sReturn = $objAdapter.MACAddress($i)
                    ExitLoop 2
                EndIf
            Next
        EndIf
    Next

    Return $sReturn
EndFunc

Func _Localhost()
    Local $aReturn, $sInput, $sData
    $sData = _Tracert("localhost")
    $aReturn = StringRegExp($sData, '(s*S*s*[)', 3)
    $sInput = StringStripWS(StringReplace($aReturn[0], "[", ""), 8)
    If StringRegExp($aReturn[0], '((d{1,3}.){3,3}d{1,3})') Then Return $aReturn[0]
    $sData = _Tracert($sInput)
    $aReturn = StringRegExp($sData, '((d{1,3}.){3,3}d{1,3})', 3)
    Return $aReturn[0]
EndFunc

Func _Tracert(Const $sTarget)
    Local $sReturn
    Switch @OSVersion
        Case "WIN_XP", "WIN_XPe", "WIN_2000"
            $sData = _RunStdOutRead("tracert -h 1 -w 1 " & $sTarget)
        Case Else
            $sData = _RunStdOutRead("tracert -4 -h 1 -w 1 " & $sTarget)
    EndSwitch
    Return $sData
EndFunc

Func _RunStdOutRead($sCommand, $sWorkingDirectory = @SystemDir)
    Local $iPID = Run(@ComSpec & ' /c ' & $sCommand, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD), $sOutput = ''
    While 1
        $sOutput &= StdoutRead($iPID)
        If @error Then
            ExitLoop
        EndIf
    WEnd
    Return $sOutput
EndFunc   ;==>_RunStdOutRead

EDIT3:

This example accepts FQDNs and IPs and differentiates between the a localhost call and all others. Some error handling included.

Lan/Wan

#include <Constants.au3>

While 1
    $sHostname = InputBox(@ScriptName, "Insert an IP Address or Hostname")
    If @error Then Exit
    If StringRegExp($sHostname, "((d{1,3}.){3}d{1,3})") Then
        $sHost = $sHostname
    Else
        $sData = _RunStdOutRead(@ComSpec & ' /c ping -w 1 ' & $sHostname)
        If StringInStr($sData, "Ping request could not find host") Then
            msgbox(16 + 262144, @ScriptName, "Host unavailable. Please enter a new host.")
            ContinueLoop
        EndIf
        $aHost = StringRegExp($sData, "((d{1,3}.){3}d{1,3})", 3)
        $sHost = $aHost[0]
    EndIf
    If $sHost = _LocalHost() Then
        $sReturn = _GetLocalMAC()
    Else
        $sReturn = _GetNetworkMAC($sHost)
    EndIf
    If $sReturn = -1 Then
        msgbox(16 + 262144, @ScriptName, "Host not found in ARP list. Host may not exist on the same subnet?")
        ContinueLoop
    EndIf
WEnd

ConsoleWrite($sReturn & @CRLF)

Func _GetLocalMAC()
    Local $strComputer = _Localhost()
    Local $objWMIService, $colAdapters, $sReturn

    $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
    If @error Then Return SetError(1, 0, -2)
    $colAdapters = $objWMIService.ExecQuery ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")

    For $objAdapter in $colAdapters
        If Not ($objAdapter.IPAddress) = " " Then
            For $i = 0 To UBound($objAdapter.IPAddress)
                If $objAdapter.IPAddress($i) = $strComputer Then
                    $sReturn = $objAdapter.MACAddress($i)
                    ExitLoop 2
                EndIf
            Next
        EndIf
    Next

    Return $sReturn
EndFunc


Func _GetNetworkMAC(Const $sHost)
    ;NOTE: This function will only work on hosts on the same sub-domain.
    Local $aReturn, $sReturn
    ;Clear all entries from the ARP and ping the host. Pinging the host will enter that host into the ARP list.
    RunWait(@ComSpec & ' /c arp -d * & ping -w 1 ' & $sHost, @SystemDir, @SW_HIDE)
    $sData = _RunStdOutRead("arp -a")
    $aReturn = StringRegExp($sData, $sHost & ".*((..-){5}..)", 3)
    If @error Then Return SetError(1, 0, -1)
    $sReturn = StringStripWS($aReturn[0], 8)
    $aReturn = StringRegExp($sReturn, '((..-){5}..)', 3)
    $sReturn = StringReplace($aReturn[0], "-", ":")
    Return $sReturn
EndFunc

Func _Localhost()
    Local $aReturn, $sInput, $sData
    $sData = _Tracert("localhost")
    $aReturn = StringRegExp($sData, '(s*S*s*[)', 3)    
    $sInput = StringStripWS(StringReplace($aReturn[0], "[", ""), 8)
    If StringRegExp($aReturn[0], '((d{1,3}.){3,3}d{1,3})') Then Return $aReturn[0]
    $sData = _Tracert($sInput)
    $aReturn = StringRegExp($sData, '((d{1,3}.){3,3}d{1,3})', 3)
    Return $aReturn[0]
EndFunc

Func _Tracert(Const $sTarget)
    Local $sReturn
    Switch @OSVersion
        Case "WIN_XP", "WIN_XPe", "WIN_2000"
            $sReturn = _RunStdOutRead("tracert -h 1 -w 1 " & $sTarget)
        Case Else
            $sReturn = _RunStdOutRead("tracert -4 -h 1 -w 1 " & $sTarget)
    EndSwitch
    Return $sReturn
EndFunc

Func _RunStdOutRead($sCommand, $sWorkingDirectory = @SystemDir)
    Local $iPID = Run(@ComSpec & ' /c ' & $sCommand, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD), $sOutput = ''
    While 1
        $sOutput &= StdoutRead($iPID)
        If @error Then
            ExitLoop
        EndIf
    WEnd
    Return $sOutput
EndFunc   ;==>_RunStdOutRead

Edited by Mechaflash
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

Array error for me

Win7 32

Func _Localhost()
Local $aReturn, $sInput, $sData
$sData = _RunStdOutRead("tracert -h 1 -w 1 localhost")
$aReturn = StringRegExp($sData, '(s*S*s*[)', 3)
$sInput = StringStripWS(StringReplace($aReturn[0], "[", ""), 8)
$sData = _RunStdOutRead("tracert -h 1 -w 1 " & $sInput)
$aReturn = StringRegExp($sData, '((d{1,3}.){3,3}d{1,3})', 3)
Return $aReturn[0] ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Not an array
EndFunc

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I get the same error on Vista x86, but that's because, for some reason, tracert is using the IPv6 address instead of the IPv4 address, so there's nothing to parse. Wouldn't this be a whole lot easier?

#include <Constants.au3>

MsgBox(0, "", _GetLocalMAC(@IPAddress1))


Func _GetLocalMAC(Const $ip)
     Local $strComputer = $ip
     Local $objWMIService, $colAdapters, $sReturn
     $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
     $colAdapters = $objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
     For $objAdapter In $colAdapters
          If Not ($objAdapter.IPAddress) = " " Then
               For $i = 0 To UBound($objAdapter.IPAddress)
                    If $objAdapter.IPAddress($i) = $ip Then
                         $sReturn = $objAdapter.MACAddress($i)
                         ExitLoop 2
                    EndIf
               Next
          EndIf
     Next
     Return $sReturn
EndFunc   ;==>_GetLocalMAC

Or, using the original function, you could do it this way.

#include <Constants.au3>

MsgBox(0, "", _GetLocalMAC(_Localhost()))

Func _GetLocalMAC(Const $ip)
     Local $strComputer = $ip
     Local $objWMIService, $colAdapters, $sReturn
     $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
     $colAdapters = $objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
     For $objAdapter In $colAdapters
          If Not ($objAdapter.IPAddress) = " " Then
               For $i = 0 To UBound($objAdapter.IPAddress)
                    If $objAdapter.IPAddress($i) = $ip Then
                         $sReturn = $objAdapter.MACAddress($i)
                         ExitLoop 2
                    EndIf
               Next
          EndIf
     Next
     Return $sReturn
EndFunc   ;==>_GetLocalMAC

Func _Localhost()
     Local $aReturn, $sInput, $sData
     $sData = _RunStdOutRead("tracert -4 -h 1 -w 1 localhost") ; <<<<<<<<<<< forces using IPv4 with the -4 option
     $aReturn = StringRegExp($sData, '(s*S*s*[)', 3)
     $sInput = StringStripWS(StringReplace($aReturn[0], "[", ""), 8)
     $sData = _RunStdOutRead("tracert -4 -h 1 -w 1 " & $sInput) ; <<<<<<<<<<< forces using IPv4 with the -4 option
     $aReturn = StringRegExp($sData, '((d{1,3}.){3,3}d{1,3})', 3)
     Return $aReturn[0]
EndFunc   ;==>_Localhost

Func _RunStdOutRead($sCommand, $sWorkingDirectory = @SystemDir)
     Local $iPID = Run(@ComSpec & ' /c ' & $sCommand, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD), $sOutput = ''
     While 1
          $sOutput &= StdoutRead($iPID)
          If @error Then
               ExitLoop
          EndIf
     WEnd
     Return $sOutput
EndFunc   ;==>_RunStdOutRead
Edited by BrewManNH

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

This also works perfectly well if you don't need to parse or echo the output in real time.

Func _RunStdOutRead($sCommand, $sWorkingDirectory = @SystemDir)
    Local $iPID = Run(@ComSpec & ' /c ' & $sCommand, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)
    ProcessWaitClose($iPID)
    $sOutput = StdoutRead($iPID)
    StdioClose($iPID) ; not strictly necessary
    Return $sOutput
EndFunc   ;==>_RunStdOutRead

Though I wonder if there's an internal AutoIt buffer size limit for caching that output...

Edited by wraithdu
Link to comment
Share on other sites

The AutoIt buffer shouldn't have any effect, because it's not being read to the script until you pull it from the STDOUT stream, Windows stores the information until you read it.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Array error for me

Win7 32

Yeah, the script doesn't take into account ipv6 (and it was tested on XP so I never got the error myself).

@Brew, your first example works if your first connection is your real connection. I noticed this in the helpfile:

IP address of first network adapter. Tends to return 127.0.0.1 on some computers.

So there's possible room for error.

I'll rewrite the original with a conditional for Vista/7 as tracert -4 isn't a valid command in XP.

Edited by Mechaflash
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

Can someone test the updated code to make sure it work properly on vista/7/8 please?

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

@JohnOne thanks for testing it out.

I was on my way to making it work across a network, but I ran into a road bump. I got it to work on the same subnet, but haven't found a workaround without having to access the host in one way, shape or form (i.e. remote shell).

I utilized ARP to grab the MAC: clearing the ARP list first, pinging a host, and looking in the ARP list for the host by its IP address.

I don't think I'll go much further than this, as we utilize psexec at work, and I can just record the stdout of a psexec arp command to a remote host and perform the processing in that manner.

This example accepts FQDNs and IPs and differentiates between the a localhost call and all others. Some error handling included.

#include <Constants.au3>

While 1
    $sHostname = InputBox(@ScriptName, "Insert an IP Address or Hostname")
    If @error Then Exit
    If StringRegExp($sHostname, "((d{1,3}.){3}d{1,3})") Then
        $sHost = $sHostname
    Else
        $sData = _RunStdOutRead(@ComSpec & ' /c ping -w 1 ' & $sHostname)
        If StringInStr($sData, "Ping request could not find host") Then
            msgbox(16 + 262144, @ScriptName, "Host unavailable. Please enter a new host.")
            ContinueLoop
        EndIf
        $aHost = StringRegExp($sData, "((d{1,3}.){3}d{1,3})", 3)
        $sHost = $aHost[0]
    EndIf
    If $sHost = _LocalHost() Then
        $sReturn = _GetLocalMAC()
    Else
        $sReturn = _GetNetworkMAC($sHost)
    EndIf
    If $sReturn = -1 Then
        msgbox(16 + 262144, @ScriptName, "Host not found in ARP list. Host may not exist on the same subnet?")
        ContinueLoop
    EndIf
WEnd

ConsoleWrite($sReturn & @CRLF)

Func _GetLocalMAC()
    Local $strComputer = _Localhost()
    Local $objWMIService, $colAdapters, $sReturn

    $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
    If @error Then Return SetError(1, 0, -2)
    $colAdapters = $objWMIService.ExecQuery ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")

    For $objAdapter in $colAdapters
        If Not ($objAdapter.IPAddress) = " " Then
            For $i = 0 To UBound($objAdapter.IPAddress)
                If $objAdapter.IPAddress($i) = $strComputer Then
                    $sReturn = $objAdapter.MACAddress($i)
                    ExitLoop 2
                EndIf
            Next
        EndIf
    Next

    Return $sReturn
EndFunc


Func _GetNetworkMAC(Const $sHost)
    ;NOTE: This function will only work on hosts on the same sub-domain.
    Local $aReturn, $sReturn
    ;Clear all entries from the ARP and ping the host. Pinging the host will enter that host into the ARP list.
    RunWait(@ComSpec & ' /c arp -d * & ping -w 1 ' & $sHost, @SystemDir, @SW_HIDE)
    $sData = _RunStdOutRead("arp -a")
    $aReturn = StringRegExp($sData, $sHost & ".*((..-){5}..)", 3)
    If @error Then Return SetError(1, 0, -1)
    $sReturn = StringStripWS($aReturn[0], 8)
    $aReturn = StringRegExp($sReturn, '((..-){5}..)', 3)
    $sReturn = StringReplace($aReturn[0], "-", ":")
    Return $sReturn
EndFunc

Func _Localhost()
    Local $aReturn, $sInput, $sData
    $sData = _Tracert("localhost")
    $aReturn = StringRegExp($sData, '(s*S*s*[)', 3) 
    $sInput = StringStripWS(StringReplace($aReturn[0], "[", ""), 8)
    If StringRegExp($aReturn[0], '((d{1,3}.){3,3}d{1,3})') Then Return $aReturn[0]
    $sData = _Tracert($sInput)
    $aReturn = StringRegExp($sData, '((d{1,3}.){3,3}d{1,3})', 3)
    Return $aReturn[0]
EndFunc

Func _Tracert(Const $sTarget)
    Local $sReturn
    Switch @OSVersion
        Case "WIN_XP", "WIN_XPe", "WIN_2000"
            $sReturn = _RunStdOutRead("tracert -h 1 -w 1 " & $sTarget)
        Case Else
            $sReturn = _RunStdOutRead("tracert -4 -h 1 -w 1 " & $sTarget)
    EndSwitch
    Return $sReturn
EndFunc

Func _RunStdOutRead($sCommand, $sWorkingDirectory = @SystemDir)
    Local $iPID = Run(@ComSpec & ' /c ' & $sCommand, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD), $sOutput = ''
    While 1
        $sOutput &= StdoutRead($iPID)
        If @error Then
            ExitLoop
        EndIf
    WEnd
    Return $sOutput
EndFunc   ;==>_RunStdOutRead

Edited by Mechaflash
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

From now on I'm going to make a post strictly for code and a post for everything else lol. It gets annoying every time I go to edit something and the code formatting breaks =/

Edited by Mechaflash
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

If you don't use the default editor, the full featured one, when replying to a post, or even when editing one, it won't mess up the formatting. Click the button on the upper left of the edit box (Tooltip says "Toggle editing mode"), it will use the basic text edit box instead of the richedit one.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

@BrewManNH ahhh ok. Thanks.

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...