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


 

 

Troubleshooting a Windows Powershell Script

Hey, Scripting Guy! QuestionHey Scripting Guy! I tried to use the script from the May 2009 TechNet Magazine article, Hey, Scripting Guy! Working with Access Databases in Windows PowerShell. But when I run it I get an error. This happens both on my Windows Vista  computer (64 bit, Service Pack 2) with Office 2007 SP2, and my Windows 2007 build 7100 (64 bit) with Office 2007 SP2 installed. The database I am using has been created by hand. Here is the error I am receiving.

Exception calling "Open" with "1" argument(s): "Provider cannot be found. It may not be properly installed."

At C:UsersfvandonkAppDataLocalTempUntitled1.ps1:31 char:19

+   $connection.Open <<<< ("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=$Db" )


I get a similar error when I create the database using the script from the Hey Scripting Guy! Article, How Can I Create a Database with More Than One Table? The error from that script is:

Unexpected token 'Provider=' in expression or statement

Can you tell me what I am doing wrong?

-- FD

 

Hey, Scripting Guy! AnswerHello FD,

The problem is that when I wrote those two scripts, I was using a 32-bit operating system. I have now upgraded to Windows 7 64-bit, and I get the same error messages you are getting. To run the scripts without generating an error, you need to make sure you are using the 32-bit version of Windows PowerShell. On a 64-bit system, you will find both a 32-bit version and a 64-bit version of Windows PowerShell installed. You should see the link for 32-bit Windows PowerShell off the Start menu on Windows 7. Click Accessories and then click Windows PowerShell:

Image of Windows PowerShell location in Windows 7


I used Windows PowerShell ISE (x86) and it works fine. I would consider putting something like this at the beginning of the script:

if($env:PROCESSOR_ARCHITECTURE -ne 'x86')

  { 'This script must be run in x86 powershell' ; exit}

 


Outputting Only the Last Three Lines of a Command

Hey, Scripting Guy! QuestionHey Scripting Guy! I have a request which I believe should be very simple, but all the searching of the Internet has not turned up anything quite right. How can I output only the last three lines of a command into a text document?

For example, I am using the command dir /s to find the total size and number of files and folders in a given directory. These directories can be quite large, so a complete output may cause the text file to exceed 1 GB in size. All I really need is the last three lines that read:

     Total Files Listed:
           299174 File(s)  1,238,631,539 bytes
           27731 Dir(s)  1,667,751,895,040 bytes free

-- KS

Hey, Scripting Guy! AnswerHello KS,

I wrote the GetDirectoryListingStats.vbs script to illustrate what you will need to do. In the GetDirectoryListingStats.vbs script, you first create an instance of the WshShell object as seen here:

Set objShell = CreateObject("WScript.Shell")


You then call the exec method to execute the dir command. To be able to execute the dir command, you also need to call the command interpreter. This is seen here:

Set objExecObject = objShell.Exec(command)


The exec method returns a textstream object. To walk through the textstream object, use the Do Until…Loop as seen here:

Do Until objExecObject.StdOut.AtEndOfStream

    strText = objExecObject.StdOut.ReadAll

Loop


Next, you use the split function to break the output into an array that will allow you to return the last few lines. This is shown here:

aryText = Split(strText, VbNewLine)


The complete GetDirectoryListingStats.vbs script is seen here.

GetDirectoryListingStats.vbs

'==========================================================================

'

' NAME: GetDirectoryListingStats.vbs

'

' AUTHOR: Ed Wilson , Microsoft

' DATE  : 6/18/2009

'

' COMMENT: Uses the exec method from the WshShell object to execute a command

' Uses stdOut to read the output.

'

'==========================================================================

 

'Option Explicit  'is used to force the scripter to declare variables

'On Error Resume Next  ‘ go to the next line if it encounters an Error

Dim objShell  'holds WshShell object   

Dim objExecObject  'holds what comes back from executing the command

Dim strText  'holds the text stream from the exec command.

Dim command  'the command to run

Dim Directory  'directory to query

Directory = "C:fso"

command = "cmd /c dir " & Directory

WScript.echo "starting program " & Now ' used to mark when program begins

Set objShell = CreateObject("WScript.Shell")

Set objExecObject = objShell.Exec(command)

 

Do Until objExecObject.StdOut.AtEndOfStream

    strText = objExecObject.StdOut.ReadAll

Loop

aryText = Split(strText, VbNewLine)

wscript.Echo "There are " & ubound(aryText) & _

 " items in the " & Directory & " Folder"

WScript.Echo aryText(ubound(aryText) -2 )

WScript.Echo aryText(ubound(aryText) -1)

 

The Measure-Object Cmdlet in Windows PowerShell CTP3

Hey, Scripting Guy! QuestionHey Scripting Guy! The –line switch used with Measure-Object in Windows PowerShell CTP3 seems to only count nonempty lines in .txt files. Is that the supposed behavior?

-- TB

Hey, Scripting Guy! AnswerHello TB,

Let’s take a look. First use the Get-Content cmdlet to read the contents of a text file. This is seen here:

PS C:Usersedwils> Get-Content 'C:fsoNew Text Document.txt'

line one

 

line two

 

line three

We see there are five lines in the text file, but only three have text. Now use the Get-Content cmdlet and pipeline the results to the Measure-Object cmdlet, and tell it to  count the number of lines. This is seen here:

PS C:Usersedwils> Get-Content 'C:fsoNew Text Document.txt' | Measure-Object -Line

 

                        Lines Words                         Characters                    Property

                        ----- -----                         ----------                    --------

                            3


As you can see, Measure-Object tells us we have three lines. Lets now try one more thing: Use Get-Content and store the contents into a text file. Now use the count property on the file. This is seen here:

PS C:Usersedwils> $file = Get-Content 'C:fsoNew Text Document.txt'

PS C:Usersedwils> $file.Count

5


TB you are correct. The Measure-Object cmdlet only counts lines; it does not count blank lines. If you need to get blank lines in a text file, you can use the count property.



Troubleshooting Output from a VBScript Script

Hey, Scripting Guy! QuestionHey Scripting Guy! I am having an issue with outputting results. My code is reading server names from a .txt file and outputting the logged-on terminal server users and the server name they are logged onto. My code looks like this:

GetTerminalServerUsersAndServers.vbs

Const ForReading = 1

Const wbemImpersonationLevelImpersonate = 3

Const wbemAuthenticationLevelPktPrivacy = 6

 

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile("servers.txt", ForReading)

 

Do Until objTextFile.AtEndOfStream

    strComputer = objTextFile.Readline

    Set objLocator = CreateObject("WbemScripting.SWbemLocator")

    Set objWMI = objLocator.ConnectServer (strComputer, "rootcimv2")

    objWMI.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate

    objWMI.Security_.AuthenticationLevel = wbemAuthenticationLevelPktPrivacy

    Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & strComputer & "rootcimv2")

    Set colSessions = objWMI.ExecQuery _

        ("Select * from Win32_LogonSession Where LogonType = 10")

          If colSessions.Count = 0 Then

             Wscript.Echo "No interactive user found"

          Else

           For Each objSession in colSessions                 

            Set colList = objWMI.ExecQuery("Associators of " _

              & "{Win32_LogonSession.LogonId=" & objSession.LogonId & "} " _

              & "Where AssocClass=Win32_LoggedOnUser Role=Dependent" )                                                                      

            For Each objItem in colList

             Wscript.Echo "Server Name: " & strComputer

Comments (0)

Skip to main content