Summary: Learn how to troubleshoot a WMI VBScript and how to handle Outlook .pst file locking issues in Windows PowerShell.

 

In this post:

·         Troubleshoot a WMI VBScript

·         How to Handle Outlook File Locking

 

Troubleshoot a WMI VBScript

Hey, Scripting Guy! QuestionHey, Scripting Guy! I am busy learning VBScript and WMI for my next job. I copied/pasted the following example (below) which comes from http://technet.microsoft.com/en-us/library/ee692852.aspx (Listing 3) then I wrote a small Q&D hack to better understand WMI error management, SwebemLastError and such. At test time, you cannot make that block of code work without errors. This is the portion that I seem to be getting stuck on.

Set objPrinter = objWMIService.Get _

       ("Win32_Printer.Name='"&  strPrinter&  "'")

 

I even asked in the Scripting Guys forum, but I did not get any answers back.

Finally, I went back a few minutes ago to the place where I copied that code from, which is the above reference, and did a cut/paste of your Listing 3 example.

Bingo! I got the same error WBEM_E_INVALID_OBJECT_PATH (with my local computer and a real printer.) instead of your nice "Typical output" example.

I am running the code on Windows 7. Any clue on this problem, please? The script I am working with is seen here.

On Error Resume Next

strComputer = "."

strPrinter = "RealPrinter"

Set objWMIService = GetObject("winmgmts:\\"&  strComputer&  "\root\cimv2") If Err = 0 Then

     WScript.Echo "No error binding to "&  strComputer

     Set objPrinter = objWMIService.Get _

       ("Win32_Printer.Name='"&  strPrinter&  "'")

     If Err = 0 Then

         WScript.Echo "No error connecting to "&  strPrinter

     Else

         DisplayErrorInfo

     End If

Else

     DisplayErrorInfo

End If

 

'******************************************************************************

 

Sub DisplayErrorInfo

 

     WScript.Echo "Error:      : "&  Err

     WScript.Echo "Error (hex) :&H"&  Hex(Err)

     WScript.Echo "Source      : "&  Err.Source

     WScript.Echo "Description : "&  Err.Description

     Err.Clear

 

End Sub

 

-- DT

 

Hey, Scripting Guy! AnswerHello, DT. It is always interesting when you work with code that shows error handling, in that one never knows whether the error being generated is "intentional" or if it is accidental. Anyway, let me tell you what is going on, and you can make up your own mind.

In the first place, obviously when run as-is, the code will generate an error because there is no fictional computer, and even the testprinter does not exist, at least not on my network. Therefore when you run the script, errors are in fact generated. The cool thing, is that the errors are handled in a nice way by the subroutine.

Now, when I change the script to point to my local computer (by using the period for the computer name), and when I change to a real printer on my network, I receive the nice error that says that I was able to connect to the local computer, but I still have a problem with the path. This output is shown here.

No error binding to .

Error:      : -2147217350

Error (hex) : &H8004103A

Source      : SWbemServicesEx

Description : Invalid object path

 

This is even though I have corrected the "issue" with the printer name. The key to the output, is the description and the source fields. SwbemServicesEx is the object that we are using to query WMI. We are using the GET method from that object. It is stored in the objWMIService variable. When you use the GET method, you have to connect to the key property from the WMI class. In this case, the code is wrong. It has us connecting to the name property, as seen here.

Set objPrinter = objWMIService.Get _

      ("Win32_Printer.name='" & strPrinter & "'")

 

I use WbemTest to determine the key property from a WMI class. For Win32_Printer (as for many of the hardware WMI classes) the key property is DeviceID, not name.

The corrected code is shown here. One other thing, in the original code, there is this line of code that hardcodes the value of the strPrinter variable. I commented it out. However, you can feel free to delete it, because it is not needed.

strPrinter = "TestPrinter"

 

Here is the revised script:

On Error Resume Next

strComputer = "."

strPrinter = "HP LaserJet P2050 Series PCL6"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") If Err = 0 Then

    WScript.Echo "No error binding to " & strComputer

   ' strPrinter = "TestPrinter"

    Set objPrinter = objWMIService.Get _

      ("Win32_Printer.DeviceID='" & strPrinter & "'")

    If Err = 0 Then

        WScript.Echo "No error connecting to " & strPrinter

    Else

        DisplayErrorInfo

    End If

Else

    DisplayErrorInfo

End If

 

'******************************************************************************

 

Sub DisplayErrorInfo

 

    WScript.Echo "Error:      : " & Err

    WScript.Echo "Error (hex) : &H" & Hex(Err)

    WScript.Echo "Source      : " & Err.Source

    WScript.Echo "Description : " & Err.Description

    Err.Clear

 

End Sub

Now when I run the script, the output seen here appears:

Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation. All rights reserved.

 

No error binding to .

No error connecting to HP LaserJet P2050 Series PCL6 Exit code: 0 , 0000h

 

How to Handle Outlook File Locking

Hey, Scripting Guy! QuestionHey, Scripting Guy!  At work, I'm having problems with my current project, the Outlook-pst-Archive-pst-backup&cleanup-files-to-the-server-so-I-can-back-them-up-there.ps1 . This script is to fix a hole in or current backup configuration: The local Outlook.pst files. And you were right when you stated that scripts are never done, they keep getting more refined. My questions is about Outlook.pst file locking.

I cannot find any reliable information on the net. In one post, a guy from Microsoft recommended looking toward handles. Another says Test-Path works ok, but he gives no example. Another says there is no .IsFileLocked method in .NET (but I found a fragment of info regarding VB and .NET 1.1 at MSDN). Another few Windows PowerShell examples from SQL Guys don't seem to work for me. They report back TRUE when it should be FALSE. I know from AutoCAD, file locks can be linked to temporary files, so maybe when a temp file gets deleted, a trigger could pick that up in WMI?

And the delay could give a pseudo WAIT in a Windows PowerShell script? Maybe WAIT is the answer? I would hate to just put a "Wait 10 seconds".

I can't even find information about how to tell if a file is locked, except that it throws an exception. Maybe EXCEPTION is it to handle the exception? I am better with try-throw-catch in vb.NET, and have not quite gotten the same pitch in Windows PowerShell yet.

Can you please shed some light in this area?

-- RO

Hey, Scripting Guy! AnswerHello, RO. If it were me, I would simply look at the outlook.exe process. If it is not running, then it will be impossible for the outlook.pst file to be locked. You are correct, in that find file locks is a pain. Seems there was a command line utility a long time ago that would report file locks and what application had what file locked, but that was a LONG time ago. The problem has actually been solved for real backup programs by using shadow copy. They hook into the file shadow copy infrastructure, and use a freeze, thaw algorithm to suspend the file, take a snapshot of the file, release the file, and then apply the transforms. That is something not exposed in a scriptable way.

Rather than using an arbitrary wait time, I would use an event driven script, and look for processes that go away. Here are a couple of Hey Scripting Guy! articles that talk about that. Once the outlook process has gone away, then I would copy the outlook.pst file. This can be configured as a shutdown script via Group Policy.

 

Well, this concludes another edition of Quick Hits Friday. Join me tomorrow for the Weekend Scripter for The Scripting Guys Really Do Rock (part one on Saturday, and part two on Sunday).

I would love you to follow me on Twitter or Facebook. If you have any questions, send email to me at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy