Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (7/31/09)

Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (7/31/09)

  • Comments 1
  • Likes
 

  

How Can I Migrate AutoText When I Upgrade from One Version of Microsoft Office to Another?

Hey, Scripting Guy! Question

Hey, Scripting Guy! We are in the process of converting from Office 2003 to Office 2007. Many people use AutoText and I am trying to automate the process of converting or bringing over their AutoText. I created the below VBScript script, but am unable to open the file afterwards. Note: The sleep really did not change anything, but I was willing to try anything. In addition, if I do this process manually, it works just fine.


Set objWord=CreateObject("Word.Application")
Set objDoc=objWord.Documents.Open("c:\Normal11.dot")
WScript.Sleep 10000
objDoc.SaveAs("c:\AutoText.dotx")
objWord.Quit

Thank you for your time.

-- JS


 

 

Hey, Scripting Guy! Answer

Hello JS,

Your problem is you are trying to convert the file typewithout actually converting it. Just changing the file extension does not work. When you do it manually through the GUI, it calls the appropriate method on the back end. Here is the documentation for the SaveAs method. There is an additional parameter you will need to use to convert the document to the .docx file format.

To convert to another format, you need to specify the appropriate value for the SaveFormat property. The additional format options are WdSaveFormat enumeration values.

 

Which Scripting Language Should I Start with When Getting into Scripting?

Hey, Scripting Guy! Question

Hey, Scripting Guy! In my current role, I am finding that I have to compare Active Directory and Office Excel data on a regular basis. I think it is time to learn scripting to ease my workload and also to keep me from harassing other people for hastily written scripts. Some of the tasks I have to do are the following:

·         Compare columns of information in Excel

·         Compare members of an AD group

·         Find machines in AD that appear in group X, Y, and Z

I am really wondering what the best language is to start with. Speaking to various people at work, they will generally lean toward whatever language they are best at rather than what language is best to actually learn. Therefore, it would be good to get some guidance here!

-- PD

Hey, Scripting Guy! Answer

 

 

Hello PD,

 

If I were going to spend time learning a new scripting language, I would learn Windows PowerShell. The reason is that it is the up-and-coming scripting language. VBScript is in maintenance mode and has had no new development work done on it since Windows XP shipped on October 25, 2001. There have been bug fixes, and security fixes, but no new features. Windows PowerShell, on the other hand, is undergoing active developmentand Windows PowerShell 2.0 will introduce some amazing new features that will greatly simplify network administration. Windows PowerShell 2.0 is built into Windows Server 2008 R2 and Windows 7. It therefore forms the basis for many new management tools moving forward, such as Active Directory Users and Computers. Using the Active Directory cmdlets, much of the work you have been doing would be relatively simple.

Even using Windows PowerShell 1.0, the process of searching Active Directory is easier than it is with VBScript. For example, see the searching AD scripts using Windows PowerShell in the Script Center Script Repository.

For working with Excel, however, there is not a significant difference. Here is a series of Hey, Scripting Guy! articles I wrote that use Windows PowerShell. For learning Windows PowerShell, I would recommend the Microsoft Press book, Microsoft Windows PowerShell Step By Step. It was written by this really cool guy named Ed Wilson. J

If you want to learn VBScript, you may want to begin with the Scripting Guide. A good book on VBScript is the Microsoft Press book, Microsoft VBScript Step by Step.

 

A Question of Scripting Style

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have a question about scripts in the Script Repository. Why do none of the scripts end with WScript.Quit? In addition, why do you use WScript.Echo for each line, instead of WScript.Echo on the first line and carriage returns (& vbCr & _) on all the rest?

-- MB

 

Hey, Scripting Guy! AnswerHello MB,

Those are all a matter of style. The use of Wscript.echo on each line makes the code easier to read for people who are just learning VBScript. The fact that you ask the question obviously means that you are more experienced. Feel free to make the change if you wish. I never use WScript.Quit. When the script ends, it quits, so from a “double-click” standpoint, there is no advantage of using it.

 

Can I Query for USB Mass Storage History?


Hey, Scripting Guy! Question

Hey, Scripting Guy! I am not sure which one is better, but is it possible to query either the registry or Device Manager for USB mass storage history? I would like to be able query all the computers on my network for their use. I mostly just want to see the DeviceID of all mass storage devices. If possible, I would love to be able to create some type of insertion query to check a mass storage device and to compare its DeviceID to one that is allowed for use. If it does not match, I would like it to alert me somehow or disable the drive. I am not sure if all that is possible or not, but I will take the original query if the other stuff cannot be done.

-- CJ

 

 

 

Hey, Scripting Guy! Answer

Hello CJ,

There is no way to query this information via Device Manager (that I know of). This Get-UsbDeviceInfo.ps1 script retrieves USB storage information from the registry of a Windows 7 computer using Windows PowerShell.

Get-UsbDeviceInfo.ps1

Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR |
ForEach-Object {
  Get-ChildItem -Path ($_.name -replace "HKEY_LOCAL_MACHINE", "HKLM:") |
   ForEach-Object {
     Get-ItemProperty -Path ($_.name -replace "HKEY_LOCAL_MACHINE", "HKLM:")
     }
}


Where Can I Find Definitions of ADSI Classes?
 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I would like to ask if there is a place available where I can find the definitions of the different classes used by ADSI, such as wbemtest.exe in WMI. Thank you for your time.

--MA


Hey, Scripting Guy! Answer

Hello MA, 

There are two tools you can use: the Schema Admin Tool and AdsiEdit. These two tools are part of the admin tool kit. To use the Schema Admin Tool, you must first register the schmmgmt.dll by using Regsvr32. Then you add it to an MMC snap-in. This is discussed in part in a recent Hey, Scripting Guy! Article: How Do I Search Active Directory?

Our Active Directory hub has many good articles, as well as links to the ADSI documentation on MSDN and to Active Directory documentation on TechNet.

 

How Can I Detect for Updates and Install Them Without Rebooting the Computer?
 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I chatted with you at TechEd 2009 in Los Angeles about a script that will detect if the monthly Microsoft security patches have been downloaded to a PC but have not been installed. The script would detect this situation and install the patches silently without rebooting the system.

I found a script on the Web, but it does not work.  On a test system, I receive the “Updates are waiting to be installed” notification and I run this script. The script reports back that there are no patches waiting.

I guess what I am actually asking for is a means to duplicate the Windows shutdown/restart feature to “Install updates and shut down” without shutting down the system. (There are too many systems that cannot be forced to shut down in my situation.)

I would appreciate any help you can give me to help keep my users secure and let me sleep at night!

--CC


Hey, Scripting Guy! Answer

Hello CC, 

I looked at your script, and do not see anything glaringly wrong with it. However, I also do not see where it downloads and installs updates either. That means the script really does not work as advertised! I am including below the SearchDownloadInstallWindowsUpdate.vbs script that I wrote for the first edition of the Windows Vista Resource Kit. It does exactly what you are interested in doing: It searches for software updates, downloads them, and then installs them. It does not reboot the computer, however.

One big thing I should advise you about: When you download and install updates from Windows Update, you should go ahead and reboot the computer. This is because the updates need to replace files that are in memory. What happens is that the version of the file on the hard disk drive is replaced, but the copy of the file that is in useand is in memoryremains in memory. This means you have version 1 of the file in memory, and version 2 of the file on the hard disk drive. This leaves the computer in an unstable state. Additionally, if the update is a security update that fixes a vulnerability in the file, the patched version of the file is on the hard disk drive, but the vulnerable version of the file remains in memory. This means your computer is vulnerable to an outside attack using an exploit that was designed for the vulnerability you just patched. It is vital that you reboot immediately when patching security vulnerabilities in order to remain protected from attacks.

SearchDownloadInstallWindowsUpdate.vbs

'==========================================================================
'
' VBScript:  AUTHOR: ed wilson , mred,  10/8/2006
'
' NAME: <searchDOwnloadInstallWindowsUpdate.vbs>
'
' COMMENT: Key concepts are listed below:
'1. Microsoft Update object
'2. Vista resource kit
'==========================================================================
Option Explicit
Dim objSession 'update session object
Dim objSearcher 'update searcher object
Dim objResult 'search result object
Dim objUpdate 'update object
Dim objColUpdates 'updates collection object
Dim objInstaller 'installer object
Dim objDownloader'downloader object
Dim strInstall     'rtn from command line argument
Dim errRTN         'rtn code from install
Dim colNamedArguments 'WshNamed object
Dim I 'counter

subCheckCscript    'check to see if running in cscript
Set colNamedArguments = WScript.Arguments.Named
strInstall = colNamedArguments("i")
subCheckArguments

WScript.Echo "Searching for updates..."
Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateupdateSearcher()
Set objResult = objSearcher.Search("IsInstalled=0 and Type='Software'")

WScript.Echo "List of applicable items on the machine:"

For I = 0 To objResult.Updates.Count-1
    Set objUpdate = objResult.Updates.Item(I)
    WScript.Echo I + 1 & "> " & objUpdate.Title
Next

If objResult.Updates.Count = 0 Then
          WScript.Echo "There are no applicable updates."
          WScript.Quit
End If

WScript.Echo vbCRLF & "Creating collection of updates to download:"

Set objColUpdates = CreateObject("Microsoft.Update.UpdateColl")

For I = 0 to objResult.Updates.Count-1
    Set objUpdate = objResult.Updates.Item(I)
    WScript.Echo I + 1 & "> adding: " & objUpdate.Title
    objColUpdates.Add(objUpdate)
Next

WScript.Echo vbCRLF & "Downloading updates..."

Set objDownloader = objSession.CreateUpdateDownloader()
objDownloader.Updates = objColUpdates
objDownloader.Download()

WScript.Echo  vbCRLF & "List of downloaded updates:"

For I = 0 To objResult.Updates.Count-1
    Set objUpdate = objResult.Updates.Item(I)
    If objUpdate.IsDownloaded Then
       WScript.Echo I + 1 & "> " & objUpdate.Title
    End If
Next

Set objColUpdates = CreateObject("Microsoft.Update.UpdateColl")

WScript.Echo  vbCRLF & "Creating collection of downloaded updates to install:"

For I = 0 To objResult.Updates.Count-1
    set objUpdate = objResult.Updates.Item(I)
    If objUpdate.IsDownloaded = true Then
       WScript.Echo I + 1 & "> adding:  " & objUpdate.Title
       objColUpdates.Add(objUpdate)  
    End If
Next

If UCASE(strInstall) = "Y" Then
          WScript.Echo "Installing updates..."
          Set objInstaller = objSession.CreateUpdateInstaller()
          objInstaller.Updates = objColUpdates
          Set errRTN = objInstaller.Install()
         
          'Output results of install
          WScript.Echo "Installation Result: " & funError(errRTN.ResultCode)
          WScript.Echo "Reboot Required: " & errRTN.RebootRequired & vbCRLF
          WScript.Echo "Summary of updates installed and results:"
         
          For I = 0 to objColUpdates.Count - 1
                   WScript.Echo I + 1 & "> " & _
                   objColUpdates.Item(i).Title & ": " & funError(errRTN.GetUpdateResult(i).ResultCode)
          Next
Else
          WScript.Echo "You have elected to NOT install the updates at this time" & VbCrLf & _
                   "They have, however, been downloaded to the local cache."
End If            

Sub subCheckCscript
If UCase(Right(Wscript.FullName, 11)) = "WSCRIPT.EXE" Then
    Wscript.Echo "This script must be run under CScript"
    WScript.Quit
End If
end Sub

Sub subCheckArguments
WScript.Echo "checking arguments"
If colNamedArguments.Count < 3 Then
          If colNamedArguments.Exists("?") Then
                   WScript.Echo "Try this: cscript " & WScript.ScriptName _
                   & VbCrLf & "Arguments are: [/i:install <y>] " _
                   & VbCrLf & "Example: cscript " & WScript.ScriptName & " /i:y"
          WScript.Quit
          End If
          If Not colNamedArguments.exists("i") Then
                   WScript.Echo "Updates will NOT be installed. They will be enumerated" & VbCrLf &_
                             "To automatically install try this: " & VbCrLf & "cscript " & _
                             wscript.ScriptName & " /i:y"
          End If
          If colNamedArguments.exists("i") Then
                   WScript.Echo "Updates will be installed automatically" & VbCrLf &_
                             "If this is not your wish, then press ^c to end the script"
          End If
End If
End Sub

Function funError(strIN)
Select Case strIN
          Case 0
                   funError = "Not Started"
          Case 1
                   funError = "In Progress"
          Case 2
                   funError = "Succeeded"
          Case 3
                   funError = "Succeeded with Errors"
          Case 4
                   funError = "Failed"
          Case 5
                   funError = "Aborted"
          Case Else
                   funError "Error " & strIN & " is unknown"
End Select
End Function

When you run SearchDownloadInstallWindowsUpdate.vbs, run it under Cscript. Interestingly enough, you can run Cscript inside a Windows PowerShell prompt:

Image of running Cscript inside a Windows PowerShell prompt


Well, this brings our week to an end. Join us next week for more scripting fun and excitement. If you want to see what we will be up to, follow us on Twitter or on Facebook. If you get stuck trying to make your script work, you can also seek advice from your fellow scripters on the Official Scripting Guys Forum. Of course, you are always welcome to send us e-mail at scripter@microsoft.com. Until next week, keep cool and enjoy the weekend.

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • I have a variation of the script above that I adapted to shutdown services prior to updating the server. The script works on the majority of my servers. HOWEVER, for a select few, the script runs and does it's service shutdown thing, but when it gets to ....

             Set objInstaller = objSession.CreateUpdateInstaller()

             objInstaller.Updates = objColUpdates

             Set errRTN = objInstaller.Install()

    It doesn't install the updates, and the "reboot trigger" remains "false" and doesn't reboot the server.

    Autoupdates is set to "Download but don't install unless I say so..."

    checked the Event logs and no updates are installed.

    I've checked the registry settings under HKEY_Local_Machine\Software\Policies\Microsoft\Windows\WindowsUpdates and it's sub AU  and all settings are identical to a server that DOES work.

    Is there a log somewhere I can look to see why this "thinks" it's updating the server but doesn't?