We are in the midst of deploying a WPA2-Enterprise wireless network here at UVM. During the testing process we have discovered that although domain-joined computers have no trouble using the network (out-of-box settings don’t work very well, but we are pushing profiles using Group Policy to make easy for our clients), stand-alone workstations need very specific WiFi settings that are not overly intuitive.
I decided to see if I could automate installation of wireless profiles using a script. Three days later, I have the outline of something that appears to work…
Below you will find a VBScript that performs the following procedures:
- Detects the operating system platform and Service Pack levels
- Installs the trusted root certificate that is used by our RADIUS server if it is not already present. The script calls the “certmgr.exe” tool, available from the Windows Platform SDK (I suppose I could have used CAPICOM, but why should I torture myself?)
- On Windows XP, uses the free utility “zwlancfg.exe” written by ENGL to install our WPA2-Enterprise wireless profile. The script will install the KB918997 HotFix if it is not already present. This HotFix adds the WiFi API to Windows, allowing programmatic configuration of wireless on XP Service Pack 2 (Note: XP Service Pack 3 includes this HotFix).
(I configured a WiFi profile on my XP laptop then used the command:
zwlancfg.exe /export:”[profile name]”
to generate the XML profile called by the script. - On Windows Vista, we call “netsh wlan import profile” to import a WiFi profile that was generated using:
netsh wlan export profile –name:”[profile name]” –folder:”[export folder]”
No doubt there are smarter ways to do this, and essential script logic that I am missing. I welcome your feedback and recommendations on how this script can be enhanced. Code follows:
option explicit
'Install UVM WPA2 wireless profile
' Supported platforms: Windows Vista and XP with Service Pack 2 or 3
' Requires external tools: "zwlancfg.exe", "CertMgr.exe" (from the Windows Platform SDK), and HotFix installer for KB918997
' Requires external files: "IPS Servidores" root certificate file, XML configuration files for XP and Vista
' create constants
const cNetName = "wpa2"
const cLogFile = "uvm_wpa2.log"
' declare variants
dim oShell, oUserEnv, oFSO, oFile
dim iSPVer
dim sTempEnv, strComputer, sOS
dim bSuccess
'define variants
bSuccess = false
strComputer = "."
'instantiate global objects
set oShell = WScript.CreateObject("WScript.Shell")
set oFSO = CreateObject("Scripting.FileSystemObject")
sTempEnv = oShell.ExpandEnvironmentStrings("%TEMP%") & ""
set oFile = oFSO.CreateTextFile(sTempEnv & cLogFile,true)
fDetectOS sOS, iSPVer
if inStr(sOS, "Vista") > 0 then
subInstCert
subImpVistaProfile
elseif inStr(sOS, "XP") > 0 then
if iSPVer = 2 then
subXPPatch
subInstCert
subImpXPProfile
elseif iSPVer = 3 then
subInstCert
subImpXPProfile
else
oFile.WriteLine "Your operating system is not supported for use with this script."
WScript.Quit -4
end if
else
end if
oFile.close
'''''''''''''''''''''''''''''''''
''' begin environment cleanup '''
'''''''''''''''''''''''''''''''''
set oFile = nothing
set oFSO = nothing
set oUserEnv = nothing
set oShell = Nothing
''''''''''''''''''''''''''''''''''
''''' end environment cleanup ''''
''''''''''''''''''''''''''''''''''
function fDetectOS(sOS, iSPVer)
'Detect OS Function - detects OS Caption string and Service Pack integer from WMI WIN32_OperatingSystem.
'Expects to varibles passed, returns the full OS Caption String, and SP Major Version intger
'Declare variables
dim colItems
dim objWMIService, objItem
'Instantiate local objects/collections
Set objWMIService = GetObject("winmgmts:" & strComputer & "rootCIMV2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
For Each objItem in colItems
sOS = objItem.Caption
oFile.Write "Detected Operating System: " & sOS
iSPVer = cInt(objItem.ServicePackMajorVersion)
oFile.Write "Detected Service Pack Version: " & iSPVer
oFile.Write "Service Pack Minor Version: " & objItem.ServicePackMinorVersion
Next
'Clean local objects/variables
set objItem = nothing
set colItems = nothing
set objWMIService = nothing
end function
sub subImpVistaProfile
'Imports Vista Wireless Profile using NETSH command.
'Requires: a Vista wifi profile file exported using NETSH, defined in cVistaProfile within this function
const cVistaProfile = ".uvm-wpa2-test.xml"
const cUserScope = "all"
dim iStrMatch
dim oExec, oStdOut
dim sStdOutLine
oFile.WriteLine "Executing command: netsh wlan add profile filename=""" & cVistaProfile & """ user=" & cUserScope & ""
set oExec = oShell.Exec("netsh wlan add profile filename=""" & cVistaProfile & """ user=" & cUserScope & "")
set oStdOut = oExec.stdOut
While not oStdOut.AtEndOfStream
sStdOutLine = oStdOut.ReadLine
oFile.WriteLine(sStdOutLine)
iStrMatch = cInt(inStr(sStdOutLine, "Profile " & cNetName & " is added on interface"))
if iStrMatch > 0 then
WScript.Echo "The " & cNetName & " wireless profile was added successfully to your system"
elseif iStrMatch = 0 then
WScript.Echo "The wireless profile failed to import. Please see the manual profile " _
& "configuration instructions available at http://www.uvm.edu/ets/wireless/wpa/. A " _
& "log file named " & cLogFile & " which contains the full error message can be " _
& "found in the " & sTempEnv & " directory."
WScript.Quit -3
End If
Wend
set oStdOut = Nothing
set oExec = Nothing
end sub
sub subImpXPProfile
' Installs an XP wifi profile using zwlancfg.exe. Requires the HotFix KB918997 be installed on the system before running.
' Requires presence of xml wifi profile file defined in cXPProfile
const cXPProfile = ".wpa2.xml"
const cForReading = 1
Dim oZFile
Dim sZFile
oFile.WriteLine "Executing command: zwlancfg.exe /import:""" & cXPProfile & """ /log"
oShell.Run "zwlancfg.exe /import:""" & cXPProfile & """ /log", 1, true
set oZFile = oFSO.OpenTextFile("zwlancfg.log", cForReading)
sZFile = oZFile.ReadAll
oZFile.close
oFile.WriteLine "Output from zwlancfg.exe follows..."
oFile.Write sZFile
iStrMatch = cInt(inStr(sStdOutLine, "Profile added to interface"))
if iStrMatch > 0 then
bSuccess = true
WScript.Echo "The " & cNetName & " wireless profile was added successfully to your system"
else WScript.Echo "Import of the WPA2 profile for XP failed. Please see the manual profile " _
& "configuration instructions available at " _
& "http://www.uvm.edu/ets/wireless/wpa/. A log file named " & cLogFile & " which " _
& "contains the full error message can be found in the " & sTempEnv & " directory."
WScript.Quit -1
End If
end sub
sub subXPPatch
stop
const cHotFixID = "KB918997" 'IS THIS HOW THE HOTFIX IS DISPLAYED BY THE WMI QUERY? nEED TO TEST!!!
dim colItems
dim objWMIService, objItem
dim iRC
dim sHFOut
dim bHFPresent
bHFPresent = false
Set objWMIService = GetObject("winmgmts:" & strComputer & "rootCIMV2")
Set colItems = objWMIService.ExecQuery( _
"SELECT * FROM Win32_QuickFixEngineering",,48)
For Each objItem in colItems
sHFOut = objItem.HotFixID
if sHFOut = cHotFixID then
bHFPresent = True
end if
Next
oFile.WriteLine "QFE HotFix ID " & cHotFixID & " is present: " & bHFPresent
if bHFPresent = false then
oFile.WriteLine "We now will attempt to install QFE HotFix 918997."
iRC = oShell.Run("WindowsXP-KB918997-v6-x86-ENU.exe /passive /noreboot", 1, true)
oFile.WriteLine "Return code from HotFix installer: " & iRC
if iRC = 0 then 'IS THIS THE ACTUAL RETURN CODE FOR A SUCCESSFUL INSTALL???
WScript.Echo "A patch to your operating system was required to enable Wireless " _
& "access to the UVM network. The patch was applied successfully. Please reboot " _
& "your system and run this script again to complete Wireless configuration."
else WScript.Echo "Application of the required XP HotFix " & cHotFixID & " " _
& "failed. Please see the manual profile configuration instructions available at " _
& "http://www.uvm.edu/ets/wireless/wpa/. A log file named " & cLogFile & " which " _
& "contains the full error message can be found in the " & sTempEnv & " directory."
WScript.Quit -1
end if
end if
set objItem = nothing
set colItems = nothing
set objWMIService = nothing
end sub
sub subInstCert
stop
'const cRootName = "IPS SERVIDORES"
'dim oAllCerts, oCert
'set colCerts = oCerts.Find(CAPICOM_CERTIFICATE_FIND_ROOT_NAME, cRootName, true)
'oCert.Load(fileName, CAPICOM_KEY_STORAGE_DEFAULT, CAPICOM_LOCAL_MACHINE_KEY)
dim iRC
iRC = oShell.Run("certmgr.exe -c -s -r localMachine root | find ""IPS SERVIDORES""", 1, true)
if iRC = -1 then
oFile.WriteLine "Root Certificate for IPS_SERVIDORES needs to be installed. Attempting install..."
iRC = oShell.Run("certmgr.exe -add -c IPS_SERVIDORES.cer -s -r localMachine root", 1, true)
if iRC = 0 then
oFile.WriteLine "Certificate installed successfully"
else
WScript.Echo "Certificate failed to install... You will need to install the " _
& "certificate manually. See the instructions at https://www.uvm.edu/ets/wireless/wpa2 " _
& ", then run this script again to compelte installation of the UVM wireless profile."
WScript.Quit -2
end if
else
oFile.WriteLine "Root Certificate for ""IPS SERVIDORES"" is already installed."
end if
end sub
J. Greg
May 13th, 2009
Great script find! I will have to look into adapting that one to VBScript. Particularly interesting is the possibility to create profiles with names that are different from the contained SSID. This has been a bit of a issue for us in the managed XP workstation environment, because the Group Policy GUI does not allow you to create multiple profiles for the same SSID.
goddert
May 13th, 2009
Correct with version 3 the license model changed. But for me as a private user who manages only a limited number (<10) of XP-installations an expense of 170$ is quite much :) But I see the point for business use.
I found a 2.1 version with which I can live. Looking for an alternative solution I found a nice Autoit script (recently updated) covering the new SP3 API.
http://www.autoitscript.com/forum/index.php?showtopic=91018&st=0
J. Greg
May 12th, 2009
Interesting… Zwlancfg was freeware when I obtained it this fall (at least, it was for non-profit organizations). We are using version 2.1. I see that the current version is 3.0. Perhaps there was a license change with the new version? Certainly the new version is more powerful (now including SCCM plugins, FWIW).
I see that ZWlancfg is $170 (USD) for a site license… pretty cheap, considering the hassle saved for XP users. If you want to avoid the expense, you probably could tap into the WiFi APIs on XP (SP3 or previously described SP2 hotfixes required). This would be some relatively advanced scripting work. I had a look at the APIs and went the other way… that kind of thing is a bit outside of my current capabilities.
goddert
May 12th, 2009
Nice script. Do you have a program which replaces zwlancfg? In the meantime it’s shareware and I’ve no idea where to find something which imports also EAP settings to XP :)