Chapter 1. General Administration

Hacks #1-16

We’ll begin with a catchall chapter of tips and tools that cover a wide range of general Windows system administration topics. Think of this chapter as the removable top drawer of your toolbox—usually cluttered, but containing your favorite, indispensable tools. The topics in this chapter include ways of hacking the Run As command, collecting event log information, running commands, extending your environment, shutting down processes, renaming mapped drives, and more. You’ll also learn how to disable file encryption if you don’t need or want it, collect configuration settings from remote machines, use automatic logon where it’s safe to do so, and make it easier for users to access Remote Assistance when they need it. We’ll also list some of our favorite third-party tools and a terrific online resource for Microsoft management technologies.

A number of the hacks in this chapter include scripts. To ensure these scripts run properly on your systems, make sure you download the latest scripting engines on the workstation from which you run the scripts. You can get these scripting engines from the Microsoft Scripting home page at http://msdn.microsoft.com/scripting/. Also, when working with the Active Directory Services Interface (ADSI), you must have the same applicable rights you need to use the built-in administrative tools, which basically means that you need administrator credentials to run the scripts.

Use Run As to Perform Administrative Tasks

Use Run As to protect your administrator workstation from Trojans and other nasties.

If you’re lazy, like I am, you probably use the default administrator account on your desktop workstation for browsing the Web, checking your email, and managing the servers on your company’s network.

Not a good idea.

What if you unknowingly visited a web page that executed a script that downloaded a Trojan to your machine? Your administrator account would be compromised, and the attacker would have total access to your workstation and possibly to your whole network! To avoid such dangers, administrators should always have two user accounts: a regular (user-level) account for ordinary activities, such as web browsing and messaging, and an administrator-level account, used only for performing administrative tasks. This way, when you are reading your email and suddenly remember you have to reschedule a backup, you can simply log off, log back on using your administrator account, perform the task, log off again, and log on again as a regular user.

Who am I kidding? That’s too much to expect of a lazy system administrator.

How Run As Works

The Run As service (called Secondary Logon service in Windows Server 2003 and Windows XP) is a hack designed to enable you to run programs by using alternate credentials while you’re logged on using another account. For example, if you are an administrator and are logged on to your desktop using your regular user account, you won’t be able to run administrative tools such as Computer Management, because they require administrator credentials to run properly. (Actually, you can open Computer Management as an ordinary user; you just can’t do much with it.) Using Run As, however, you can run Computer Management as an administrator while remaining logged on as an ordinary user.

There are two ways to use Run As: using the GUI or from the command line. To use the GUI method, first find the program you want to run in Windows Explorer or My Computer. Then, for executables (*.exe files), hold down the Shift key, right-click the program’s icon, and select Run to open the Run As Other User dialog box shown in Figure 1-1. For MMC consoles (*.msc files) and Control Panel utilities (*.cpl files), you do the same thing but don’t need to hold down the Shift key.

Using Run As to run a program using administrator credentials
Figure 1-1. Using Run As to run a program using administrator credentials

Once you specify the appropriate alternate credentials and click OK, the program you selected runs in the security context of those alternate credentials until you close or terminate the program. If you prefer, the alternative credentials can also be entered as domain\user or user@domain, which in Figure 1-1 would be MTIT\Administrator or Administrator@mtit.com for an example domain named mtit.com (replace these credentials with the name of your own domain). The advantage of doing it the way shown in Figure 1-1 is that, if your computer is a member server, you can specify a local user account by entering the name of the computer in the Domain field.

Using Run As from the command line is just as easy, but you need to know the path to the program (unless the program file is located within the system path). For example, the Computer Management console file compmgmt.msc is located in the \system32 directory. To run it as Administrator in the MTIT domain, simply type the following at a command prompt:

runas /user:MTIT\Administrator "mmc %windir\system32\compmgnt.msc"

You’ll be prompted for a password for the account, after which Computer Management will open. Note that you can also type this command directly into the Run box (accessed by StartRun).

Limitations of Run As

While Run As is useful, it has some limitations. First, the alternate credentials you specify must have the Log On Locally user right on the computer. Since Run As is usually used with administrator credentials (which have that right by default), this is usually an issue only in certain circumstances. For example, say you grant a few knowledgeable users a second user account that belongs to the Power Users group, to allow them to update device drivers and perform other minor maintenance on their desktop computers. If you try to reduce the attack surface of your network by removing the right to Log On Locally from the Power Users group using Group Policy, then these users won’t be able to perform such tasks.

Also, there are certain tasks you can’t perform directly using Run As, such as opening the Printers folder to administer a printer that is connected to your machine. The reason for this is that the special folders such as Printers and Network and Dial-up Connections are opened indirectly by the operating system, not by a command. You also can’t use Run As to open Windows Explorer and access the filesystem on your computer as administrator, because the Windows shell explorer.exe is already running as your current desktop environment and Windows allows only one GUI shell to run at a time.

Finally, Run As also might not work if the program you are trying to run is located on a network share, because the credentials used to access the share might be different than the credentials used to run the program.

Most limitations have workarounds of some sort, if you try hard enough to find them. So, let’s see if we can figure out ways to get around these limitations (except for the Log On Locally limitation, which is absolute).

Running programs without an executable

Say you want to change some settings for the Local Area Connection in the Network and Dial-up Connections folder. If you try doing this as an ordinary user, you’ll get a message saying “The controls on this properties sheet are disabled because you do not have sufficient privileges to access them.” Here’s how to access these settings as an administrator without logging out of your regular account. Right-click on the task bar and open Task Manager. Then, switch to the Processes tab, select explorer.exe, and click End Process to kill the desktop but leave Task Manager running. Now, switch to the Applications tab, click New Task, type runas /user:MTIT\Administrator explorer.exe to run the Windows Explorer shell in an administrator context, and click OK. Finally, move Task Manager out of the way and type your password into the command-prompt window.

A new desktop will now appear, running in the security context of your administrator account. You can now change the settings of your Local Area Connection, modify the properties of a printer in the Printers folder, browse the filesystem, or do anything you want to do as administrator. But be sure to leave Task Manager running, because it is your only connection to your original desktop! You can minimize it so it won’t be in the way.

Once you’re finished performing your administrative tasks, you can return to your original desktop (the one running under the security context of your regular account) as follows. Maximize Task Manager so that you’ll have access to it when your desktop disappears again. Then, to log off of your administrator session, click StartShut Down and select Log Off.

Warning

Do not try to log off by pressing Ctrl-Alt-Del and clicking Log Off, because this will log off the session for your regular user account.

Your administrator desktop has now disappeared, but Task Manager is still running (in the security context of your regular account), so switch to the Applications tab, click New Task, type runas /user:MTIT\Administrator explorer.exe, and click OK. Your desktop has returned.

At this point, you might ask, “Why should I go to all that trouble? It would be faster just to log off as a regular user and log on as an administrator.” True, but any applications you have running as a regular user would then have to be terminated. Doing it the way shown here, however, leaves all your desktop applications running in the background.

Running programs from network shares

Here’s how to get around the limitation of running programs from network shares with appropriate credentials. To run a program named test.exe found in the TOOLS share on server SRV230, use StartRun to open a command-prompt window as administrator, type runas /user:MTIT\Administrator cmd to open a command shell in administrator context, and then map a drive to the shared folder by typing net use Z:\\SRV230\TOOLS. Now, switch to the Z: drive and run the program as desired. This lets you connect to the shared folder using domain administrator credentials and run the program under the same credentials. This approach is also useful for installing applications from a network distribution point.

Run As Shortcuts

To make your life easier, instead of having to type stuff at the command line, you can use Run As to create a shortcut that will run a program under alternate credentials. For example, to run the Computer Management console from a Run As shortcut, right-click on your desktop, select NewShortcut, and type %windir%\system32\compmgmt.msc as the command string. Name your shortcut Computer Management and click OK. Then, right-click on the shortcut, select Properties to open its properties sheet, and on the Shortcut tab select the checkbox labeled “Run program as other user” (on Windows Server 2003, click the Advanced button on the Shortcut tab to configure this). Now, whenever you double-click on the shortcut to run Computer Management, the Run As Other User dialog box (see Figure 1-1) will appear. Just type in your administrator password to run Computer Management in administrator context.

There’s another way to create Run As shortcuts that you might find even easier to use. Just right-click on your desktop, select NewShortcut, and type the following command string:

%windir%\system32\runas.exe /user:MTIT\Administrator "mmc %windir%\system32\compmgmt.msc"

Save the shortcut with the name Computer Management. Now, when you double-click the shortcut, a command-prompt window opens, prompting you for the password for the MTIT\Administrator account. Type the password, press Enter, and Computer Management starts in administrator context.

What if you get tired of typing your administrator password each time you want to run a Run As shortcut? On Windows Server 2003, there’s a way to get around that. Just create a new shortcut with this command string:

%windir%\system32\runas.exe /user:MTIT\Administrator /savecred "mmc %windir%\
system32\compmgmt.msc"

Notice the /savecred switch in this string. This option first appeared in Windows XP. The first time you double-click on the shortcut, a command-prompt window opens to prompt you for the password for the alternate credentials, just like before. The next time you double-click on the shortcut, however, you are not prompted for the password; it was stored on your machine the first time you ran the shortcut. Now you no longer have to type a password each time you use your Run As shortcut. Time-saver, right? Yes, but it’s also a possible security hole: once the credentials for your administrator account are stored locally on the machine, they can be used to run any command-line program using administrator credentials.

Here’s a scenario to illustrate what I mean. Let’s say you need to run an administrative tool on a user’s desktop machine without logging the user off the machine. You ask the user to take a coffee break. Then, you open a command-prompt window and use runas with /savecred to start the tool (you use /savecred because you might have to run several administrative tools and you don’t want to have to type your complex 24-character password repeatedly). When you’re finished, you close all the tools you started and walk away. When the user returns to her desktop, she opens a command prompt and types runas /user:MTIT\Administrator /savecred cmd. A command-prompt window opens, displaying administrator credentials in the title bar. The user now knows that she can use this approach to run any program on her machine using administrator credentials.

What did you do wrong as administrator in this scenario? Two things: you used /savecred on a user’s desktop machine, which saved your administrator password locally on the machine, and you haven’t renamed the default administrator account. If you had changed the name of this account to something complex and unknown to ordinary users, the runas /user:MTIT\Administrator /savecred cmd command the user typed wouldn’t work.

What do you do if you have used /savecred on an unsecured machine without thinking about the consequences? Just delete your stored credentials on the machine by opening Stored User Names and Passwords in the Control Panel.

Drag and Drop to the Run Menu

If you’re tired of having to drop out to a command prompt and navigate through folders to run an executable that requires switches, try this.

The following easy-to-use steps can be used to run the program of your choice from the Run menu with any command-line switches you need to include. This is much handier than opening a command prompt and changing to the directory where the executable is located, especially if long filenames are involved, which requires you to enclose your path in double quotes.

First, navigate in Windows Explorer to the executable you want to launch (Figure 1-2).

Selecting the executable to run in Explorer
Figure 1-2. Selecting the executable to run in Explorer

Next, use StartRun to invoke the Run menu (Figure 1-3).

Opening the Run menu
Figure 1-3. Opening the Run menu

Then, drag and drop your executable to the Run menu (Figure 1-4). Make sure the Open box is empty before you perform this step, or unexpected results might occur.

Dragging and dropping the executable into the Run menu
Figure 1-4. Dragging and dropping the executable into the Run menu

Now, simply add your switches and click OK to launch your application (Figure 1-5).

Adding switches as needed
Figure 1-5. Adding switches as needed

You’ll want to keep in mind that any filenames or paths that don’t follow the old 8.3 naming convention should be within quotation marks to run properly (Figure 1-6).

Using quotation marks for long filenames/paths
Figure 1-6. Using quotation marks for long filenames/paths

Note that your switches and arguments can reside outside of the quotation marks.

Sean Ademy

Find and Replace Registry Keys from a Command Line

Using the Regfind utility, you can easily search the Registry for a value, regardless of the key, and replace it.

Regfind (from the Windows 2000 Server Resource Kit) can be an invaluable tool when you need change a Registry key that you know the value for but when do not necessarily know the full path. Recently tasked with changing the hardcoded DNS server IP on all the servers in our organization, I was pleasantly surprised when I located this gem. The problem with trying to change the DNS server entry in the Registry is that all the IP parameters are broken up by a hashed ID. The ID references several things, but most of them have to do with the network card. Regfind allows you to search a set of subkeys in the Registry for a specific value and, when found, replace it. Another real beauty of this program is that it will work remotely; all you need to do is supply it with a list of machines and let it go. Using a list of computer names (generated from SMS, Server Manager, or AD Users and Computers), combined with two batch files, you can make sweeping changes in a dynamic environment.

The Code

Here’s an example of how to change the DNS server entry on all servers in your organization. First, create a batch file called Regchange2.bat with the following syntax:

regfind -m \\%1 -p HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\parameters "OLDIP" -r "NEWIP"

You will obviously want to replace OLDIP with the old DNS server IP and replace NEWIP with the new DNS server IP.

Now, create a second batch file called regchange1.bat with the following syntax:

for /F %%A in (servers.txt) do (call regchange2.bat %%A)

This searches the servers.txt file for computer names and passes them to the regchange2.bat file as a command-line argument.

Now you need to create a list file for your batch files to use. Create a listing of servers that need to have their DNS IP’s changed and save that list as servers.txt. An SMS report or a copy/paste from the server manager will suffice, or you can create the file manually if you like.

Running the Hack

Now, simply run the regchange1.bat batch file by calling it from a logon script and watch all your servers have their IP settings changed!

This is just one simple example of how to use Regfind. There are many command-line arguments, so please examine those to meet your needs.

Donnie Taylor

Automatically Log On After Booting

It’s sometimes convenient to configure machines to log on automatically when booted. Here are three ways to do this.

In all versions of Windows that are based on Windows NT (including Windows 2000, Windows XP, and Windows Server 2003), a user is required to log on before he can use the system interactively. This is usually done by pressing Ctrl-Alt-Del and typing the user’s credentials. Automatic logon is an option you can set to enable Windows to log on automatically using credentials that are stored in the Registry. To invoke automatic logon, you set Registry entries that define the user ID, the password, and the domain to be used to log on. Why use this feature? There are a number of reasons. As an IT professional, I have several of my home systems set up to do this, and it makes life simpler. Test systems in a lab might be another place to use this feature. I also use it all the time on virtual machine images I have running on my laptop.

Automatic login makes things simpler, but it creates a security hole. First, the credentials are stored in clear text in the Registry. Thus, anyone with remote Registry privileges can see the clear text user ID and password. Also, if you have automatic logon set on a laptop, anyone who turns on the laptop is automatically logged in as you. So use this feature carefully!

Manual Configuration

You can configure automatic logon manually by adding the following four key Registry entries: AutoAdminLogon, DefaultDomainName, DefaultUserName, and DefaultPassword. These entries inform Windows whether to attempt automatic logon and provide the credentials (username, password, and domain).

Start Registry Editor (StartRun regedit) and find the Registry key HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon, which is where the Registry values you set to control automatic logon are located. Two of these values, DefaultDomainName and DefaultUserName, already exist. DefaultDomainName is a string that holds the domain (or workstation) name where the user ID exists, and DefaultUserName is the user ID that Winlogon will attempt to use to log on. This username is authenticated against the domain (or workstation) name set in the DefaultDomainName setting.

Now, create two new values by right-clicking on Winlogon and selecting NewString Value, which will create new values of type REG_SZ. Name the first value AutoAdminLogon, and specify a value data of 1 to instruct Winlogon to attempt to use automatic logon. Name the second value DefaultPassword; this value specifies the password for the user set in the DefaultUserName setting.

The result will looking like Figure 1-7.

Enabling automatic logon by editing the Registry
Figure 1-7. Enabling automatic logon by editing the Registry

Script Method

An easier way to configure automatic logon on your machines is to use two VBScript scripts, one to enable automatic logon and the other to disable it. Here’s the script for enabling it:

' Script to turn on automatic logon
' (c) Thomas Lee 2002
' Freely distributed!
Dim Prompt, oWSH,UserName, UserPass, UserDomain
set oWSH = WScript.CreateObject("WScript.Shell")

' get user name
Prompt = "Enter the autologon user name"
UserName = InputBox(Prompt, Title, "")

' get password
Prompt = "Enter the autologon user password for " & UserName
UserPass = InputBox(Prompt, Title, "")

' get domain
Prompt = "Enter the autologon user domain for " & UserName
Userdomain = InputBox(Prompt, Title, "")

' now set these in the Registry
oWSH.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon",
"1","REG_SZ"
oWSH.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultDomainName", UserDomain, "REG_SZ" 
oWSH.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultUserName", UserName, "REG_SZ" 
oWSH.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultPassword", UserPass, "REG_SZ"

' ensure the change is persistent!
oWSH.RegWrite "HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\ForceAutoLogon", 
"1", "REG_SZ" 

' All done

And here’s the script for disabling automatic logon:

' Script to remove autoadmin logon
' (c) Thomas Lee 2002
' Freely distributed!
Option Explicit
On Error Resume Next

'Declare variables
Dim Prompt, oWSH

'Set the Windows Script Host Shell 
set oWSH = WScript.CreateObject("WScript.Shell")

' delete the relevant keys
oWSH.RegDelete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
AutoAdminLogon"
oWSH.RegDelete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultDomainName"
oWSH.RegDelete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultUserName"
oWSH.RegDelete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
DefaultPassword"

' All done - say goodbye!
Legend = "Autoadmin removed - have a nice day!"
MyBox = MsgBox (legend, 4096, "We're Done")

You can use Notepad to type these scripts and save them with a .vbs file extension, or download autoadminlogon.vbs and noautoadminlogon.vbs from http://www.oreilly.com/catalog/winsvrhks/.

Sysinternals Tool

Finally, here’s one more way to configure automatic logon on machines. Mark Russinovich, of Sysinternals fame, also wrote a simple program to do this. You can download the program and the source from http://www.sysinternals.com/ntw2k/source/misc.shtml#AutoLogon, where you can find lots of other great tools.

Thomas Lee

Wait for and Optionally Terminate a Process

If you’ve wondered how to write code that waits for a process to finish before terminating it, here’s the answer.

I have seen a number of discussions regarding the need for a VB script that waits for a process to finish. The script in this hack does this and more: it waits for a process to finish and optionally terminates the process if it has not finished within a specified amount of time.

This code is a modified form of what I use to control my software deployments, and it has two purposes. First, the code is designed to be certain that the deployment script waits until the initiated software setup executable is fully finished before proceeding. Even though the majority of recent software releases do not require this functionality when being deployed, it is still required for some legacy installations. Second, the code can perform a forceful termination of an application if this functionality is required.

This script accepts three arguments: the name of the executable to wait for or terminate, the amount of time to wait before terminating the specified executable, and (optionally) a switch specifying that the script should run silently. Note that the script uses Windows Management Instrumentation (WMI) for the process-management tasks, so make sure you’re running the latest WMI version on your machine.

The Code

The script consists of several sections, which are described inline in the following sections.

Main routine

First, command-line switches are read in the main body area:

Option Explicit
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' File:     vbsWaitForProcess.vbs
' Updated:  Nov 2002
' Version:  1.0
' Author:   Dan Thomson, myITforum.com columnist
'           I can be contacted at dethomson@hotmail.com
'
' Usage:    The command processor version must be run using cscript
'           cscript vbsWaitForProcess.vbs notepad.exe 60 S
'           or
'           The IE and Popup versions can be run with cscript or wscript
'           wscript vbsWaitForProcess.vbs notepad.exe -1
'
' Input:    Name of executable  (ex: notepad.exe)
'           Time to wait in seconds before terminating the executable
'               -1 waits indefinitely for the process to finish
'               0 terminates the process imediately
'               Any value > 0 will cause the script to wait the specified
'               amount of time in seconds before terminating the process
'           Silent mode  (S)
'
' Notes:
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

On Error Resume Next

'Define some variables
Dim strProcess
Dim intWaitTime
Dim strSilent

'Get the command line arguments
strProcess = Wscript.Arguments.Item(0)
intWaitTime = CInt(Wscript.Arguments.Item(1))
strSilent = Wscript.Arguments.Item(2)

Call WaitForProcess (strProcess, intWaitTime, strSilent)

Check if process is running

Next, the ProcessIsRunning function determines if a process is running:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Function: ProcessIsRunning
'
' Purpose:  Determine if a process is running
'
' Input:    Name of process
'
' Output:   True or False depending on if the process is running
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Function ProcessIsRunning( strProcess )
    Dim colProcessList

    Set colProcessList = Getobject("Winmgmts:").Execquery _
        ("Select * from Win32_Process Where Name ='" & strProcess & "'")
    If colProcessList.Count > 0 Then
        ProcessIsRunning = True
    Else
        ProcessIsRunning = False
    End If

    Set colProcessList = Nothing
End Function

Terminate the process

In the next section, the ProcessTerminate function terminates a process:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Function: TerminateProcess
'
' Purpose:  Terminates a process
'
' Input:      Name of process
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Function ProcessTerminate( strProcess )
    Dim colProcessList, objProcess

    Set colProcessList = GetObject("Winmgmts:").ExecQuery _
        ("Select * from Win32_Process Where Name ='" & strProcess & "'")
    For Each objProcess in colProcessList
        objProcess.Terminate( )
    Next

    Set colProcessList = Nothing
End Function

Wait for process to terminate

Finally, in the WaitForProcess subroutine, the user interface is set up, the script waits while the process is active, and the process termination is initiated. I created three versions of the subroutine in an effort to demonstrate a few methods for displaying status messages. For example, here’s how to display these messages using the command console:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Sub: WaitForProcess
'
' Purpose:  Waits for a process
'
' Input:    Name of process
'           Wait time in seconds before termination.
'             -1 will cause the script to wait indefinitely
'             0 terminates the process imediately
'             Any value > 0 will cause the script to wait the specified
'             amount of time in seconds before terminating the process
'           Display mode.
'             Passing S will run the script silent and not show any prompts
'
' Output:   On screen status
'
' Notes:    The version echos user messages in the command window via StdOut
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub WaitForProcess( strProcess, intWaitTime, strMode )

  If ProcessIsRunning(strProcess) Then
    Dim StdOut
    Dim w : w = 0
    Dim strPrompt
    Dim intPause : intPause = 1

    If UCase(strMode) <> "S" Then
      strPrompt = "Waiting for " & strProcess & " to finish."
      Set StdOut = WScript.StdOut
      StdOut.WriteLine ""
      StdOut.Write strPrompt
    End If
    'Loop while the process is running
    Do While ProcessIsRunning(strProcess)
      'Check to see if specified # of seconds have passed before terminating
      'the process. If yes, then terminate the process
      If w >= intWaitTime AND intWaitTime >= 0 Then
        Call ProcessTerminate(strProcess)
        Exit Do
      End If
      'If not running silent, post user messages
      If UCase(strMode) <> "S" Then _
        StdOut.Write "."
      'Increment the seconds counter
      w = w + intPause
      'Pause
      Wscript.Sleep(intPause * 1000)
    Loop
    If UCase(strMode) <> "S" Then
      StdOut.WriteLine ""
      Set StdOut = Nothing
    End If
  End If
End Sub

The result is shown in Figure 1-8.

Status message displayed in command console
Figure 1-8. Status message displayed in command console

Alternatively, here’s some code for displaying status messages in Internet Explorer:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Sub: WaitForProcess
'
' Purpose:  Waits for a process
'
' Input:    Name of process
'           Wait time in seconds before termination.
'             -1 will cause the script to wait indefinitely
'             0 terminates the process imediately
'             Any value > 0 will cause the script to wait the specified
'             amount of time in seconds before terminating the process
'             Display mode.
'             Passing S will run the script silent and not show any prompts
'
' Output:   On screen status
'
' Notes:    This version uses Internet Explorer for user messages
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub WaitForProcess( strProcess, intWaitTime, strMode )

  If ProcessIsRunning(strProcess) Then
    Dim objIntExplorer
    Dim c : c = 0
    Dim w : w = 0
    Dim strPrompt
    Dim intPause : intPause = 1

    strPrompt = "Waiting for " & strProcess & " to finish."

    'If not running silent, create reference to objIntExplorer
    'This will be used for the user messages. Also set IE display attributes
    If UCase(strMode) <> "S" Then
      Set objIntExplorer = Wscript._
      CreateObject("InternetExplorer.Application")
      With objIntExplorer
        .Navigate "about:blank"
        .ToolBar = 0
        .Menubar = 0         ' no menu
        .StatusBar = 0
        .Width=400
        .Height = 80
        .Left = 100
        .Top = 100
        .Document.Title = "WaitForProcess"
      End With
      'Wait for IE to finish
      Do While (objIntExplorer.Busy)
          Wscript.Sleep 200
      Loop
      'Show IE
      objIntExplorer.Visible = 1
    End If
    Do While ProcessIsRunning(strProcess)
      'Check to see if specified # of seconds have passed before terminating
      'the process. If yes, then terminate the process
      If w >= intWaitTime AND intWaitTime >= 0 Then
        Call ProcessTerminate(strProcess)
        Exit Do
      End If
      If UCase(strMode) <> "S" Then
        objIntExplorer.Document.Body.InnerHTML = strPrompt & String(c, ".")
        'Increment the counter.
        'Reset the counter indicator if it's > 25 because
        'we don't want it taking up a lot of screen space.
        If c > 25 Then c = 1 Else c = c + 1
        'Increment the seconds counter
        w = w + intPause
      End If
      'Pause
      Wscript.Sleep(intPause * 1000)
    Loop
    objIntExplorer.Quit( )             ' close Internet Explorer
    Set objIntExplorer = Nothing      ' release object reference

  End If
End Sub

The resulting status message is shown in Figure 1-9.

Displaying status messages in Internet Explorer
Figure 1-9. Displaying status messages in Internet Explorer

Finally, here’s code that uses the Popup method of Windows Scripting Host for displaying status messages:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Sub: WaitForProcess
'
' Purpose:  Waits for a process
'
' Input:    Name of process
'           Wait time in seconds before termination.
'             -1 will cause the script to wait indefinitely
'             0 terminates the process imediately
'             Any value > 0 will cause the script to wait the specified ' 
'             amount of time in seconds before terminating the process
'           Display mode.
'             Passing S will run the script silent and not show any prompts
'
' Output:   On screen status
'
' Notes:    This version uses WshShell.Popup for user messages
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub WaitForProcess( strProcess, intWaitTime, strMode )

  If ProcessIsRunning(strProcess) Then
    Dim objWshShell
    Dim c : c = 0
    Dim w : w = 0
    Dim strPrompt
    Dim intPopupTimer : intPopupTimer = 2
    Dim intPause : intPause = 1

    strPrompt = "Waiting for " & strProcess & " to finish."

    'If not running silent, create reference to objWshShell
    'This will be used for the user messages
    If UCase(strMode) <> "S" Then _
      Set objWshShell = CreateObject("WScript.Shell")
    'Loop while the process is running
    Do While ProcessIsRunning(strProcess)
      'Check to see if specified # of seconds have passed before terminating
      'the process. If yes, then terminate the process
      If w >= intWaitTime AND intWaitTime >= 0 Then
        Call ProcessTerminate(strProcess)
        Exit Do
      End If
      'If not running silent, post user prompt
      If UCase(strMode) <> "S" Then
        objWshShell.Popup strPrompt & String(c, "."), intPopupTimer, _
        "WaitForProcess", 64
        'Increment the counter.
        'Reset the counter indicator if it's > 25 because
        'we don't want it taking up a lot of screen space.
        If c > 25 Then c = 1 Else c = c + 1
      End If
      'Increment the seconds counter
      w = w + intPause + intPopupTimer
      'Pause
      Wscript.Sleep(intPause * 1000)
    Loop
    Set objWshShell = Nothing
  End If
End Sub

The resulting dialog box is shown in Figure 1-10.

Displaying status messages in a dialog box
Figure 1-10. Displaying status messages in a dialog box

Note that if you are assembling a standalone script, it should contain sections 1, 2, 3, and one option from section 4. If you would rather incorporate this code into your existing script, you need only sections 2, 3, and one option from section 4. You’ll also need to add the call statement that is at the end of the main routine section. All the code sections are self-contained, which makes them easy to import into existing scripts.

Running the Hack

To use this hack, type the code into Notepad (with Word Wrap disabled) and save it with a .vbs extension as WaitForProcess.vbs. Or, if you don’t want to tire your fingers out, download it from the O’Reilly web site instead.

Here are a few sample command-line examples. This will wait indefinitely until Notepad is closed:

cscript WaitForProcess.vbs notepad.exe -1

This will wait silently and indefinitely until Notepad is closed:

cscript WaitForProcess.vbs notepad.exe -1 S

And this will wait 10 seconds before Notepad is forcefully closed:

cscript WaitForProcess.vbs notepad.exe 10

Dan Thomson

Shut Down a Remote Computer

Here’s a nifty way to use a script to shut down remote machines.

Sometimes, you need to be able to shut down a server remotely. This script pings the computer in question prior to sending the Win32Shutdown method. It operates on remote PCs and has been tested on systems running Windows 2000. It will probably work on NT4 systems with the proper WHS/WMI/VB scripting, though it has not been tested on such systems.

Using the Win32Shutdown method, the script provides you with the option of logging off the current user of the machine, powering the machine down, or rebooting it. In addition, each of these options can be forced so that the action occurs even if applications are running. Use this option carefully, though, because it might cause the logged-on user to lose his work if he has open files. Note that forced log off/power down/reboot will not work if the screen saver is password-protected and is currently active.

The Code

Make sure you have the latest scripting engines on the workstation you run this script from. You can download the latest scripting engines at the Microsoft Scripting home page (http://msdn.microsoft.com/library/default.asp?url=/nhp/default.asp?contentid=28001169). Note that, when working with the Active Directory Services Interface (ADSI), you must have the same applicable rights as you need to use the built-in administrative tools. Also, for VB scripts that interact with Windows Management Instrumentation (WMI), apply the most current version of the WMI agents.

Type the following code into a text editor such as Notepad (making sure to have Word Wrap disabled) and save it with a .vbs extension. Alternatively, you can download the RemoteShutdown.vbs script from the O’Reilly web site at http://www.oreilly.com/catalog/winsvrhks/.

'/'|| RemoteShutdown.vbs
'||
'|| Created by Harvey Hendricks, MCP, MCSE, A+
'|| March 2001
'|| email: Harvey.Hendricks@aramcoservices.com
'||
'||
'|| Based on techniques and ideas from:
'|| SMS admin, SMS Installer, & WMI forums ->
'|| http://www.myITforum.com/forums
'|| Win32 Scripting -> http://cwashington.netreach.net/
'|| Microsoft Windows Script Technologies ->
'|| http://msdn.microsoft.com/scripting
'|| Microsoft Online Library -> 
'|| http://msdn.microsoft.com/library/default.asp
'|| Microsoft VBScript 5.5 documentation and Microsoft WMI SDK
'||
'||~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'|| SCRIPT LOGIC FLOW:
'|| Collects computername from user, calls function to ping the computername
'|| to determine if it is accessible, if not then display message and exit
'|| otherwise continue.
'|| Collects desired action to perform from the user, does error checking on
'|| the input to determine if it is acceptable, if not then display message
'|| and exit otherwise continue.
'|| Set variables and output messages based on the action chosen. Calls
'|| Win32Shutdown with the appropriate variable. Displays success message
'|| and exits
'||
'|| Uses WMI Win32Shutdown method from the Win32_OperatingSystem class
'|| to perform different logoff / powerdown / reboot functions
'||
'|| Testing found the following values to be effective on Win32Shutdown:
'|| Action decimal binary
'|| Logoff 0 0000
'|| Force Logoff 4 0100
'|| Reboot 2 0010
'|| Force Reboot 6 0110
'|| Powerdown 8 1000
'|| Force Powerdown 12 1100
'||
'|| Notice that the third bit from the right appears to be the "FORCE" bit.
'||
'|| A value of 1 will do a shutdown, ending at the "It is safe to turn
'|| off your computer" screen. I have no use for this and did not test it.
'||
'||
'||NOTES: - tested under Windows 2000 Pro. with ACPI compliant systems -
'|| SHOULD work under Windows NT4 without modification IF the
'|| system has compatible versions of WSH / WMI / VBscripting
'||
'||Logoff / Powerdown / Reboot:
'|| Does not work if a password protected screen saver is active or
'|| there is data to save. Either way the system waits for user input.
'||
'||Force Logoff / Force Powerdown / Force Reboot:
'|| Does not work if a password protected screen saver is active, will wait
'|| for user input. Otherwise will close open applications without saving
'|| data.
'||
'\/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

'/\/\/\/\/\/\/\/\/\/\/\/\/\/\ start function 
function Ping(byval strName)
dim objFSO, objShell, objTempFile, objTS
dim sCommand, sReadLine
dim bReturn

set objShell = WScript.CreateObject("Wscript.Shell")
set objFSO = CreateObject("Scripting.FileSystemObject")

'Set default return value
bReturn = false

'Create command line to ping and save results to a temp file
sCommand = "cmd /c ping.exe -n 3 -w 1000 " & strName & " > C:\temp.txt"

'Execute the command
objShell.run sCommand, 0, true

'Get the temp file
set objTempFile = objFSO.GetFile("C:\temp.txt")
set objTS = objTempFile.OpenAsTextStream(1)

'Loop through the temp file to see if "reply from" is found,
'if it is then the ping was successful
do while objTs.AtEndOfStream <> true
sReadLine = objTs.ReadLine
if instr(lcase(sReadLine), "reply from") > 0 then
bReturn = true
exit do
end if
loop

'Close temp file and release objects
objTS.close
objTempFile.delete
set objTS = nothing
set objTempFile = nothing
set objShell = nothing
set objFSO = nothing

'Return value
Ping = bReturn
end function
'/\/\/\/\/\/\/\/\/\/\/\/\/\/\ end function

'/\/\/\/\/\/\/\/\/\/\/\ Start Main body of script 
'Get computer name to operate on
ComputerName=InputBox("Enter the Machine name of the computer" & vbCRLF _
& "you wish to Shutdown / Reboot / Logoff", _
"Remote Shutdown / Reboot / Logoff", _
"ComputerName")

'if Cancel selected - exit 
If (ComputerName = "") Then Wscript.Quit

'change the name to uppercase
ComputerName=UCase(ComputerName)

'ping the computername to see if it is accessible
bPingtest = ping(Computername)

If bPingtest = FALSE Then
y = msgbox ("'" & ComputerName & "' is not accessible!" & vbCRLF _
& "It may be offline or turned off." & vbCRLF _
& "Check the name for a typo." & vbCRLF, _
vbCritical, ComputerName & " NOT RESPONDING")
Wscript.Quit
end IF

'Get the action desired
Action=InputBox( _
"Select Action to perform on " & ComputerName & vbCRLF & vbCRLF _
& " 1 - Logoff" & vbCRLF _
& " 2 - Force Logoff ( NO SAVE )" & vbCRLF _
& " 3 - Powerdown" & vbCRLF _
& " 4 - Force Powerdown ( NO SAVE )" & vbCRLF _
& " 5 - Reboot" & vbCRLF _
& " 6 - Force Reboot ( NO SAVE )" & vbCRLF & vbCRLF _
& "NOTE:" & vbCRLF _
& " Using Force will close windows" & vbCRLF _
& " without saving changes!", _
"Select action to perform on " & ComputerName, "")

'if Cancel selected - exit 
If (Action = "") Then Wscript.Quit

'error check input
If (INSTR("1234567",Action)=0) OR (Len(Action)>1) then
y = msgbox("Unacceptable input passed -- '" & Action & "'", _
vbOKOnly + vbCritical, "That was SOME bad input!")
Wscript.Quit
end if

'set flag to disallow action unless proper input achieved, 1 => go 0 => nogo
flag = 0

'set variables according to computername and action
Select Case Action
Case 1 'Logoff
x = 0
strAction = "Logoff sent to " & ComputerName
flag = 1
Case 2 'Force Logoff 
x = 4
strAction = "Force Logoff sent to " & ComputerName
flag = 1
Case 3 'Powerdown
x = 8
strAction = "Powerdown sent to " & ComputerName
flag = 1
Case 4 'Force Powerdown
x = 12
strAction = "Force Powerdown sent to " & ComputerName
flag = 1
Case 5 'Reboot
x = 2
strAction = "Reboot sent to " & ComputerName
flag = 1
Case 6 'Force Reboot
x = 6
strAction = "Force Reboot sent to " & ComputerName
flag = 1
Case 7 'Test dialog boxes
y = msgbox("Test complete", vbOKOnly + vbInformation, "Dialog Box Test Complete")
flag = 0
Case Else 'Default -- should never happen
y = msgbox("Error occurred in passing parameters." _
& vbCRLF & " Passed '" & Action & "'", _
vbOKOnly + vbCritical, "PARAMETER ERROR")
flag = 0
End Select

'check flag
' if equal 1 (TRUE) then perform Win32Shutdown action on remote PC
' and display a confirmation message
' if not equal 1 (FALSE) then skip the action and script ends
if flag then
Set OpSysSet=GetObject("winmgmts:{(Debug,RemoteShutdown)}//" _
& ComputerName & "/root/cimv2").ExecQuery( _
"Select * from Win32_OperatingSystem where Primary=true")
for each OpSys in OpSysSet
OpSys.Win32Shutdown(x)
y = msgbox(strAction,vbOKOnly + vbInformation,"Mission Accomplished")
next
end If

'Release objects
set OpSys = nothing
set OpSysSet = nothing

Running the Hack

To run the hack, simply double-click on the RemoteShutdown.vbs file in Windows Explorer (or a shortcut to this file on your desktop) and type the name of the remote computer you want to log off from, power down, or reboot. This name can be the NetBIOS name, DNS name, or IP address of the remote machine. You will then be presented with an input box that displays a menu of options:

1 - Logoff
2 - Force Logoff
3 - Powerdown
4 - Force Powerdown
5 - Reboot
6 - Force Reboot

Simply type the number for the action you want to perform and press Enter.

Harvey Hendricks

Rename Mapped Drives

Renaming drive mappings can be done in several ways, but automating the process is most efficient using a script.

Occasionally, an administrator might need to change drive-mapping names to hide share paths or to make the drive name user-friendly. This is an easy operation when done manually through a console, but when you try to automate this task, it becomes a little more difficult. Because mapped drives are not partitions on the local hard disk, common DOS commands, such as label, can’t be used. Most drive-mapping commands, such as net use, don’t have a way to customize the name of the mapped drive either.

One common way to perform this task is to hack the following Registry key and add the _LabelFromReg string value:

HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\%key%

Here, the %key% variable is the drive letter to be changed.

There is a whole host of ways to make this method work, either by editing the Registry directly, via script, or by importing a .reg file using regedit /c. All of these methods require many steps and some require external files, so they might not fit into every administrative scheme. But there’s an easier approach.

The Code

As it turns out, our old friend VBScript can be used to make this task a little more seamless. This simple script can be used on mapped drives as well as local partitions:

mDrive = "drive letter"
Set oShell = CreateObject("Shell.Application")
oShell.NameSpace(mDrive).Self.Name = "AnyName"

Running the Hack

To use this hack, simply edit the script to change the drive letter and drive name as desired. For example, if E: is a mapped drive that has the label Budgets on 172.16.33.14, and you want to change the label on the mapped drive to simply Budgets, change this line:

mDrive = "drive letter"

to this:

mDrive = "e:\"

Then, change this line:

oShell.NameSpace(mDrive).Self.Name = "AnyName"

to this:

oShell.NameSpace(mDrive).Self.Name = "Budgets"

Finally, run the script by creating a shortcut to it and double-clicking on the shortcut, by calling it from a logon script, or by any other method suitable for your environment.

Michael Brainard

Execute a Command on Each Computer in a Domain

This handy script lets you easily run any command on a specified subset of computers in your domain.

Running the same command on multiple computers in your domain can be tedious indeed, but such a scenario is common in an administrator’s life. I’ve written this hack to make this chore easier. The script traverses member systems of a domain, executing a command against each system that has a name that matches a particular specification you specify in the command line. Note that regular expressions are legal in this script, which makes it a powerful and flexible addition to the administrator’s toolkit.

The Code

To use this script, type it into a text editor such as Notepad (make sure Word Wrap is disabled) and save it with a .vbs extension as ExecuteAll.vbs. Alternatively, if you don’t want to wear your fingers out, you can download the script from the O’Reilly web site.

'Script Name: ExecuteAll.vbs

Option Explicit

Dim oDomain, oService, oItem, oShell
Dim strDomain, strSpec, strCommand, intButton
Dim oArgs, strFinalCommand, oRegEx, boolConfirm

' Prepare to execute commands & do popups
Set oShell = CreateObject("WScript.Shell")

GetArguments

' Access the domain so we can traverse objects
WScript.Echo "Accessing NT Domain " & strDomain
Set oDomain = GetObject("WinNT://" & strDomain)

' Initiate our regular expression support
Set oRegEx = New RegExp
oRegEx.Pattern = strSpec
oRegEx.IgnoreCase = True

' Traverse each computer (WinNT) object in the domain
WScript.Echo "Searching for " & strSpec
oDomain.Filter = Array("Computer") ' only look at computers
For Each oItem In oDomain
If oRegEx.Test(oItem.Name) Then
WScript.Echo " Matched " & oItem.Name
strFinalCommand = Replace(strCommand, "$n", oItem.Name)

intButton = vbNo
If boolConfirm Then
intButton = oShell.Popup("Execute " & strFinalCommand & "?",,_
"System " & oItem.Name, vbYesno + vbQuestion)
End If
If (boolConfirm = False) Or (intButton = vbYes) Then
WScript.Echo " Executing: " & strFinalCommand
execute strFinalCommand
End If
End If
Next

' All done; clean up
Set oItem = Nothing
Set oRegEx = Nothing
Set oDomain = Nothing
Set oShell = Nothing
Set oArgs = Nothing

'
' Glean the arguments for our run from the command line, if provided.
' If any are missing, prompt for input. A blank input signals an abort.
'
' /Y is an optional last argument
Sub GetArguments
Dim i, strConfirm, intButton
Set oArgs = WScript.Arguments

boolConfirm = True ' assume always confirm
strDomain = "" ' domain to be traversed
strSpec = "" ' name specification to be matched
strCommand = "" ' command to be executed on each match
strConfirm = "" ' track prompting for confirmation setting

' Look for our optional 4th argument
If oArgs.Length = 4 Then
If UCase(oArgs.Item(3)) = "/Y" Then
boolConfirm = False
strConfirm = "/Y" ' don't prompt below
End If
End If

' Look for any specified arguments, in order
If oArgs.Length >= 1 Then strDomain = oArgs(0)
If oArgs.Length >= 2 Then strSpec = oArgs(1)
If oArgs.Length >= 3 Then strCommand = oArgs(2)

' Prompt for any arguments not specified on the command line
If strDomain = "" Then
strDomain = InputBox _
("Enter the name of the NT Domain to be traversed", _
"NT Domain")
End If
If strDomain = "" Then WScript.Quit
strDomain = UCase(strDomain)

If strSpec = "" Then
strSpec = InputBox _
("Enter your name specification for the computer(s) " & _
"that will be matched within the " & strDomain & " Domain." & _
vbCrlf & "Regular Expressions are acceptable.", _
"Name Specification")
End If
If strSpec = "" Then WScript.Quit

If strCommand = "" Then
strCommand = InputBox _
("Enter the command to be executed on each computer matching " & _
strSpec & " within the " & strDomain & " Domain." & _
vbCrlf & "$n will be substituted for the computer name.", _
"Command to Execute")
End If
If strCommand = "" Then WScript.Quit

If strConfirm = "" Then
intButton = oShell.Popup("Confirm each command prior to execution?",,_
"Confirm?", vbYesNo + vbQuestion)
If intButton = vbNo Then
boolConfirm = False
End If
End If
End Sub

' Execute a command. Each is always run under a new instance of the command
' processor. This allows the use of built-in commands and I/O redirection.
'
' We won't wait for command completion.
Sub Execute(strCommand)
Dim RetVal

strCommand = "%COMSPEC% /c " & strCommand

RetVal = oShell.Run(strCommand, 1, False)
End Sub

Running the Hack

Here is the syntax for running the script:

ExexcuteAll.vbs <DomainToTraverse> <ComputerSpecification> <Command> [/Y]

When the script runs, the matched system’s name will be substituted for the occurrence of $n in the command to be performed. By default, each command instance is confirmed before it is executed, but you can specify /Y to always answer Yes instead.

Here’s an example of how to run the script:

ExexcuteAll.vbs MYDOMAIN WKSATL* "del \\$n\admin$\activitylog.txt"

This example traverses the MYDOMAIN domain, looking for computer names that start with WKSATL* (note the wildcard) and deletes the activitylog.txt file from the C:\Winnt folder.

Hans Schefske

Add, Remove, or Retrieve Environment Variables

Environment variables can easily be added, removed, or retrieved using the script in this hack.

Using VBScript to work with the Windows system environment can be pretty simple. This hack shows how to use a script to read variables, add new variables, remove variables, and recurse through all of them. Just take a look through the script and read the comments to see how to perform each task. Note that there are four types of values in the Windows Script Host (WSH) environment—System, User, Volatile, and Process—and the script uses all of them.

By the way, this script is provided by Dudeworks (http://www.dudeworks.net). For additional resources on Windows scripting and working with the environment, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/wsProEnvironment.asp.

The Code

Type the following script into Notepad (with Word Wrap disabled) and save it with a .vbs extension as GetEnvVars.vbs:

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
'Created by: Rob Olson - Dudeworks 
'Created on: 10/17/2001 
'Purpose: Get Environment Variables. 
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

wscript.echo "Working with the Environment: Provided by www.dudeworks.net"&vbcrlf&vbcrlf&strval 

'// Create an instance of the wshShell object
set WshShell = CreateObject("WScript.Shell")
'Use the methods of the object
wscript.echo "Environment.item: "& WshShell.Environment.item("WINDIR")
wscript.echo "ExpandEnvironmentStrings: "& WshShell.ExpandEnvironmentStrings("%windir%")

'// add and remove environment variables
'// Specify the environment type ( System, User, Volatile, or Process )
set oEnv=WshShell.Environment("System")

wscript.echo "Adding ( TestVar=Windows Script Host ) to the System " _
& "type environment"
' add a var
oEnv("TestVar") = "Windows Script Host"

wscript.echo "removing ( TestVar=Windows Script Host ) from the System " _
& "type environment"
' remove a var
oEnv.Remove "TestVar"


'// List all vars in all environment types

'//System Type
set oEnv=WshShell.Environment("System")
for each sitem in oEnv 
strval=strval & sItem &vbcrlf 
next
wscript.echo "System Environment:"&vbcrlf&vbcrlf&strval 
strval=""

'//Process Type
set oEnv=WshShell.Environment("Process")
for each sitem in oEnv 
strval=strval & sItem &vbcrlf 
next
wscript.echo "Process Environment:"&vbcrlf&vbcrlf&strval 
strval=""

'//User Type
set oEnv=WshShell.Environment("User")
for each sitem in oEnv 
strval=strval & sItem &vbcrlf 
next
wscript.echo "User Environment:"&vbcrlf&vbcrlf&strval 
strval=""

'//Volatile Type
set oEnv=WshShell.Environment("Volatile")
for each sitem in oEnv 
strval=strval & sItem &vbcrlf 
next

wscript.echo "Volatile Environment:"&vbcrlf&vbcrlf&strval 
strval=""

Running the Hack

To run the script, open a command prompt, change to the directory where the script is saved, and type cscript.exe GetEnvVars.vbs. Here is an example of typical output from the script on a Windows 2000 machine:

Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Working with the Environment: Provided by www.dudeworks.net

Environment.item: %SystemRoot%
ExpandEnvironmentStrings: C:\WINNT
Adding ( TestVar=Windows Script Host ) to the System type environment
removing ( TestVar=Windows Script Host ) from the System type environment
System Environment:

ComSpec=%SystemRoot%\system32\cmd.exe
Os2LibPath=%SystemRoot%\system32\os2\dll;
Path=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem
windir=%SystemRoot%
OS=Windows_NT
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_LEVEL=6
PROCESSOR_IDENTIFIER=x86 Family 6 Model 5 Stepping 2, GenuineIntel
PROCESSOR_REVISION=0502
NUMBER_OF_PROCESSORS=1
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
TEMP=%SystemRoot%\TEMP
TMP=%SystemRoot%\TEMP

Process Environment:

=C:=C:\
=ExitCode=00000000
ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\Administrator\Application Data
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=SNOOPY
ComSpec=C:\WINNT\system32\cmd.exe
HOMEDRIVE=C:
HOMEPATH=\Documents and Settings\Administrator
LOGONSERVER=\\SNOOPY
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Os2LibPath=C:\WINNT\system32\os2\dll;
Path=C:\WINNT\system32;C:\WINNT;C:\WINNT\System32\Wbem
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 5 Stepping 2, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0502
ProgramFiles=C:\Program Files
PROMPT=$P$G
SystemDrive=C:
SystemRoot=C:\WINNT
TEMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
TMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
USERDOMAIN=SNOOPY
USERNAME=Administrator
USERPROFILE=C:\Documents and Settings\Administrator
windir=C:\WINNT

User Environment:

TEMP=%USERPROFILE%\Local Settings\Temp
TMP=%USERPROFILE%\Local Settings\Temp

Volatile Environment:

LOGONSERVER=\\SNOOPY
APPDATA=C:\Documents and Settings\Administrator\Application Data

By the way, if you add a new variable via the command prompt, you will not see it when you try to read it via the script. You can read only the new values created via the same scripting type you used to create them. Although I’ve tested this only to a limited extent, it seems to be true. Try it for yourself; just open a command prompt, type Set DUDE=Dudeworks, and press Enter to set the new environment variable. Now, when you execute GetEnvVars.vbs, and you’ll notice that it does not list that new variable. However, if you type SET at the command prompt, you will see it.

Rob Olson

Extend Group Policy

Group Policy is a powerful tool for managing Windows systems, but by configuring ADM files you can extend its capabilities even further.

One day, one of my customers gave me a phone call to say that “the Group Policy Plan we made was pretty nice, but there’s something missing, and if we had this we could really impress our boss.” From that day on, my life wasn’t the same, because this comment led to me discover the true power of Group Policy through customizing ADM files.

But first you need to understand the basics of ADM files.

ADM Files

An ADM file is an ASCII file that defines the Group Policy settings; every checkbox, drop-down menu, and folder in the Group Policy window is defined in this file. The ADM file can also be hacked with any text editor to extend the built-in settings of Group Policy, or you could even build a custom ADM to import to your own Group Policies files. This customization feature makes Group Policy a more powerful tool to manage computers.

The default Group Policy Object (GPO) created in Active Directory is composed of three ADM files: conf.adm, inetres.adm, and system.adm. The conf.adm file holds all the policy settings for Microsoft NetMeeting. The inetres.adm file holds some of the settings for the Windows Components section under both Computer and User Configuration portions of Group Policy. Finally, the system.adm file has additional settings for the Windows Components and System sections under Administrative Template in both the Computer and User Configuration portions of the Group Policy.

These ADM files are located in the %winnt%\inf folder, and every other ADM file that is installed on your machine will be put into that location as well. Also, many products that Microsoft has released for Windows 2000/XP have their own ADM files. For example, the Microsoft Office XP Resource Kit has a corresponding ADM file for each product of the Office suite. For instance, an ADM file called word10.adm adds policy settings that affect Word XP on clients computers.

Hacking ADM Files

How do you to find the policy you want to edit? And how do you change it? In the following example, I want to find and edit the “Save Word files as” policy in the word10.adm file. This policy defines the way a file is saved by default in Word XP. I usually add the option to save the Word file in a format that appears in a local version of Word but doesn’t appear in the ADM.

Figure 1-11 shows what the policy looks like.

Editing a policy setting
Figure 1-11. Editing a policy setting

As you can see, the policy setting is found in the Save folder and its name is “Save Word files as.” Now, if I want to find this policy in the appropriate ADM file, I simply need to look for “Save Word files as.” To do this, just open the correct ADM file (which in this case is word10.adm) and do a text search for the string “Save Word files as”. You’ll find the following section of the ADM file:

POLICY "Save Word files as"
KEYNAME Software\Policies\Microsoft\Office\10.0\Word\Options
PART "Save Word files as" DROPDOWNLIST
VALUENAME DefaultFormat
ITEMLIST
NAME "Word document (*.doc)" VALUE "DEFAULT"
NAME "Web Page (*.htm; *.html)" VALUE "HTML"
NAME "Word 6.0/95 (*.doc)" VALUE "MSWord6Exp"
NAME "Word 6.0/95 - Japanese (*.doc)" VALUE"MSWord6JExp"
NAME "Word 6.0/95 - Korean (*.doc)" VALUE "MSWord95KExp"
NAME "Word 97-2002 & 6.0/95 - RTF" VALUE "MSWord6RTFExp"
NAME "Works 4.0 for Windows (*.wps)" VALUE "MSWorksWin4"
NAME "Works 3.0 for Windows (*.wps)" VALUE "MSWorksWin3"
END ITEMLIST
NOSORT
END PART
END POLICY

As you can see, the first line, Policy "Save Word files as“, defines the name of the policy as it appears in Figure 1-11, while everything under that line defines the policy settings until the last line, END POLICY, closes the policy. Looking at this further, KEYNAME defines the path to the affected key in the Registry, PART defines the way the policy box will appear in the GUI (in this case, a drop-down menu list), VALUENAME defines the name of the affected value in the Registry, NAME defines the name of each option as it appears in the drop-down list, and VALUE specifies the actual data that will be inserted into the affected value that is defined by VALUENAME.

So, if I want to add another option to be displayed in the drop-down list of this policy, all I need to do is add the following line wherever I want (within the section bounded by ITEMLIST and END ITEMLIST):

NAME "Word 97-2002 & 6.0/95 Hebrew Converter\doc" VALUE "MSWord6HBRExp"

Figure 1-12 shows the result of what will be added to the policy drop-down list in the GUI.

Adding an option to a drop-down list
Figure 1-12. Adding an option to a drop-down list

Easy, isn’t it? With this method, you can manipulate virtually any Registry key that is in the HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER hives to extend Group Policy.

If you’d like to learn more about hacking ADM files, see http://www.microsoft.com/windows2000/en/server/help/sag_spconcepts_34.htm from the Windows 2000 Server online documentation. Note that occasionally you might not see the results of your hack; see article 228723 in the Knowledge Base on TechNet for more information (http://support.microsoft.com/default.aspx?scid=kb;en-us;228723).

Oren Zippori

Disable EFS

While the Encrypted File System of Windows 2000/XP can be useful for protecting data, your best approach might actually be to disable it.

The Encrypted File System (EFS) feature was first introduced in Windows 2000 and is also available in Windows XP Professional. EFS provides a much higher level of security than the one offered by NTFS alone, which can be circumvented without much effort as long as physical access to the computer is allowed. EFS is extremely easy to use and is available without any special configuration because it is enabled by default. Even though it seems that with all these advantages EFS should quickly find its place in everyone’s environment, implementating it properly is a fairly complex task.

The Problem

Your two primary concerns are the ability to recover encrypted files and the protection of private keys used for encryption, which are associated with each user’s account and the recovery agent’s account. Recovery of encrypted files might be a fairly common occurrence. Because the private keys necessary for decryption are stored in the user’s profile, if the profile gets deleted or corrupted, the user can no longer access their encrypted files. The process of recovery involves simply logging on as an account that is designated as a data recovery agent. By default, this account is a local administrator on a standalone computer and a domain administrator in a domain environment. Because the private keys for data recovery agents are also stored as part of their profiles, it is recommended that private keys for data recovery agents should be exported from the computer that contains them and stored in a secure place until a recovery needs to be performed.

Currently, without using any custom solution, backup and storage of a user’s private keys (without backing up the entire profile) tends to be a time-consuming process. In addition, using nondefault recovery agents (which is the recommended procedure) requires installation of the Certificate Authority feature, which also needs to be managed properly. If you are not ready to handle all these additional tasks, your best bet might simply be to temporarily disable EFS on users’ machines.

The Solution

In the Windows 2000 domain environment, launch the Group Policy MMC snap-in and select the Group Policy Object (GPO) linked to your domain. Then, drill down to Computer ConfigurationWindows SettingsSecurity SettingsPublic Key PoliciesEncrypted Data Recovery Agents, right-click on the folder labeled Encrypted Data Recovery Agents, and select Delete Policy to delete the default recovery policy. Then, right-click on Encrypted Data Recovery Agents again and select Initialize Empty Policy. This will remove users’ ability to use EFS on any Windows 2000 system that belongs to the domain. In absence of EFS recovery agent, Windows 2000 clients will refuse to encrypt any files or folders.

However, you might be in for a surprise if you try to use the same approach in Windows XP, because Microsoft changed the default EFS behavior to allow a Windows XP client to use encryption even if no Data Recovery Agent is available (the same is true for Windows Server 2003). Fortunately, there are several new ways of preventing this, which we’ll look at now.

Disabling EFS for a file

Windows XP offers greater flexibility in configuring the scope of reach of EFS. If your intention is to disable EFS for a single file, you can simply assign the system attribute to the file. Although this is not the most elegant solution, it does provide a quick workaround. In order to apply the system attribute to a file, use the attrib command with +s parameter. For example, to apply the system attribute to the info1.txt file, type the following at the command prompt:

attrib +s info1.txt

Disabling EFS for a folder

If you instead want to prevent EFS on the folder level, you can create a desktop.ini file in the folder. The desktop.ini file should contain the following two lines:

[Encryption]
Disable=1

This will affect the folder itself and all of its files. However, it does not have any impact on its subfolders and their content.

Disabling EFS for a system

Finally, if you prefer, you can disable EFS on the system level. This can be accomplished by editing the Registry. Set the following entry of DWORD type to the value 1:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\EfsConfiguration

It is easier, however, to use Group Policy for this purpose. Start by launching Local Security Policy from the Administrative Tools menu. Next, double-click on the Public Key Policies folder. You will see a subfolder named Encrypting File System. Right-click on it and select Properties from the context-sensitive menu. You will notice a checkbox labeled “Allow users to encrypt files using Encrypting File System (EFS),” as shown in Figure 1-13.

Disabling EFS in Windows XP/2003
Figure 1-13. Disabling EFS in Windows XP/2003

Unchecking this box will disable EFS altogether on the system. Note that this setting can be also used to together with Group Policy to disable EFS for all computers residing in any of Active Directory containers—sites, domains, or organizational units.

Marcin Policht

Get Event Log Information

Need to check on the size and configuration settings of your event logs? Use this script instead of the GUI; it’s faster!

Monitoring event logs is an essential part of an administrator’s job. Unfortunately, viewing event log settings and log file sizes from the GUI is cumbersome, and it would be useful to have an easier way to obtain this information.

That’s exactly what this hack is all about. You can run the script on Windows NT/2000 and later to obtain the current file size, maximum file size, and number of records, and you can overwrite settings on the Application, System, and Security logs.

The Code

Type the following script into Notepad (make sure Word Wrap is disabled) and save it with a .vbs extension as loginfo.vbs. Or, if you like, you can download the script from the O’Reilly web site.

Option Explicit
On Error Resume Next
Dim strMoniker
Dim refWMI
Dim colEventLogs
Dim refEventLog
Dim strSource

'moniker string stub - security privilege needed to get
'numrecords for Security log
strMoniker = "winMgmts:{(Security)}!"

'append to moniker string if a machine name has been given
If WScript.Arguments.Count = 1 Then _
strMoniker = strMoniker & "\\" & WScript.Arguments(0) & ":"

'attempt to connect to WMI
Set refWMI = GetObject(strMoniker)
If Err <> 0 Then
WScript.Echo "Could not connect to the WMI service."
WScript.Quit
End If

'get a collection of Win32_NTEventLogFile objects
Set colEventLogs = refWMI.InstancesOf("Win32_NTEventLogFile")
If Err <> 0 Then
WScript.Echo "Could not retrieve Event Log objects"
WScript.Quit
End If

'iterate through each log and output information
For Each refEventLog In colEventLogs
WScript.Echo "Information for the " & _
refEventLog.LogfileName & _
" log:"
WScript.Echo " Current file size: " & refEventLog.FileSize
WScript.Echo " Maximum file size: " & refEventLog.MaxFileSize
WScript.Echo " The Log currently contains " & _
refEventLog.NumberOfRecords & " records"

'output policy info in a friendly format using OverwriteOutDated,
'as OverWritePolicy is utterly pointless.
'note "-1" is the signed interpretation of 4294967295
Select Case refEventLog.OverwriteOutDated
Case 0 WScript.Echo _
" Log entries may be overwritten as required"
Case -1 WScript.Echo _
" Log entries may NEVER be overwritten"
Case Else WScript.Echo _
" Log entries may be overwritten after " & _
refEventLog.OverwriteOutDated & " days"
WScript.Echo
End Select
Next

Set refEventLog = Nothing
Set colEventLogs = Nothing
Set refWMI = Nothing

Running the Hack

To run the script, use Cscript.exe, the command-line version of the Windows Script Host (WSH). Simply type cscript loginfo.vbs at a command prompt from the directory in which the script resides. Here is a sample of typical output when the script runs on a Windows 2000 machine:

C:\>cscript loginfo.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Information for the Security log:
 Current file size: 65536
 Maximum file size: 524288
 The Log currently contains 166 records
 Log entries may be overwritten after 7 days

Information for the Application log:
 Current file size: 524288
 Maximum file size: 524288
 The Log currently contains 2648 records
 Log entries may be overwritten as required

Information for the System log:
 Current file size: 524288
 Maximum file size: 524288
 The Log currently contains 2648 records
 Log entries may be overwritten after 7 days

Note that when you run this script on a domain controller it displays information concerning the Directory Service, File Replication Service, and DNS logs as well.

Rod Trent

Shortcut to Remote Assistance

Remote Assistance is a helpful feature for troubleshooting Windows XP systems, but it’s a pain for ordinary users to use. This hack creates a helpful shortcut to this feature.

Windows XP provides a Remote Assistance feature, but you have to walk through several screens to get to it. This can be a problem for users who are not technically savvy, and you might find yourself spending a lot of time explaining to them how to use the feature. However, there’s a really cool workaround. Place a shortcut to this feature on users’ desktops. This will provide them with quicker access to the screen where they can type in the remote computer’s IP address to ask for remote assistance. This approach will make life easier for both you and your users.

First, right-click on the desktop and choose NewShortcut. Then, in the Create Shortcut box, type the following URL into the Location Box:

hcp://CN=Microsoft%20Corporation,L=Redmond,S=Washington,C=US/Remote%20Assistance/
Escalation/Unsolicited/unsolicitedrcui.htm

as shown in Figure 1-14.

Creating a shortcut to the Remote Assistance feature
Figure 1-14. Creating a shortcut to the Remote Assistance feature

Click Next and name the shortcut something descriptive, like “Remote Assistance” (Figure 1-15).

Naming the shortcut
Figure 1-15. Naming the shortcut

When the shortcut creation is finished, you’ll have an icon on your desktop for Remote Assistance (Figure 1-16).

Desktop icon for Remote Assistance
Figure 1-16. Desktop icon for Remote Assistance

When you double-click on this icon, you’ll be whisked away to the Remote Assistance feature, as shown in Figure 1-17. Simply type the computer name or IP address of the computer you want to connect to for remote assistance.

Remote Assistance window
Figure 1-17. Remote Assistance window

Pretty handy, eh?

Rod Trent

Desktop Checker

Here’s a useful script to quickly display the configuration of a remote system for troubleshooting or inventory purposes.

This handy script will attempt to gather various Windows NT/2000/XP/2003 operating-system attributes and display them in a coherent way to assist in troubleshooting. I highly suggest modifying the customization variables located within the script. To edit this text file, just open it with Notepad (leave Word Wrap turned off). Even if you have no experience with VBScript, you should find the changes quite easy to make. Please read the comments for different sections to make the tool viable for your organization.

This tool was intended to use only standard API calls and nothing from third-party COM objects. This keeps the tool lightweight and portable as only a text file. I suggest putting the tool into a local directory by itself so that the HTML pages it creates don’t get out of hand. If a machine does not have WMI 1.5, then a lot of info might be missing. You will get similar results if you don’t have administrator rights on the remote box. This script will not work on any Windows 9x operating systems.

The Code

You can download this script as DesktopChecker.vbs from the O’Reilly web site at http://www.oreilly.com/catalog/winsvrhks/:

'**************************************************************
'*                                                            *
'*  Desktop Checker - This script will ATTEMPT to gather      *
'*  various OS attributes and diplay them in a coherent       *
'*  way to assist in troubleshooting.  I highly suggest       *
'*  modifying the customization variables located 2 sections  *
'*  below.  Please read the comments for different sections   *
'*  to make the tool viable for your organization.  This      *
'*  tool was intended to use only standard API calls and      *
'*  nothing from 3rd party COM objects.  This keeps the       *
'*  tool lightwieght and portable as only a text file.        *
'*  I suggest putting the tool into a directory by itself     *
'*  so that the HTML pages it creates don't get out of hand.  *
'*  If a machine does not have WMI 1.5 then lots of info may  *
'*  be missing.                                               *
'*                                                            *
'*  Dennis Abbott                                             *
'*  speckled_trout@hotmail.com                                *
'*                                                            *
'**************************************************************
On Error Resume Next
Dim WshShell,WshFso,WshNet,WshSysEnv,IE,wmi,ADSIobj,OutPutFile,DumpFile
Dim PathToScript,ComSpec,Cnt,CompName,Company,Title,LogoLink,SelectServices, _
Domain,Progress,Instance,CurLine
Set WshShell = CreateObject("Wscript.Shell")
Set WshFso = CreateObject("Scripting.FileSystemObject")
Set WshNet = CreateObject("Wscript.Network")
Set WshSysEnv = WshShell.Environment("SYSTEM")
PathToScript = Left(WScript.ScriptFullName,(Len(WScript.ScriptFullName) - _ 
(Len(WScript.ScriptName) + 1)))
ComSpec = WshSysEnv("COMSPEC")
Cnt = 0

' grab contents of clipboard
' This allows you to work a LIST of boxes by cut-n-paste
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate("about:<script language=" & Chr(34)
& "vbscr" & "ipt" & Chr(34) & ">function go( ):document.all.it2.select"
 & "( ):document.execCommand " & 
Chr(34) & "Paste" & Chr(34) & ":en" & "d function</script><body 
onload=go( )>
<input type=t" & "ext value=" & Chr(34) & "start" & Chr(34) & " 
id=it2></body>")
While IE.ReadyState <> 4:Wend
CompName = IE.document.all.it2.value
IE.quit( )
Set IE = Nothing

' SET CUSTOMIZATION VARIABLES
Company = "myITforum"
Title = Company & " - Helpdesk Diagnostic Tool"
LogoLink = "http://www.myitforum.com/img/logo_final.gif"
' The next line alows you to query a variety of NT services of your choosing
' Make sure you enter the service NAME not the DISPLAY NAME, they can be
  different names
SelectServices = Array("WinMgmt","Norton Antivirus Server","DefWatch","clisvc","Dhcp")
Domain = "amd"  'Your NT domain
Progress = True   
'causes pop-up boxes when set to True it is silent when set to False

CompName = InputBox("Enter the name of the remote computer",Title,CompName)
If CompName = "" Then MsgBox "No machine name was entered.....goodbye" : _ Wscript.Quit(0)
Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!//" & _ CompName)
Set ADSIobj = GetObject("WinNT://" & CompName & ",Computer")

Call PrepHTML(CompName)  'create an HTML file

If Progress Then
    WshShell.Popup "Getting OS information",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetOS(CompName)
If Progress Then
    WshShell.Popup "Getting NT administrators",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetAdmins(CompName)
If Progress Then
    WshShell.Popup "Checking Vital Services",2,Title, vbokonly + _
    vbsystemmodal
End If
Call Services(CompName,SelectServices)
If Progress Then
    WshShell.Popup "Checking Admin shares",2,Title, vbokonly + vbsystemmodal
End If
Call AdminShares(CompName)
If Progress Then
    WshShell.Popup "Getting date/time stamp",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetTime(CompName)
If Progress Then
    WshShell.Popup "Getting NetBIOS information",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetNBTstat(CompName)
If Progress Then
    WshShell.Popup "Pinging computer",2,Title, vbokonly + vbsystemmodal
End If
Call Ping(CompName)
If Progress Then
    WshShell.Popup "Getting Registry Quota",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetRegQuota(CompName)
If Progress Then
    WshShell.Popup "Getting Hardware information",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetHW(CompName)
If Progress Then
    WshShell.Popup "Getting Network Card information",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetNIC(CompName)
If Progress Then
    WshShell.Popup "Getting Software information",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetSW(CompName)
If Progress Then
    WshShell.Popup "Getting Critical NT Events",2,Title, vbokonly + _
    vbsystemmodal
End If
Call GetEvents(CompName)
Call ExitScript

Function PrepHTML(CompName)
    Set OutPutFile = WshFso.CreateTextFile(PathToScript & "\" & CompName _
    & ".html")
    OutPutFile.WriteLine "<body>"
    OutPutFile.WriteLine "<h1><center>" & Title & "</center></h1>"
    OutPutFile.WriteLine "<p><IMG SRC=" & Chr(34) & LogoLink & Chr(34) _
    & "</img></p>"
    OutPutFile.WriteLine "</p><p>" & "Account running this script is " _
    & WshNet.UserDomain & "\" & WshNet.UserName & " @ " _
    & Now & " from workstation " & WshNet.ComputerName & "</p>"
    OutPutFile.WriteLine "<p>Information on remote machine <b>\\" _
    & UCase(CompName) & "</b></p>"
    OutPutFile.WriteLine "<p><font color=red>To see information as it " _ 
    loads hit the REFRESH button on your web browser.</font></p>"
    OutPutFile.WriteLine "<hr>"
    WshShell.Run PathToScript & "\" & CompName & ".html"
End Function

Function GetOS(CompName)
    OutPutFile.WriteLine "<h3>1 - Operating System</h3>"
    OutPutFile.WriteLine "Operating System Version = " _
    & ADSIobj.OperatingSystem & " " & ADSIobj.OperatingSystemVersion & "<br>"
    For Each Instance in wmi.ExecQuery("Select * From Win32_OperatingSystem")
        OutPutFile.WriteLine "Operating System Caption = " _
        & Instance.Caption & "<br>"
        OutPutFile.WriteLine "Operating System Service Pack = " _
        & Instance.CSDVersion & "<br>"
        OutPutFile.WriteLine "Operating System LastBootUpTime = " _
        & StrDateTime(Instance.LastBootUpTime) & "<br>"
        OutPutFile.WriteLine "Operating System Directory = " _
        & Instance.WindowsDirectory & "<br>"
    Next
    OutPutFile.WriteLine "<hr>"
End Function

Function GetAdmins(CompName)
    Dim Admins,Admin
    Dim AdsInfo
    Set Admins = GetObject("WinNT://" & CompName & "/Administrators")
    OutPutFile.WriteLine "<h3>2 - Members of the local " _
    & "administrators group</h3>"
    OutPutFile.WriteLine "<table border=1><tr><td><b>Name</
b></td><td><b>Type</b></td><td><b>
Description</b></td></tr>"
    For Each Admin in Admins.Members
        Set AdsInfo = GetObject(Admin.adspath)
        OutPutFile.WriteLine "<tr><td>" & AdsInfo.Name & "</td><td>" _
        & AdsInfo.Class & "</td><td>" & AdsInfo.Description & "</td></tr>"
    Next
    OutPutFile.WriteLine "</table>"
    OutPutFile.WriteLine "<hr>"
End Function

Function Services(CompName,SelectServices)
    Dim Service,srvc,State,Strg
    OutPutFile.WriteLine "<h3>3 - Status of vital services</h3>"
    OutPutFile.WriteLine "<table border=1><tr><td><b>Service 
Name</b></td><td><b>Display Name</b></td><td>
<b>Status</b></td></tr>"
    For Each Service in SelectServices
        Strg = "<tr><td>" & Service & "</td><td></
td><td><b><font color=FF0000>NOT PRESENT</font></b></
td></tr>"
        ADSIobj.Filter = Array("Service")
        For Each srvc in ADSIobj
            Select Case srvc.Status
            Case 1 State = "<font color=FF0000>STOPPED</font>"
            Case 2 State = "<font color=FF0000>START_PENDING</font>"
            Case 3 State = "<font color=FF0000>STOP_PENDING</font>"
            Case 4 State = "RUNNING"
            Case 5 State = "<font color=FF0000>CONTINUE_PENDING</font>"
            Case 6 State = "<font color=FF0000>PAUSE_PENDING</font>"
            Case 7 State = "<font color=FF0000>PAUSED</font>"
            Case Else State = "<font color=FF0000>ERROR</font>"
            End Select
                If LCase(srvc.Name) = LCase(Service) Then Strg = _
                "<tr><td>" & srvc.Name & "</td><td>" &
 srvc.DisplayName _
                & "</td><td>" & State & "</tr></td>"
        Next
    OutPutFile.WriteLine Strg    
    Next
    OutPutFile.WriteLine "</table>"
    OutPutFile.WriteLine "<hr>"
End Function

Function AdminShares(CompName)
    Dim Shares
    OutPutFile.WriteLine "<h3>4 - Status of administrative shares</h3>" 
    Shares = True
    If WshFso.FolderExists("\\" & CompName & "\c$") = True Then
        OutPutFile.WriteLine "C$ share exists<br>"
    Else
        Shares = False
        OutPutFile.WriteLine "<font color=red>C$ share is not " _
        & "accessible</font><br>"
    End If
    If WshFso.FolderExists("\\" & CompName & "\admin$") = True Then
        OutPutFile.WriteLine "admin$ share exists<br>"
    Else
        Shares = False
        OutPutFile.WriteLine "<font color=red>admin$ share is not " _
        & "accessible</font><br>"
    End If
    If Shares = False Then
        OutPutFile.WriteLine "<br>"
        OutPutFile.WriteLine "<font color=red>Shares made not be " _
        & "accessible due to the folowing reasons:</font><br>"
        OutPutFile.WriteLine "<font color=red>a - You do not have " _
        & "admin rights on this box</font><br>"
        OutPutFile.WriteLine "<font color=red>b - box is offline</font><br>"
        OutPutFile.WriteLine "<font color=red>c - Server service is not " _
        & "running</font><br>"
        OutPutFile.WriteLine "<font color=red>d - Shares have been " _
        & "disabled</font><br>"
        OutPutFile.WriteLine "<font color=red>e - remote machine's " _
        & "operating system is not NT-based</font><br>"
    End If
    OutPutFile.WriteLine "<hr>"
End Function

Function GetTime(CompName)
    OutPutFile.WriteLine "<h3>5 - Current date and time</h3>" 
    OutPutFile.WriteLine "Current date and time of a domain controller<br>"
    WshShell.Run ComSpec & " /c net time /DOMAIN:" & Domain & " >" _
    & PathToScript & "\time.txt",6,True 
    Set DumpFile = WshFso.OpenTextFile(PathToScript & "\time.txt", 1, True)
    Do While DumpFile.AtEndOfStream <> True
        CurLine = DumpFile.ReadLine
        If InStr(CurLine,"Current") <> 0 Then
            OutPutFile.WriteLine CurLine & "<br>"
        End If
    Loop
    DumpFile.Close
    OutPutFile.WriteLine "Current date and time of computer you are " _
    & "troubleshooting<br>"
    WshShell.Run ComSpec & " /c net time \\" & CompName " _
    & " >" & PathToScript & "\time.txt",6,True 
    Set DumpFile = WshFso.OpenTextFile(PathToScript & "\time.txt", 1, True)
    Do While DumpFile.AtEndOfStream <> True
        CurLine = DumpFile.ReadLine
        If InStr(CurLine,"Current") <> 0 Then
            OutPutFile.WriteLine CurLine & "<br>"
        End If
    Loop
    DumpFile.Close
    OutPutFile.WriteLine "<hr>"
End Function

Function Ping(CompName)
    OutPutFile.WriteLine "<h3>7 - Ping test (DNS name resolution)</h3>"
    OutPutFile.WriteLine "<h4>If you get no reply on the ping yet other data is 
retrieved on this page then there is most likely a problem with a static DNS entry.  
This needs to be fixed before anything else.  You MUST VERIFY the machine is running 
DHCP before 
you modify the static DNS entry!!!!</h4>"
    WshShell.Run ComSpec & " /c ping " & CompName & " >" & 
PathToScript & _
    "\ping.txt",6,True 
    Set DumpFile = WshFso.OpenTextFile(PathToScript & "\ping.txt", 1, True)
    Do While DumpFile.AtEndOfStream <> True
         OutPutFile.WriteLine DumpFile.ReadLine & "<br>"
    Loop
    Set DumpFile = Nothing
    OutPutFile.WriteLine "<hr>"
End Function

Function GetNBTstat(CompName)
    Dim User
    User = "Nobody Logged On"    
    WshShell.Run ComSpec & " /c nbtstat -a " & CompName & " >" & 
PathToScript & "\nbt.txt",6,True 
    Set DumpFile = WshFso.OpenTextFile(PathToScript & "\nbt.txt", 1, True)
    Do While DumpFile.AtEndOfStream <> True
        CurLine = DumpFile.ReadLine
        If InStr(CurLine,"---") <> 0 Then
            CurLine = DumpFile.ReadLine
            CompName = Trim(Left(CurLine,InStr(CurLine,"<")-1))
        End If
        If InStr(CurLine,"<03>") <> 0 Then
            If Trim(Left(CurLine,InStr(CurLine,"<03>")-1)) <> _
            UCase(CompName) and _
            Trim(Left(CurLine,InStr(CurLine,"<03>")-1)) <> _
            UCase(CompName) & "$" Then
                User = Trim(Left(CurLine,InStr(CurLine,"<03>")-1))
            End If
        End If
        If InStr(CurLine,"<1E>") <> 0 Then
            If Trim(Left(CurLine,InStr(CurLine,"<1E>")-1)) <> UCase(CompName) 
and Trim(Left(CurLine,InStr(CurLine,"<1E>")-1)) <> UCase(CompName) & "$" 
Then
                Domain = Trim(Left(CurLine,InStr(CurLine,"<1E>")-1))
            End If
        End If
    Loop
    OutPutFile.WriteLine "<h3>6 - NetBIOS Info</h3>"
    OutPutFile.WriteLine "Current User Logged on = " & User & " (this value may 
not be accurate, it depends on the box's messenger service)<br>"
    OutPutFile.WriteLine "Domain machine is joined to = " & Domain & "<br>"
        DumpFile.Close
           OutPutFile.WriteLine "<hr>"
End Function

Function GetNIC(CompName)
    OutPutFile.WriteLine "<h3>9 - Network Card Configuration</h3>"
    For Each Instance in wmi.ExecQuery("Select * From Win32_" & _
    "NetworkAdapterConfiguration Where IPenabled = 'True'")
        OutPutFile.WriteLine "<table border=1><tr><td><b>" & _
        "Attribute</b></td><td><b>Value</b></td></tr>"
        OutPutFile.WriteLine "<tr><td>Name of card</td><td>" _
        & Instance.Caption & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>DHCP Enabled</td><td>" _
        & Instance.DhcpEnabled & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>IP address</td><td>" _
        & Instance.IPAddress(0) & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>Subnet Mask</td><td>" _
        & Instance.IPSubnet(0) & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>MAC Address</td><td>" _
        & Instance.MACAddress & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>DNS HostName</td><td>" _
        & Instance.DNSHostname & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>DNS Servers(in order)</td><td>" _
        & Instance.DNSServerSearchOrder(0) & " : " _
        & Instance.DNSServerSearchOrder(1) & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>Primary WINS</td><td>" _
        & Instance.WINSPrimaryServer & "</td></tr>"
        OutPutFile.WriteLine "<tr><td>Secondary WINS</td><td>" _
        & Instance.WINSSecondaryServer & "</td></tr>"
        OutPutFile.WriteLine "</table>"
    Next
    OutPutFile.WriteLine "<hr>"
End Function

Function GetRegQuota(CompName)
    OutPutFile.WriteLine "<h3>8 - Registry size information</h3>"
    For each Instance in wmi.InstancesOf("Win32_Registry")
        OutPutFile.WriteLine "Current Registry size is " _
        & Instance.CurrentSize & " MB's.<br>"
        OutPutFile.WriteLine "Maximum Registry size is " _
        & Instance.MaximumSize & " MB's.<br>"
        If Instance.MaximumSize - Instance.CurrentSize < 8 Then
            OutPutFile.WriteLine "<font color=red><b>The Registry quota on " _
            & CompName & " may need to be increased!!!</font></b><br>"
        End If
    Next
    OutPutFile.WriteLine "<hr>"
End Function

Function GetHW(CompName)
    Dim stuff
    OutPutFile.WriteLine "<h3>10 - Hardware Information</h3>"
    For Each Instance in wmi.ExecQuery("Select * From Win32_" & _
    "LogicalDisk Where DeviceID = 'C:'")
        OutPutFile.WriteLine "Total Drive space available on C: is " &  Left(Instance.
FreeSpace/1000000,InStr(Instance.FreeSpace/1000000, ".")-1) & " Megabytes.<br>"
        stuff = ((Instance.Size - Instance.FreeSpace)/Instance.Size)*100
        OutPutFile.WriteLine "The C: drive is " _
        & Left(stuff,InStr(stuff, ".")-1) & "% full.<br>"
    Next
    For Each Instance in wmi.ExecQuery("Select * From Win32_ComputerSystem")
        OutPutFile.WriteLine "Computer Manufacturer = " _
        & Instance.Manufacturer & "<br>"
        OutPutFile.WriteLine "Computer Model = " & Instance.Model & "<br>"
        OutPutFile.WriteLine "Total Physical Memory = " & Left
(Instance.TotalPhysicalMemory/1000000,InStr(Instance.TotalPhysicalMemory/1000000,".")-1) 
& " MB's" & "<br>"
    Next
    For Each Instance in wmi.ExecQuery("Select * From Win32_" & _
    "SystemEnclosure")
        OutPutFile.WriteLine "Asset Tag = " & Instance.SMBIOSassettag " _
        & "<br>"
        OutPutFile.WriteLine "Serial Number = " & Instance.serialnumber " _
        & "<br>"
    Next
    For Each Instance in wmi.ExecQuery("Select * From Win32_Processor")
        OutPutFile.WriteLine "Processor Name = " & Instance.Name & "<br>"
        OutPutFile.WriteLine "Processor Clock Speed = " _
        & Instance.CurrentClockSpeed & " MHz<br>"
        OutPutFile.WriteLine "Processor Voltage = " _
        & Instance.CurrentVoltage & " Volts<br>"
        OutPutFile.WriteLine "Current Processor Load = " _
        & Instance.LoadPercentage & "%<br>"
    Next
    OutPutFile.WriteLine "<hr>"
End Function

Function GetSW(CompName)
    Dim oReg
    Dim NavParent,PatternDate,NavDir,NavVer,IEVersion,program,installed,
    Version,ProgramName
    OutPutFile.WriteLine "<h3>11 - Software Information</h3>"
    Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!//" _
    & CompName & "/root/default:StdRegProv")
    oReg.getstringvalue 2147483650,"SOFTWARE\INTEL\LANDesk\VirusProtect6\CurrentVersion\",
"Parent",NavParent
    oReg.getstringvalue 2147483650,"SOFTWARE\Symantec\SharedDefs\", _
    & "NAVCORP_70",PatternDate
    oReg.getstringvalue 2147483650,"SOFTWARE\Symantec\InstalledApps\" & _
    ","NAV",NavDir
    If UCase(Left(NavDir,1)) = "C" Then
        NavVer = WshFso.GetFileVersion("\\" & CompName & "\c$\" _
        & Right(NavDir,Len(NavDir)-3) & "\vpc32.exe")
        OutPutFile.WriteLine "Norton Antivirus Version = " &  NavVer  _
        & "<br>"
    End If
    PatternDate = Right(PatternDate,12)
    OutPutFile.WriteLine "Norton Antivirus Parent Server = " & NavParent _
    & "<br>"
    OutPutFile.WriteLine "Norton Antivirus Definition Date = " _
    & Mid(PatternDate,5,2) & "/" & Mid(PatternDate,7,2) & "/" & 
Mid(PatternDate,1,4) & " Revision " & Right(PatternDate,3) & "<br>"
    oReg.getstringvalue 2147483650,"SOFTWARE\Microsoft\Internet Explorer\" & _
    ","Version",IEVersion
    OutPutFile.WriteLine "<p>Internet Explorer Version = " & IEVersion
    OutPutFile.WriteLine "<p>Installed Programs(from Add/Remove Programs applet)</
p>"
    OutPutFile.WriteLine "<table border=1><tr><td><b>Program 
Name</b></td><td><b>Version(if available)</b></td></
 tr>"
    oReg.EnumKey 2147483650, "SOFTWARE\Microsoft\Windows\CurrentVersion\" & _
    "Uninstall", installed
    For each program in installed
        oReg.getstringvalue 2147483650,"SOFTWARE\Microsoft\Windows\" & _
        "CurrentVersion\Uninstall\" & program & "\","DisplayName",ProgramName
        oReg.getstringvalue 2147483650,"SOFTWARE\Microsoft\Windows\" & _
        "CurrentVersion\Uninstall\" & program & "\","DisplayVersion",Version
        If ProgramName <> "" Then
            OutPutFile.WriteLine "<tr><td>" & ProgramName & "</
td><td>" & Version & "</td></tr>"
        End If
    Next
    OutPutFile.WriteLine "</table>"
    OutPutFile.WriteLine "<hr>"
End Function

Function GetEvents(CompName)
    OutPutFile.WriteLine "<h3>12 - First 25 Errors from the system event log</h3>"
    OutPutFile.WriteLine "<table border=1><tr><td><b>DateTimeStamp
</b></td><td><b>EventSource</b></td><td><b>
Message</b></td></tr>"
    For Each Instance in wmi.ExecQuery("Select * From Win32_NTLogEvent Where Type = 
'Error' and LogFile = 'System'")
        Cnt = Cnt + 1
        If Cnt = 25 Then Exit For
        OutPutFile.WriteLine "<tr><td>" & Mid(Instance.TimeGenerated,5,2) " _
        & "-" & Mid(Instance.TimeGenerated,7,2) & "-" _
        & Left(Instance.TimeGenerated,4) & "</td><td>" _
        & Instance.SourceName & "</td><td>" & Instance.Message & "</td></tr>"
    Next
    OutPutFile.WriteLine "</table>"
End Function
Function StrDateTime(d)
    Dim strVal,strDate,strTime
    strVal = CStr(d)
    strDate = DateSerial(Left(strVal, 4), _
    Mid(strVal, 5, 2), _
    Mid(strVal, 7, 2))
    strTime = TimeSerial(Mid(strVal, 9, 2), _
    Mid(strVal, 11, 2), _
    Mid(strVal, 13, 2))
    StrDateTime = strDate + strTime
End Function

Function ExitScript
    OutPutFile.WriteLine "</body>"
    OutPutFile.Close
    WshShell.Run PathToScript & "\" & CompName & ".html"
    If Progress Then 
        MsgBox "The " & Title & " script is done.",vbokonly + _
        vbsystemmodal,Title
    End If
    Set WshShell = Nothing
    Set WshFso = Nothing
    Set WshNet = Nothing
    Set OutPutFile = Nothing
    Wscript.Quit(0)
End Function

Running the Hack

To run this hack, simply double-click on the DesktopChecker.vbs file in Windows Explorer (or on a shortcut to the file on your desktop). Then, type the name of the remote computer you want to query using either its NetBIOS name, DNS name, or IP address. At this point, Internet Explorer will open and display a page titled “myITforum Helpdesk Diagnostic Tool,” followed by a series of dialog boxes that show the progress of the script (you don’t need to click OK to close these dialog boxes, because they close automatically). Once the final dialog box appears—“The myITforum Helpdesk Diagnostic Tool script is done”—click OK and refresh the web page to view the information.

Here’s some sample output generated when the script was run on a workstation using Domain Admin credentials. The target machine is a Windows Server 2003 machine named SRV230. The output of the script is in the form of an HTML page named srv230.htm, which is created in the same directory where the script itself resides, but the output has been reformatted here as text to make it easier to include in this book.

myITforum - Helpdesk Diagnostic Tool
Account running this script is MTIT2\administrator @ 12/3/2003 11:40:37 AM from 
workstation
SRV235
Information on remote machine \\SRV230
To see information as it loads hit the REFRESH button on your web browser.
----------------------------------------------------------------------------
1 - Operating System
Operating System Version = Windows NT 5.2
Operating System Caption = Microsoft(R) Windows(R) Server 2003, Enterprise Edition
Operating System Service Pack = 
Operating System LastBootUpTime = 12/3/2003 11:26:42 AM
Operating System Directory = C:\WINDOWS
----------------------------------------------------------------------------
2 - Members of the local administrators group
Name               Type   Description 
Administrator      User   Built-in account for administering the computer/domain 
Enterprise Admins  Group  Designated administrators of the enterprise 
Domain Admins      Group  Designated administrators of the domain 
----------------------------------------------------------------------------
3 - Status of vital services
Service Name             Display Name                        Status 
winmgmt                  Windows Management Instrumentation  RUNNING 
Norton Antivirus Server                                      NOT PRESENT 
DefWatch                                                     NOT PRESENT 
clisvc                                                       NOT PRESENT 
Dhcp                     DHCP Client                         RUNNING 
----------------------------------------------------------------------------
4 - Status of administrative shares
C$ share exists
admin$ share exists
----------------------------------------------------------------------------
5 - Current date and time
Current date and time of a domain controller
Current date and time of computer you are troubleshooting
----------------------------------------------------------------------------
6 - NetBIOS Info
Current User Logged on = Nobody Logged On (this value may not be accurate, it depends on 
the box's messenger service)
Domain machine is joined to = amd
----------------------------------------------------------------------------
7 - Ping test (DNS name resolution)
If you get no reply on the ping yet other data is retrieved on this page then there is 
most likely a problem with a static DNS entry. This needs to be fixed before anything 
else. 
You MUST VERIFY the machine is running DHCP before you modify the static DNS entry!!!!
----------------------------------------------------------------------------
8 - Registry size information
Current Registry size is 1 MB's.
Maximum Registry size is 88 MB's.
----------------------------------------------------------------------------
10 - Hardware Information
Total Drive space available on C: is 1776 Megabytes.
The C: drive is 58% full.
Computer Manufacturer = System Manufacturer
Computer Model = System Name
Total Physical Memory = 536 MB's
Asset Tag = Asset-1234567890
Serial Number = Chassis Serial Number
Processor Name = Intel(R) Pentium(R) III processor
Processor Clock Speed = 501 MHz
Processor Voltage = 29 Volts
Current Processor Load = 2%
----------------------------------------------------------------------------
9 - Network Card Configuration
Attribute              Value 
Name of card           [00000001] 3Com EtherLink XL 10/100 PCI For Complete PC Management 
NIC (3C905C-TX) 
DHCP Enabled           False 
IP address             172.16.11.230 
Subnet Mask            255.255.255.0 
MAC Address            00:01:02:FC:92:FC 
DNS HostName           srv230 
DNS Servers(in order)  172.16.11.230 :  
Primary WINS  
Secondary WINS  
----------------------------------------------------------------------------
11 - Software Information
Norton Antivirus Parent Server = 
Norton Antivirus Definition Date = // Revision 
Internet Explorer Version = 6.0.3790.0 
Installed Programs(from Add/Remove Programs applet)

Program Name                                                     Version(if available) 
FullShot V6  
Windows Media Player Hotfix [See wm819639 for more information]  
Remote Administration Tools                                      5.2.3790.0 
----------------------------------------------------------------------------
12 - First 25 Errors from the system event log
DateTimeStamp  EventSource  Message 
11-21-2003     W32Time      The time provider NtpClient is configured to acquire time 
from one or more time sources, however none of the sources are currently accessible. No 
attempt to contact a source will be made for 15 minutes. NtpClient has no source of 
accurate time.  
11-13-2003     DCOM         The server {A9E69610-B80D-11D0-B9B9-00A0C922E750} did not 
register with DCOM within the required timeout.  
etc...

Dennis Abbott

Top Five Tools

Here’s one IT professional’s take on five third-party tools for Windows 2000 every system administrator should have.

There can be no doubt that with every release of Microsoft’s operating system the need for third-party utilities becomes less and less. One major complaint about NT was its lack of disk quotas, something Unix has included since day one. A number of companies noticed this oversight and produced a product that did the trick. The release of Windows 2000 saw disk quotas become part of the OS, thus making the need to purchase this type of software an irrelevance for the majority of companies.

Whether you agree with Microsoft’s policy of continually adding features to its products that were once available only from other sources is one for debate. But in my role as a network administrator, I still find a need to seek out additional software to help make my job a lot easier. I’m sure everyone has their favorite must-have utilities, but these are my top five must-have add-on products for Windows 2000.

Server Monitor Lite

Server Monitor Lite is an invaluable monitoring product that allows you to monitor your servers centrally and get notified if a problem occurs. I use this utility to ping all my servers periodically, watch for low disk space, keep an eye on critical services, and make sure the company intranet is still accessible for my users. For more information, see http://www.purenetworking.net/Products/ServerMonitor/ServerMonitor.htm.

Lost Password Recovery

Have you inherited systems for which nobody knows the local administrator password, or do you have users that need access to Word, Excel, or Access documents that are password-protected and nobody knows the password? Well, this handy little product will save the day. It lets you reset the password on a huge array of systems. For more information, see http://www.lostpassword.com.

Data Replicator

Do you need to copy files from one system to another on a regular basis? Data Replicator makes this job much easier—it allows you to watch files or folders for changes, and then replicate them to another location. You can copy files across a LAN, WAN, or via FTP, which makes Data Replicator a great alternative to traditional backup software. For more information, see http://www.purenetworking.net/Products/DataReplicator/DataReplicator.htm.

Virtual Network Computing (VNC)

Take control of your remote servers from the comfort of your desk. VNC lets you control Windows, Unix, and Mac machines. For more information, see http://www.realvnc.com.

Network View

With this handy tool, you’ll never need to draw out your network. It automatically generates a network diagram for you within minutes. For more information, see http://www.networkview.com.

Janet Ryding

myITforum.com

One of the best resources around for administrators who deploy and manage Windows-based networks, myITforum.com is best described by its CEO and founder, Rod Trent.

myITforum.com (http://www.myitforum.com) is the leading systems administration web site and community. It was created to be the Internet’s premiere knowledge and information forum for IT professionals. The web site provides IT administrators the opportunity to gain better insight about what they do by learning/sharing from other IT experts throughout the world. Through the web site, myITforum.com users give tips, share insight, and download utilities and tools to assist them in managing their IT enterprises. Whether you oversee 10 nodes or 100,000 nodes, myITforum.com can help you manage your environment.

myITforum.com is managed by Rod Trent (myself!), a Microsoft MVP and author of the best-selling books Microsoft SMS Installer, Admin911: SMS, and IIS 5.0: A Beginner’s Guide. Rod Trent is the leading authority on Microsoft SMS and an annual presenter and keynote presenter at the annual Microsoft Management Summit (http://www.microsoft.com/management/training/mms.mspx). He has over 18 years of IT experience, 8 of which have been dedicated to SMS. In addition to his best-selling books, Rod has written thousands of articles on technology topics in many publications, on the Web, and in the form of Microsoft white papers, case studies, and technical guides. Rod is also a principal in NetImpress, Inc. (http://www.netimpress.com), a technology publishing company.

History

myITforum.com’s roots lead back to the now defunct Swynk.com web site. Swynk.com was founded and operated by Stephen Wynkoop until 1999. Stephen had developed a web site that allowed administrators all over the world to gain support for their everyday IT tasks. myITforum.com was built on the success of the Systems Management Server (SMS) section of Swynk.com. The success of the SMS section led to an urgency to keep the ever-growing community alive when it was evident that the parent company of Swynk.com was not going to support it. Swynk.com had become much more than simply content and articles, and it became evident that the web site had outgrown its electronic boundaries. It had become a live community that was represented both on the Web and in the real IT world. So, the SMS community from Swynk.com migrated to its web site location: http://www.myitforum.com.

Since the move, myITforum.com has grown by leaps and bounds, primarily due to the opportunities it presents to administrators all over the world to interact with their fellow administrators and peers. The members of the myITforum.com community are the most caring folks found in any corner of the Internet. They give their time, experience, and knowledge selflessly to help create a brain trust of smarter administrators who become efficient and proficient IT professionals.

Scope

While myITforum.com was based on Microsoft Systems Management Server, it has grown far beyond this one topic. To be an SMS administrator, an IT professional must be proficient in far more than just SMS. SMS administrators are required to support many different applications, operating systems, and technologies. Because of this requirement and myITforum.com’s ability to grow quickly with the community needs, myITforum.com expanded its topic base to include many more areas in the IT world. myITforum.com supports Altiris products, Microsoft Operations Manager (MOM), VBScript, SMS 1.2/2.0/2003, Windows, SQL Server, Networking, Active Directory, security and patch management, antivirus technologies, Windows Mobile technologies, web technologies, and deployment technologies such as Windows Installer.

MyITforum.com supports these many topics through articles, email discussion lists, and web-based forums Figure 1-18 shows the myITforum.com home page. The articles posted to the web site are quite a bit different than the articles you find in other publications. Instead of information from individuals you can’t be sure have ever worked in IT, the myITforum.com articles are from real IT workers from real IT experiences. The premise is that if you are faced with a real-world situation, someone out there has probably already been through it and has the solution all wrapped up. By sharing their experiences through articles, the myITforum.com columnists provide a central location for IT administrators all of the world to get solutions to problems they might be facing, without having to spend days or weeks working through a tough situation. If it’s a problem, someone has already faced it and succeeded, and the solution is probably outlined on myITforum.com.

Home page of myITforum.com
Figure 1-18. Home page of myITforum.com

In addition to providing these web resources for the myITforum.com community, myITforum.com has transcended the confines of the Internet. Because real IT professionals make up the myITforum.com community, myITforum.com has reached beyond the Web to aid real people in setting up real-world local communities. myITforum.com has been instrumental in setting up over 17 user groups all over the world. From the U.S. to Canada to Israel to Australia, myITforum.com has provided valuable time and resources to set up and manage some of the most successful user group communities in the real world. myITforum.com provides many things to the user groups, including a free web site for the group’s web presence, contacts with vendors for speaking services, and an intermediary link between Microsoft and the user group for planning, support, and meeting facilities.

Over time, myITforum.com has also become a successful liaison between employers and prospective employees. Offered as a free service, myITforum.com has helped place hundreds of qualified employees into IT jobs. During the last few years, when the economy has caused layoffs and outsourcing, myITforum.com has stood as a central beacon for employers and employees to connect with each other. So, in addition to providing a central repository for connecting with peers, myITforum.com has become an informal meeting place, where workers find employment and employers locate the top candidates for open positions.

It has been noted that if you attend any IT event, anywhere in the world, you will find at least one myITforum.com community member. myITforum.com’s influence reaches into almost every nook of the IT world, primarily because it provides what IT professionals need to advance to a higher level in their profession, but also because it provides a level of sharing that can’t be experienced anywhere else. myITforum.com is a real community comprised of real people with real personalities. Participating in myITforum.com is like meeting with friends. myITforum.com is an ever-evolving, ever-growing community meeting place that extends experience and knowledge that is more valuable than sitting through a weeklong training class. At the end of the day, myITforum.com is the one location for everything IT.

Rod Trent

Get Windows Server Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.