Bakkenalia

Extracts from Torgeir Bakken's posts

Torgeir does not like the idea of keeping up a web page.  (I wouldn't  either, he does too much).

I keep collecting his code from posts in various Microsoft forums since he manages to wrap up some useful problem solutions, and I've finally decided to post the ones I use frequently here so I don't need to do a complete scan of my script collection or heavy Google browsing when I need to use one.


Automated Update Installations

The free Microsoft Software Services (SUS), Win2k and WinXP only:
http://www.microsoft.com/windows2000/windowsupdate/sus/default.asp


With SUS, there are a couple of downsides though...

1)
If the users local account on the client computer is a non-admin (a.k.a. not
members of the Administrators group), you cannot prevent SUS rebooting the
client PC when the patches have been installed. After  a reboot notice and a 5
minutes pause, the computer just reboots. As a non-admin, there is no way to
supress it.

2)
The client can only check for updates once a day, if the client misses the
update check "time window" (a.k.a. it was offline/powered off), it will
"reschedule" the check to next day.

3)
The SUS service needs to run on a Windows 2000 Server (non DC) with IIS
installed.


There is a separate newsgroup for SUS as well:
microsoft.public.softwareupdatesvcs
---------------------------------------------------------------
Set oShell = CreateObject("WScript.Shell")

sCmd = "C:\q323759.exe /q:a /r:n"
oShell.Run sCmd, 1, True


Note that the user running the logon script needs to be a local administrator.


If you want to do a remote installation that is unattended (no user input) and
single file install file based, you can use PsExec.exe in the free PsTools suite
from Sysinternals for this (will work on Win NT 4.0, Win2k and WinXP).

http://www.sysinternals.com/ntw2k/freeware/pstools.shtml

To install e.g. q323759.exe remotely, do like this:

psexec.exe \\some_computer  -c C:\q323759.exe /q:a /r:n

The file "behind" -c must exist on the computer running PsExec.
PsExec will copy the specified program to the remote system for execution and
run it with the additional switches. After the install, the file q323759.exe
will be deleted from the remote computer.

If not domain, username and password can be supplied:
psexec.exe \\some_computer -u user -p pwd -c C:\q323759.exe /q:a /r:n


See here for a complete VBScript example that installs SW on a list of computers

in a text file using PsExec:

From: Torgeir Bakken (Torgeir.Bakken-spam@hydro.com)
Subject: Re: Auto-Installing WMI
Newsgroups: microsoft.public.win32.programmer.wmi
Date: 2002-08-12 20:04:56 PST
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=3D58758B.3139B90C%40hydro.com

[Local copy of this script - AKA]


Lock Workstation Icon In QuickLaunch Tray

' Script that adds a padlock icon in Quick Launch Tray
' that locks the workstation (Win2k/WinXP)

Set oShell = CreateObject("WScript.Shell")

sCurrUsrPath = oShell.ExpandEnvironmentStrings("%UserProfile%")
Set oShortCut = oShell.CreateShortcut(sCurrUsrPath _
  & "\Application Data\Microsoft\Internet Explorer\" _
  & "Quick Launch\Lock Workstation2.lnk")

oShortCut.TargetPath = "rundll32.exe"
oShortCut.Arguments = "user32.dll,LockWorkStation"
oShortCut.IconLocation = "shell32.dll,47"
oShortCut.Save

WMI Uptime Script

Set oOS = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
For Each obj in oOS
  ' if WinXP, use SWbemDateTime for date/time formatting!
  sLastBoot = ConvWbemTime(obj.LastBootUpTime)
  sNow = ConvWbemTime(obj.LocalDateTime)
'	uptime = DateDiff("s",CDate(sLastBoot),CDate(sNow))
 uptime = DateDiff("s",obj.LastBootUpTime,obj.LocalDateTime)
Next

Function ConvWbemTime(IntervalFormat)
  Dim sYear, sMonth, sDay, sHour, sMinutes, sSeconds
  sYear = mid(IntervalFormat, 1, 4)
  sMonth = mid(IntervalFormat, 5, 2)
  sDay = mid(IntervalFormat, 7, 2)
  sHour = mid(IntervalFormat, 9, 2)
  sMinutes = mid(IntervalFormat, 11, 2)
  sSeconds = mid(IntervalFormat, 13, 2)

  ' Returning format yyyy-mm-dd hh:mm:ss
  ConvWbemTime = sYear & "-" & sMonth & "-" & sDay & " " _
               & sHour & ":" & sMinutes & ":" & sSeconds
End Function

WMI CPU ID

wscript.echo CpuID

Function CpuID()
  ' Obtaining CPU identification using WMI
  ' Script author: Torgeir Bakken

  ' Function returns a number of type integer:
  ' 0  ==>  Unknown CPU
  ' 1  ==>  Pentium or Pentium MMX
  ' 2  ==>  Pentium Pro/II or Celeron
  ' 3  ==>  Pentium III
  ' 4  ==>  Pentium 4

  ' based on this table:
  ' Family   Model               Type
  ' 5        <  4                Pentium
  ' 5        >= 4                Pentium MMX
  ' 6        <  3                Pentium Pro
  ' 6        >= 3 < 5            Pentium II
  ' 6        == 5                Pentium II or Celeron
  ' 6        == 6                Celeron
  ' 6        >= 7                Pentium III
  '15        >= 0                Pentium 4

  ' Family 5 and 6 identification based on information from here:
  ' ftp://download.intel.com/support/processors/procid/24161812.pdf

  Dim oWMI, oCpu, sCpuDescr, aCpuDescr, i, iFamily, iModel, iVersion

  Set oWMI = GetObject("winmgmts:")
  For Each oCpu in oWMI.InstancesOf("Win32_Processor")
    sCpuDescr = oCpu.Description
  Next

  aCpuDescr = Split(sCpuDescr)
  For i = 0 to Ubound(aCpuDescr)
    If LCase(aCpuDescr(i)) = "family" Then
      iFamily = CInt(aCpuDescr(i+1))
    End If
    If LCase(aCpuDescr(i)) = "model" Then
      iModel = CInt(aCpuDescr(i+1))
    End If
  Next

  iVersion = (iFamily * 100) + iModel

  Select Case True
    Case iFamily = 5
      ' Pentium or Pentium MMX
      CpuID = 1

    Case iVersion < 607
      ' Pentium Pro/II or Celeron
      CpuID = 2

    Case iFamily = 6
      ' Pentium III
      CpuID = 3

    Case iFamily = 15
      ' Pentium 4
      CpuID = 4

    Case Else
      ' Unknown CPU
      CpuID = 0
  End Select
End Function

Installed Applications Via Registry Enumeration


WScript.Echo InstalledApplications(".")

Function InstalledApplications(node)
 Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
 Set oRegistry = GetObject("winmgmts://" _
  & node & "/root/default:StdRegProv")
 sBaseKey = _
  "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
 iRC = oRegistry.EnumKey(HKLM, sBaseKey, arSubKeys)

 For Each sKey In arSubKeys

  iRC = oRegistry.GetStringValue( _
   HKLM, sBaseKey & sKey, "DisplayName", sValue)
  If iRC <> 0 Then
   oRegistry.GetStringValue _
    HKLM, sBaseKey & sKey, "QuietDisplayName", sValue
  End If
  If sValue <> "" Then
   InstalledApplications = _
    InstalledApplications & sValue & vbCrLf
  End If
 Next
End Function

Show Network Adapter States

Set oNicStatus = _
GetObject("winmgmts:root\wmi").InstancesOf("MSNdis_MediaConnectStatus")

For Each oNic In oNicStatus

  If oNic.NdisMediaConnectStatus = 0 Then
    sNicStatus = "connected"
  Elseif oNic.NdisMediaConnectStatus = 1 Then
    sNicStatus = "disconnected"
  Else
    sNicStatus = "unknown"
  End If

  WScript.Echo "Status of " & oNic.InstanceName & ": " & sNicStatus

Next

Set An Environment Variable Via WMI

From a Google post.

Note: this works great for modifying a variable for all Terminal Server sessions as well.  The example below creates a variable named %RouterStatus% with the value of UP in the SYSTEM  environment on a server named Mort.  - AKA

SetWmiEnvVar "MORT", "<SYSTEM>", "RouterStatus", "UP"

Sub SetWmiEnvVar( Host, sContext, sVarName, sValue)
 ' Sets an environment variable on an arbitrary host via WMI
 ' NOTE: This will of course not affect currently running
 ' processes.
 ' For a systemwide value, use <SYSTEM> as context
 ' for default user, use <DEFAULT>
 ' otherwis,e use the specific user's name
 ' Get the class object itself
 Dim EnvClass, EnvVarInst
 Set EnvClass = GetObject("WinMgmts://" & Host _
  & "/root/cimv2:Win32_Environment")
 ' Make a new instance of that class
 Set EnvVarInst = EnvClass.SpawnInstance_
 ' File in the key props and props of interest on that instance
 EnvVarInst.UserName = sContext
 EnvVarInst.Name = sVarName
 EnvVarInst.VariableValue = sValue
 ' Write the new instance in to WMI
 EnvVarInst.Put_
End Sub