ChangeMACAddressBatch script

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
elias
Posts: 5
Joined: 19 May 2016 18:20

ChangeMACAddressBatch script

#1 Post by elias » 28 Jun 2016 13:15

Hello,

I wrote a neat script to change the MAC address of network adapters using Batch and the available supporting OS commands.

Where to get latest version: https://raw.githubusercontent.com/Passi ... sBatch.bat


Features:
[*] Change MAC address of online and offline network cards
[*] Revert / Reset MAC address
[*] Interactive menu
[*] Command line interface
[*] Developer mode for use with other programs

Enjoy!

Code: Select all

@echo off

:: --------------------------------------------------------------------------
::
:: Change MAC Address using Batch Files
::
:: (c) Elias Bachaalany <lallousz-x86@yahoo.com>
:: Authored with the help of the following book:
::       Batchography: The Art of Batch Files Programming
::
:main
    setlocal enabledelayedexpansion

    title ChangeMACAddressBatch v1.0 (c) lallouslab.net - The Batchography book

      :: Show help screen
   if "%1"=="help" (
      goto show-help
   )

   :: Get all relevant information
   call :get-interfaces-info iset iinfo ireg

   :: List adapters
   if "%1"=="list" (
      call :cmdline-list-adapters iset iinfo
      goto :eof
   )

   :: From here and on, operations require administrative privileges
   call :check-privilege-and-instruct
   if %errorlevel%==0 (
      pause
      goto :eof
   )

   :: If no arguments are passed, then start the interactive menu
   if "%1"=="" (
      call :check-privilege-and-abort
      call :main-menu iset iinfo
      pause
      goto :eof
   )

   :: Change adapter MAC address
   if "%1"=="change" (
      call :cmdline-change-mac-address iinfo "%~2"  "%~3"
      goto :eof
   )

   if "%1"=="reset" (
      call :cmdline-reset-mac-address iinfo "%~2"
      goto :eof
   )

:: --------------------------------------------------------------------------
::
:: Command line handler to reset an adapter's MAC address
::
:cmdline-reset-mac-address <1=iinfo> <2=adapater> <3=new mac>
   echo Resetting "%~2"'s MAC address to factory settings
   call :reset-mac-address "%~1" "%~2"

   goto :eof


:: --------------------------------------------------------------------------
::
:: Command line handler to change an adapter's MAC address
::
:cmdline-change-mac-address <1=iinfo> <2=adapater> <3=new mac>
   set __t=%~3
   set __t=%__t:-=%
   echo Changing "%~2"'s MAC address to "%~3"
   call :change-mac-address "%~1" "%~2" "%__t%"

   goto :eof


:: --------------------------------------------------------------------------
::
:: Command line handler to list all detected adapters
::
:cmdline-list-adapters <1=iset> <2=iinfo>
   echo.
   echo Adapters friendly names list:
   echo -------------------------------

   :: For each interface, return the physical address and the adapter name
   for /f "tokens=2 delims=.=" %%a in ('set %~1.') do (
      set __t=!%~2[%%a].mac!
      echo MAC Address: [!__t!] ^| Adapter name: %%a
   )

   goto :eof

:: --------------------------------------------------------------------------
::
:: Check for admin privilege then display instructions if needed
::
:check-privilege-and-instruct
   net session >nul 2>&1
   if %errorlevel% equ 0 exit /b 1

   call :show-banner
   echo.
   echo The %~nx0 script requires administrative privileges to run:
   echo.
   echo 1. If you are starting it from the Windows Explorer, then Right-click
   echo    on the %~nx0 script and choose "Run as administrator"
   echo.
   echo 2. If you are running it from the command prompt, then make sure you
   echo    start a new elevated command prompt and try again.
   echo.
   echo On Windows 8 and above, to start an elevated command prompt press the Win+X key
   echo and then choose "Command Prompt (Admin)".
   echo.
   echo.
   exit /b 0

:: --------------------------------------------------------------------------
::
:: Show banner
::
:show-banner
   echo   -----================================================================================------
    echo.
    echo      Change the MAC address of network adapters - Batch file script v1.0
    echo.                     Copyright (c) by Elias Bachaalany - lallouslab.net
    echo.
    echo           Inspired by the book "Batchography: The Art of Batch Files Programming"
    echo.
   echo   -----================================================================================------
   echo.
    exit /b


:: --------------------------------------------------------------------------
::
:: Help
::
:show-help
   call :show-banner
   echo Usage:
   echo ---------
   echo.
   echo %~n0 list
   echo  -- Lists all adapters
   echo.
   echo %~n0 change "Adapter Name" "New MacAddress"
   echo  -- Changes an adapter's MAC address
   echo.
   echo %~n0 reset "Adapter Name"
   echo  -- Resets an adapater's MAC address
   echo.
   echo.
   exit /b


:: --------------------------------------------------------------------------
::
:: Main interactive menu
::
:main-menu <1=iset> <2=iinfo>
   :main-menu-repeat
   cls
   call :show-banner
   echo.
   echo Please choose adapter:
   echo ------------------------

   set __choices=Q
   for /f "tokens=2 delims=.=" %%a in ('set %~1.') do (
      call set __num=%%%~2[%%a].index%%
      set __choices=!__choices!!__num!
      set __c2i[!__num!]=%%a
      echo !__num!^) %%a
   )
   echo.
   echo Q^) Quit
   
   set /p=">" <nul
   choice /C:%__choices% >nul
   set /a __num=%errorlevel%-1
   if %__num%==0 (
      exit /b 0
   )

   set adapter=!__c2i[%__num%]!
   call :adapter-menu "%~2" "%adapter%"

   goto main-menu-repeat


:: --------------------------------------------------------------------------
::
:: Adapter menu
::
:adapter-menu <1=iinfo> <2=adapter>
   cls

   call set __CurMac=%%%~1[%~2].mac%%
   call :show-banner
   echo Adapter information:
   echo ---------------------
        echo Friendly Name     :  %~2
   call echo Adapter Name      :  %%%~1[%~2].adapter%%
        echo MAC Address       :  %__CurMac%
   call echo Connection status :  %%%~1[%~2].state%%
   echo.
   echo Please choose action:
   echo   ^(C^) Change MAC Address
   echo   ^(R^) Reset MAC address
   echo   ^(B^) Back to main menu

   set /p=">" <nul
   choice /C:"BCR" >nul
   set __option=%errorlevel%

   :: Go back to main menu
   if %__option%==1 (
      exit /b 0
   )

   :: Change MAC address
   if %__option%==2 (
      :: Prompt and validate a new MAC address
      call :prompt-new-mac-address !__CurMac! __NewMac

      :: User cancelled?
      if !errorlevel!==0 (
         goto :eof
      )
      :: Now change the MAC address
      echo Changing MAC address to !__NewMac!
      call :change-mac-address iinfo "%~2" !__NewMac!

      set /p="Adapater MAC address changed. Press any key to go back to the main menu..."<nul
      pause >nul
   )

   :: Reset MAC address
   if %__option%==3 (
      echo.
      choice /C:YN /M "Are you sure you want to reset the MAC address to its default/original value"
      :: User canceled
      if !errorlevel!==2 (
         goto :eof
      )
      :: Reset the MAC address
      echo Resetting MAC address...
      call :reset-mac-address iinfo "%~2"
      pause
   )
   goto :eof


:: --------------------------------------------------------------------------
::
:: Prompt and validate for a new MAC address
::
:prompt-new-mac-address <1=curmac> <2=newmac> => errorlevel(0=cancel, 1=ok)
   echo.
   echo.
   echo The standard (IEEE 802) format for printing MAC-48 addresses in human-friendly form is six groups of
   echo two hexadecimal digits, separated by hyphens (-).
   echo.
   echo Very Important
   echo ---------------
   echo Note: If you are changing the MAC address of a Wireless adapater then make sure the first two hexadecimal
   echo       digits are "02" or "06", otherwise the adapter MAC address changes won't take effect.
   echo.
   echo Example MAC addresses formats include:
   echo     02-1A-11-2C-24-9D ^<-- Starts with "02" for a Wireless adapater
   echo     50-8A-CB-86-CA-AA
   echo     06-24-65-1D-C3-A2 ^<-- Starts with "06" for a Wireless adapater
   echo     00-0C-07-FC-94-08
   echo     1C-FC-BB-DB-6C-67
   echo.
   echo.   
   :prompt-new-mac-address-repeat
      echo Old MAC address: %~1
      set /p __NewMAC="New MAC address: "

      echo.
      choice /C:YN /M "Are you sure you want to change the MAC address "
      if %errorlevel%==2 (
         exit /b 0
      )
      :: Replace hyphenes
      set __NewMAC=%__NewMAC:-=%

      :: Check the proper length (too short)
      if ".%__NewMAC:~11,1%" EQU "." (
         echo.
         echo *** MAC address value too short ***
         echo.
         :: Repeat the prompt
         goto prompt-new-mac-address-repeat
      )
      :: Too long
      if ".%__NewMAC:~12,1%" NEQ "." (
         echo.
         echo *** MAC address value too long ***
         echo.
         goto prompt-new-mac-address-repeat
      )

   :: Update caller's value
   set %~2=%__NewMAC%

   :: Check if the value has changed or not
   set __t=%~1
   set __t=%__t:-=%
   if "%__NewMAC%"=="%__t%" (
      exit /b 0
   )

   :: Return success
   exit /b 1


:: --------------------------------------------------------------------------
::
::Reset MAC address for a given adapter
::
:reset-mac-address <1=iinfo> <2=adapter>
   set __t=!%~1[%~2].reg!
   reg delete "%__t%" /F /V NetworkAddress >nul 2>&1

   :: Refresh the interface
   call :refresh-interface "%~1" "%~2"
   goto :eof


:: --------------------------------------------------------------------------
::
:: Change MAC address
::
:change-mac-address <1=iinfo> <2=adapter> <3=NewMac>
   set __t=!%~1[%~2].reg!
   reg add "%__t%" /F /V NetworkAddress /T REG_SZ /D %~3 >nul 2>&1

   :: Refresh the interface
   call :refresh-interface "%~1" "%~2"
   goto :eof


:: --------------------------------------------------------------------------
::
:: Re=enables interface by bringing it down then up again
::
:refresh-interface <1=iinfo> <2=adapter>
   :: Bring the interface down
   netsh interface set interface "%~2" disable
   :: Bring it up again
   netsh interface set interface "%~2" enable

   :: Refresh the internal information
   call set __t=%%%~1.name%%
   call :get-interfaces-info "%__t%" "%~1" ireg

   goto :eof


:: --------------------------------------------------------------------------
::
:: Get all relevant (combined) interfaces information
::
:get-interfaces-info <1=set-name> <2=iinfo> <3=ireg>
   :: Cache the set-name
   set %~2.name=%~1

   :: Get ipconfig information
   call :get-interfaces-ipconfig-info "%~2" "%~1"

   :: Get the interface registry key information
   call :get-interfaces-reg-keys "%~3"

   set /a __num=1
   :: Link the interface registry key information with the interface info
   for /f "tokens=2 delims=.=" %%a in ('set iset.') do (
      :: Get adapter name
      set __t=!iinfo[%%a].adapter!
      :: Get the ireg key name
      set __v=%~3[!__t!]
      :: Get the ireg key value
      call set __t=%%!__v!%%

      :: Patch-in the registry path into the iinfo
      set %~2[%%a].reg=!__t!

      :: Set a one-based index
      set %~2[%%a].index=!__num!
      set /a __num+=1
   )

   goto :eof


:: --------------------------------------------------------------------------
::
:: Get interfaces registry key pathes into an associative array
:: Scan for both "DriverDesc" and "adapterModel" (in the case of WiFi drivers)
::
:get-interfaces-reg-keys <1=arr>
   call :get-interfaces-reg-keys-ex "%~1" "DriverDesc" 6 "Driver"
   call :get-interfaces-reg-keys-ex "%~1" "AdapterModel" 7 "Adapter"
   goto :eof


::
:: Get interfaces registry key pathes into an associative array
:: (the a-array's key is the driver description (aka the adapter name))
::
:get-interfaces-reg-keys-ex <1=arr> <2=KeyName> <3=MatchLen> <4=MatchVal>
   for /f "tokens=*" %%a in (
      'reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}" /v "%~2" /s 2^>nul'
      ) do (
      set __t=%%a
      if "!__t:~0,10!"=="HKEY_LOCAL" (
         set __regkey=%%a
      )
      if "!__t:~0,%3!"=="%~4" (
         for /f "tokens=2*" %%b in ("%%a") do (
            set %~1[%%c]=!__regkey!
         )
      )
   )
   set __regkey=
   set __t=

   goto :eof


:: --------------------------------------------------------------------------
::
:: Get interfaces information from the ipconfig output
::
:get-interfaces-ipconfig-info <1=arr> <2=interfaces-set>
   :: Return interface friendly names
   call :get-interfaces-netsh-info %~1

   :: For each interface, return the physical address and the adapter name
   for /f "tokens=1,2 delims=][" %%a in ('set %~1[') do (
      call :get-interface-info %~1 "%%b"
      set %~2.%%b=1
   )

   exit /b 0


:: --------------------------------------------------------------------------
::
:: Get interface information (adapter name and physical address)
::
:get-interface-info <1=arr> <2=name>
   set /a __stage=0
   for /f "tokens=*" %%a in ('ipconfig /all') do (
      set __var=%%a
      if !__stage! equ 0 (
         set __t=!__var:*adapter %~2:=!
         if "!__t!" NEQ "!__var!" (
            set /a __stage=1
         )
      )
      if !__stage! EQU 1 (
         set __t=!__var:Description . . . . . . . . . . . : =!
         if "!__t!" NEQ "!__var!" (
            set %~1[%~2].adapter=!__t!
            set /a __stage+=1
         )
      )
      if !__stage! EQU 2 (
         set __t=!__var:Physical Address. . . . . . . . . : =!
         if "!__t!" NEQ "!__var!" (
            set %~1[%~2].mac=!__t!
            set /a __stage+=1
         )
      )
   )
   :: Clear work variables
   set __stage=
   set __var=
   set __t=

   goto :eof


:: --------------------------------------------------------------------------
::
:: Return the interfaces information from the netsh command
::
:get-interfaces-netsh-info <1=arr>
   FOR /F "tokens=2,3*" %%a in ('netsh interface show interface') do (
      if /i "%%a" neq "State" (
         set %1[%%c].state=%%a
      )
   )
   exit /b 0


mirrormirror
Posts: 129
Joined: 08 Feb 2016 20:25

Re: ChangeMACAddressBatch script

#2 Post by mirrormirror » 01 Jul 2016 21:19

Thank you for posting your script for us all. I currently do not have a use for it but will keep it in my library.

Post Reply