Hi,
some time ago I looked for a tool which will check a given list of netork cards in a computer if the LAN cable is plugged in. Depending of the cable status one or more other network connections should be en- or disabled.
I found some pieces of code which I could pack together and wrote the rest ofr this to work.
I need this tool because we have some WLAN access points and notebooks with port replicators. The replicator is connect to the local ethernet network. The WLAN access points and the Ethernet switches share the same IP domain so having a notebook with both active Ethernet and WLAN may cause trouble. The notebooks have a switch to turn WLAN off but sometimes someone will forget this. Our older DELL notebooks have a driver which will provide this function. But the newer notebooks wont.
You also have to download the COM.zip from this page
COM Standard Library and extract com.ahk into the same directory you put LANSwitcher.ahk.
LANSwitcher.ahk:
Code:
; LAN-Switcher
; AutoHotkey Version: 1.0.47.06
; Language: English / German
; Platform: Windows XP, Windows 7
; Author: Nils Winkler <nils.winkler@rheinchemie.com>
;
; Script Function:
; Load hardware ID's from the ini file, check network connections for unplugged
; cables and enable or disable other network connections.
;
; used scripts from www.autohotkey.com
; http://www.autohotkey.com/forum/topic18720.html
; http://www.autohotkey.com/forum/topic39033.html
;
; Using the COM.ahk script found here:
; http://www.autohotkey.com/forum/topic22923.html
;
; 2009-01-09: version 1.00
; 2009-01-14: version 1.01: reload after standby and hibernation
; 2009-03-06: version 1.02: - fixed a bug with more than one entry in ini file
; - show configuration entry for the tray icon added
; - added autorun entry (enable / disable and a part in the ini file
; for just display autorun status)
; - added ini parameter for allowing exiting this program
; 2009-03-10: version 1.03: - fixed a bug with reloading the script after wakeup from standby
; 2009-04-03: version 1.04: - fixed a bug with recognizing the cable status and WLAN enabling after restart
; 2009-04-17: version 1.05: restart after standby or hibernation using goto
; 2009-11-24: version 1.06: support for Windows 7
; 2010-01-14: version 1.07: - change "start on logon" for Windows 7 using task scheduler
; - check for administrative rights on start
#Include COM.ahk
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Singleinstance force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
Start:
; configuration file
INIFILE = LANSwitcher.ini
; AHK min. version required
MINAHKVERSION = 1.0.47.00
; LAN-Switcher version
VERSION = 1.07
; detect Windows GUI language, for a MUI installation other keys were used
RegRead, GUI_Language, HKEY_CURRENT_USER, Control Panel\Desktop, MultiUILanguageId
If ErrorLevel
RegRead, GUI_Language, HKEY_CURRENT_USER, Control Panel\International, Locale
StringRight, GUI_Language, GUI_Language, 4 ; the string has 8 characters
If GUI_Language in 0407,0807,0c07,1007,1407 ; german
{
CONNENABLE = &Aktivieren
CONNDISABLE = &Deaktivieren
EXITPROGRAM = LAN-Switcher beenden
TRAYTOOLTIP = LAN-Switcher
SHOWCONFIG = Konfiguration anzeigen
CONFIGLANCHECK = Überwache folgende Netzwerkschnittstelle(n):
CONFIGLANSWITCH = Schalte folgende Netzwerkverbindung(en) um:
AUTORUN = automatisch mit Windows starten
ABOUT = Über LAN-Switcher
ABOUTTEXT = LAN-Switcher v %VERSION%
ERROR = Fehler:
ONLYXP = Das Programm benötigt min. Windows.
AHKVERSION = Das Programm benötigt min.`nAutoHotKey Version %MINAHKVERSION%.
INIFILEDOESNOTEXIST = Die Konfigurationsdatei`n`"%INIFILE%`" wurde nicht gefunden.
LANCHECKCOUNTZERO = Im Abschnitt [LANCheck] der Konfigurationsdatei`n`"%INIFILE%`" wurde keine ID1 gefunden.
LANSWITCHCOUNTZERO = Im Abschnitt [LANSwitch] der Konfigurationsdatei`n`"%INIFILE%`" wurde keine ID1 gefunden.
NOLANCHECKLEFT = Keine der im Abschnitt [LANCheck]`nangegebenen ID's wurde gefunden.
NOLANSWITCHLEFT = Keine der im Abschnitt [LANSwitch]`nangegebenen ID's wurde gefunden.
NOADMIN = Dieses Programm muß mit Administratoren-Rechten gestartet werden.
}
Else If GUI_Language in 0409,0809,0c09,1009,1409,1809,1c09,2009,2409,2809,2c09,3009,3409 ; english
{
CONNENABLE = En&able
CONNDISABLE = Disa&ble
EXITPROGRAM = Exit LAN switcher
TRAYTOOLTIP = LAN switcher
SHOWCONFIG = Show configuration
CONFIGLANCHECK = Monitoring the following network interface(s):
CONFIGLANSWITCH = Switching the follwing network connection(s):
AUTORUN = start with Windows automatically
ABOUT = About LAN switcher
ABOUTTEXT = LAN switcher v %VERSION%
ERROR = Error:
ONLYXP = This prorgam needs at least Windows XP.
AHKVERSION = This program requires at least`nAutoHotKey version %MINAHKVERSION%.
INIFILEDOESNOTEXIST = The configuration file "%INIFILE%" could not be found.
LANCHECKCOUNTZERO = No ID1 found in section [LANCheck]`nin the configuration file`n"%INIFILE%`".
LANSWITCHCOUNTZERO = No ID1 found in section [LANSwitch]`nin the configuration file`n"%INIFILE%`".
NOLANCHECKLEFT = None of the IDs in section [LANCheck]`ncould be found.
NOLANSWITCHLEFT = None of the IDs in section [LANSwitch]`ncould be found.
NOADMIN = This program has to be started with administrative rights.
}
Else ; language is not supported
{
MsgBox, 16, Error:, The GUI language is not supported.`nPlease contact the author.`n`nFound language id: %GUI_Language%
ExitApp
}
If Not A_IsAdmin
{
MsgBox, %NOADMIN%
ExitApp
}
;---------------------------------------------------------------
; do some error checks
;---------------------------------------------------------------
; only tested with Windows XP
If A_OSVersion <> WIN_XP
{
If A_OSVersion <> WIN_VISTA
{
MsgBox, 16, %ERROR%, %ONLYXP%
ExitApp
}
}
; check the AutoHotKey version
If A_AhkVersion < %MINAHKVERSION%
{
MsgBox, 16, %ERROR%, %AHKVERSION%
ExitApp
}
; check if the ini file exist
IfNotExist, %INIFILE%
{
MsgBox, 16, %ERROR%, %INIFILEDOESNOTEXIST%
ExitApp
}
;---------------------------------------------------------------
; read the ini file and count the number of devices to be checked
;---------------------------------------------------------------
LANCheckCount = 0
Loop
{
IniRead, tmp1, %INIFILE%, LANCheck, ID%A_Index%, ""
StringUpper, tmp1, tmp1
If tmp1 = ""
break
LANCheck%A_Index% = %tmp1%
LANCheckPlugged%A_Index% = 0
LANCheckCount = %A_Index%
}
; error check
If LANCheckCount = 0 ; no hardware ID for checking is found
{
MsgBox, 16, %ERROR%, %LANCHECKCOUNTZERO%
ExitApp
}
;---------------------------------------------------------------
; read the ini file and count the number of devices to be enabled or disabled
;---------------------------------------------------------------
LANSwitchCount = 0
Loop
{
IniRead, tmp1, %INIFILE%, LANSwitch, ID%A_Index%, ""
StringUpper, tmp1, tmp1
If tmp1 = ""
break
LANSwitch%A_Index% = %tmp1%
LANSwitchCount = %A_Index%
}
; error check
If LANSwitchCount = 0 ; no hardware ID for switching is found
{
MsgBox, 16, %ERROR%, %LANSWITCHCOUNTZERO%
ExitApp
}
;---------------------------------------------------------------
; read the device description from the registry
;---------------------------------------------------------------
LoopDevicesKey = SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
ConnectionsKey = SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}
; => connection\Name
; => connection\PnpInstanceID = ID
Loop, HKLM, %LoopDevicesKey%, 2
{
RegRead, Characteristics, HKLM, %LoopDevicesKey%\%A_LoopRegName%, Characteristics
If ( Characteristics = 132 )
{
; Characteristics = 132 --> 'network adapter' found --> read adapter name
RegRead, tmp1, HKLM, %LoopDevicesKey%\%A_LoopRegName%, DriverDesc
; read the component device id from the registry
RegRead, tmp2, HKLM, %LoopDevicesKey%\%A_LoopRegName%, ComponentId
StringUpper, tmp2, tmp2
; test if the device id is in the LAN list to the devices to be checked
Loop, %LANCheckCount%
{
test := SubStr( tmp2, 1, StrLen( LANCheck%A_Index% ))
test2 := LANCheck%A_Index%
If test = %test2%
LANCheckName%A_Index% = %tmp1%
}
; test if the device id is in the LAN list of the devices to be switched
Loop, %LANSwitchCount%
{
test := SubStr( tmp2, 1, StrLen( LANSwitch%A_Index% ))
test2 := LANSwitch%A_Index%
If test = %test2%
LANSwitchName%A_Index% = %tmp1%
}
}
}
test =
test2 =
;---------------------------------------------------------------
; remove all entries from the LANCheck array wich don't have a name yet
;---------------------------------------------------------------
actPos = 1
Loop
{
nameCheck := LANCheckName%actPos%
If ( nameCheck = "" )
{
; LANCheckName is empty, delete this record
delCount := LANCheckCount - actPos
actCopyPos := actPos
Loop, %delCount%
{
actDelPos := actPos + A_Index - 1
actCopyPos := actDelPos + 1
LANCheck%actDelPos% := LANCheck%actCopyPos%
LANCheckPlugged%actDelPos% := LANCheckPlugged%actCopyPos%
LANCheckName%actDelPos% := LANCheckName%actCopyPos%
}
LANCheckCount -= 1
LANCheck%actCopyPos% =
LANCheckPlugged%actCopyPos% =
LANCheckName%actCopyPos% =
actDelPos =
actCopyPos =
delCount =
}
Else
{
actPos += 1
}
If (actPos > LANCheckCount)
break
If ( LANCheckCount = 0 )
break
}
nameCheck =
; check if there is any hardware id left
If LANCheckCount = 0
{
MsgBox, 16, %ERROR%, %NOLANCHECKLEFT%
ExitApp
}
;---------------------------------------------------------------
; remove all entries from the LANSwitch array wich don't have a name yet
;---------------------------------------------------------------
actPos = 1
Loop
{
nameCheck := LANSwitchName%actPos%
If ( nameCheck = "" )
{
; LANSwitchName is empty, delete this record
delCount := LANSwitchCount - actPos
actCopyPos := actPos
Loop, %delCount%
{
actDelPos := actPos + A_Index - 1
actCopyPos := actDelPos + 1
LANSwitch%actDelPos% := LANSwitch%actCopyPos%
LANSwitchName%actDelPos% := LANSwitchName%actCopyPos%
}
LANSwitchCount -= 1
LANSwitch%actCopyPos% =
LANSwitchName%actCopyPos% =
actDelPos =
actCopyPos =
delCount =
}
Else
{
actPos += 1
}
If (actPos > LANSwitchCount)
break
If ( LANSwitchCount = 0 )
break
}
nameCheck =
; check if there is any hardware id left
If LANSwitchCount = 0
{
MsgBox, 16, %ERROR%, %NOLANSWITCHLEFT%
ExitApp
}
;---------------------------------------------------------------
; read the connection names from the registry
;---------------------------------------------------------------
Loop, HKLM, %ConnectionsKey%, 2
{
RegRead, PnpInstanceID, HKLM, %ConnectionsKey%\%A_LoopRegName%\Connection, PnpInstanceID
RegRead, ConnName, HKLM, %ConnectionsKey%\%A_LoopRegName%\Connection, Name
Loop, %LANSwitchCount%
{
test := SubStr( PnpInstanceID, 1, StrLen( LANSwitch%A_Index% ))
test2 := LANSwitch%A_Index%
If test = %test2%
LANSwitchConnName%A_Index% = %ConnName%
}
}
;---------------------------------------------------------------
; remove all entries from the LANSwitch array wich are not used in an network connection
;---------------------------------------------------------------
actPos = 1
Loop
{
nameCheck := LANSwitchConnName%actPos%
If ( nameCheck = "" )
{
; LANSwitchConnName is empty, delete this record
delCount := LANSwitchCount - actPos
actCopyPos := actPos
Loop, %delCount%
{
actDelPos := actPos + A_Index - 1
actCopyPos := actDelPos + 1
LANSwitch%actDelPos% := LANSwitch%actCopyPos%
LANSwitchName%actDelPos% := LANSwitchName%actCopyPos%
}
LANSwitchCount -= 1
LANSwitch%actCopyPos% =
LANSwitchName%actCopyPos% =
actDelPos =
actCopyPos =
delCount =
}
Else
{
actPos += 1
}
If (actPos > LANSwitchCount)
break
If ( LANSwitchCount = 0 )
break
}
nameCheck =
; check if there is any hardware id left
If LANSwitchCount = 0
{
MsgBox, 16, %ERROR%, %NOLANSWITCHLEFT%
ExitApp
}
;---------------------------------------------------------------
; create a custom tray menu
;---------------------------------------------------------------
Menu, Tray, NoStandard
Menu, Tray, Icon, Shell32.dll, 174
Menu, Tray, Tip, %TRAYTOOLTIP%
Menu, Tray, Add, %ABOUT%, About
Menu, Tray, Add, %SHOWCONFIG%, ShowConfig
Menu, Tray, Add, %AUTORUN%, SwitchAutoRun
Menu, Tray, Add
Menu, Tray, Add, %EXITPROGRAM%, ExitProgram
; check if switching the autorun is allowed in .ini file
IniRead, allowToggleAutorun, %INIFILE%, General, AllowToggleAutorun, ""
If allowToggleAutorun != 1
Menu, Tray, Disable, %AUTORUN%
; check if autorun is enabled
If A_OSVersion < %WIN_VISTA%
{
RegRead, autoRunVal, HKLM, %autoRunKey%, LANSwitcher
If autoRunVal !=
Menu, Tray, Check, %AUTORUN%
}
Else
{
RunWait, %A_WinDir%\System32\schtasks.exe /Query /TN LANSwitcher,, UseErrorLevel HIDE
If ErrorLevel = 0
Menu, Tray, Check, %AUTORUN%
}
; check if exiting this program is allowed in .ini file
IniRead, allowExit, %INIFILE%, General, AllowExit, ""
If allowExit != 1
Menu, Tray, Disable, %EXITPROGRAM%
;---------------------------------------------------------------
; initialize the program
;---------------------------------------------------------------
; set a low priority for this process
Process, priority, , Low
; initialize COM
COM_Init()
; wake up from standby or hibernation?
OnMessage(0x218,"WM_POWERBROADCAST")
;---------------------------------------------------------------
; check if cables are plugged in
; set the LANCheckPlugged variables to a false value
; so the main loop will recognize a change...
;---------------------------------------------------------------
Loop, %LANCheckCount%
{
If CablePlugged( LANCheckName%A_Index% )
{
LANCheckPlugged%A_Index% = 0
}
Else
{
LANCheckPlugged%A_Index% = 1
}
}
;---------------------------------------------------------------
; main loop
;---------------------------------------------------------------
Loop
{
Loop, %LANCheckCount%
{
If CablePlugged( LANCheckName%A_Index% )
{
; cable plugged in
If LANCheckPlugged%A_Index% = 0
{
Loop, %LANSwitchCount%
{
NetConnect( 0, LANSwitchConnName%A_Index%, CONNENABLE, CONNDISABLE )
}
LANCheckPlugged%A_Index% = 1
}
}
Else
{
; cable unplugged
If LANCheckPlugged%A_Index% = 1
{
Loop, %LANSwitchCount%
{
NetConnect( 1, LANSwitchConnName%A_Index%, CONNENABLE, CONNDISABLE )
}
LANCheckPlugged%A_Index% = 0
}
}
}
Sleep, 5000
}
;---------------------------------------------------------------
; exit application
ExitProgram:
; uninitialize COM
COM_Term()
ExitApp
;---------------------------------------------------------------
About:
MsgBox, 0, %TRAYTOOLTIP%, %ABOUTTEXT%
Return
;---------------------------------------------------------------
ShowConfig:
msg = %CONFIGLANCHECK%
Loop, %LANCheckCount%
{
tmpMsg := LANCheckName%A_Index%
msg = %msg%`n%tmpmsg%
}
msg = %msg%`n`n%CONFIGLANSWITCH%
Loop, %LANSwitchCount%
{
tmpMsg := LANSwitchConnName%A_Index%
msg = %msg%`n%tmpmsg%
tmpMsg := LANSwitchName%A_Index%
msg = %msg%`n(%tmpmsg%)
}
MsgBox, 0, %TRAYTOOLTIP%, %msg%
tmpMsg =
msg =
Return
;---------------------------------------------------------------
; switch the auto run registry entry
SwitchAutoRun:
; use an other method to run LANSwitcher on Vista or newer OS
If A_OSVersion < %WIN_VISTA%
{
RegRead, autoRunVal, HKLM, %autoRunKey%, LANSwitcher
If autoRunVal =
{
Menu, Tray, Check, %AUTORUN%
RegWrite, REG_SZ, HKLM, %autoRunKey%, LANSwitcher, "%A_ScriptFullPath%"
}
Else
{
Menu, Tray, UnCheck, %AUTORUN%
RegDelete, HKLM, %autoRunKey%, LANSwitcher
}
}
Else
{
; use a scheduled task on VISTA or newer because the program need elevated access rights to run
EnvGet, dom, USERDOMAIN
If dom =
username = %A_UserName%
Else
username = `"%dom%\%A_UserName%`"
RunWait, %A_WinDir%\System32\schtasks.exe /Query /TN LANSwitcher,, UseErrorLevel HIDE
If ErrorLevel = 0
RunWait, %A_WinDir%\System32\schtasks.exe /Delete /TN LANSwitcher /F,, UserErrorLevel HIDE
Else
RunWait, %A_WinDir%\System32\schtasks.exe /Create /TN LANSwitcher /TR "\"%A_ScriptFullPath%\"" /SC ONLOGON /RL HIGHEST /F /RU %username%,, UserErrorLevel HIDE
RunWait, %A_WinDir%\System32\schtasks.exe /Query /TN LANSwitcher,, UseErrorLevel HIDE
If ErrorLevel = 0
Menu, Tray, Check, %AUTORUN%
Else
Menu, Tray, UnCheck, %AUTORUN%
}
Return
;---------------------------------------------------------------
; check if a network cable is plugged in
;---------------------------------------------------------------
CablePlugged( NetworkCardDescription )
{
; SubStr() to remove a tailing newline
CablePlugged := !SubStr( WMI_Query( "\\.\root\WMI", "MSNdis_MediaConnectStatus WHERE InstanceName='" . NetworkCardDescription . "'", "NdisMediaConnectStatus" ), 1, 1 )
Return CablePlugged
}
NetConnect( bEnable = False, sConnection = "Network Connections", ConnEnable = "", ConnDisable = "" )
{
psh := COM_ActiveXObject( "Shell.Application" )
pns := COM_Invoke_( psh, "Namespace", 3, CSIDL_Connections := 0x0031 )
pitems := COM_Invoke( pns, "Items" )
Loop, % COM_Invoke( pitems, "Count" )
{
pid := COM_Invoke_( pitems, "Item", 3, A_Index - 1 )
If ( COM_Invoke( pid, "Name" ) = sConnection )
{
bRes := True
Break
}
COM_Release( pid )
}
If !bRes
Return
pverbs := COM_Invoke( pid, "Verbs" )
pvb := COM_Invoke_( pverbs, "Item", 3, nVB := 0 )
If pvb
{
sVerbName := COM_Invoke( pvb, "Name" )
tmp1 := InStr( sVerbName, ConnEnable )
tmp2 := InStr( sVerbName, ConnDisable )
If ( bEnable && InStr( sVerbName, CONNENABLE )) || ( !bEnable && InStr( sVerbName, CONNDISABLE ))
COM_Invoke( pvb, "DoIt" )
WinWait, %sConnection% ahk_class #32770,, 1
WinWaitClose
COM_Release( pvb )
}
COM_Release( pverbs )
COM_Release( pid )
COM_Release( pitems )
COM_Release( pns )
COM_Release( psh )
}
;------------------------------------------------------------------------------
; WMI_Query()
; by Sean
; http://www.autohotkey.com/forum/topic16632.html
;------------------------------------------------------------------------------
WMI_Query( Namespace, Class, Property = "" )
{
psvc := COM_GetObject( "winmgmts:{impersonationLevel=impersonate}!" . Namespace )
pset := COM_Invoke( psvc, "ExecQuery", "SELECT * FROM " . Class )
penm := COM_Invoke( pset, "_NewEnum" )
Loop, % COM_Invoke( pset, "Count" )
If COM_Enumerate( penm, pobj ) = 0
{
If Not Property
MsgBox % COM_Invoke(pobj, "GetObjectText_")
Else
sResult .= COM_Invoke( pobj, Property ) . "`n"
COM_Release( pobj )
}
COM_Release( penm )
COM_Release( pset )
COM_Release( psvc )
Return sResult
}
; wake up from standby or hibernation => reload the script
WM_POWERBROADCAST( wparam, lparam, msg, hwnd ){
if ( wparam = 7 or wparam = 18 )
{
SetTimer, WaitAndRestart, 5000
}
}
; After waking up from hibernation or standby restart the script to
; reinitialize. Also pass all given parameters to the new instance of
; the script, as first parameter set "/restart".
WaitAndRestart:
Goto Start
And this is my first LANSwitcher.ini:
Code:
[LANCheck]
ID1=pci\ven_8086&dev_10f5
ID2=PCI\VEN_14E4&DEV_16A6&SUBSYS_81261028
ID3=PCI\VEN_14E4&DEV_1677&SUBSYS_01821028
ID4=PCI\VEN_14E4&DEV_1600&SUBSYS_01C21028
[LANSwitch]
ID1=PCI\VEN_8086&DEV_4236&SUBSYS_10118086
ID2=PCI\VEN_14E4&DEV_4320&SUBSYS_00011028
ID3=PCI\VEN_14E4&DEV_4320&SUBSYS_00031028
ID4=PCI\VEN_14E4&DEV_4312&SUBSYS_00071028
[General]
AllowToggleAutorun=0
AllowExit=0
The IDs can be read from the devices in the device manager. Open the network device, switch to the "Details" tab and select "Device instance id" (usually this is selected by default). Here you will find an id which you can write into the ini file. You don't have to copy the whole text, just from beginning to SUBSYS_... should be enough.
[General]
If the parameter "AllowToggleAutorun" is be set to 1, the user is able to toggle the autorun. Therefore the registry is used. Setting the parameter to any other value disables this feature.
If the parameter "AllowExit" is set to 1, the user can exit this program. Setting the parameter to anything else disables the exit entry in the tray menu.
Best regards, Nils.
Edit: update to version 1.0.2 on march, 6th, 2009
Edit: update to version 1.0.4 on april, 3rd, 2009
Edit: update to version 1.0.7 on january, 15th, 2010