Hey, Scripting Guy! How can I Migrate a VBScript to Windows PowerShell that parses a log file for errors?

Hey, Scripting Guy! How can I Migrate a VBScript to Windows PowerShell that parses a log file for errors?

  • Comments 2
  • Likes

 

Bookmark and Share

 

Q: Hey Scripting Guy! I need to migrate a VBScript to Windows PowerShell 2.0 that I use to parse a log file for errors that occur during a specific operation. I am only interested in the errors, not the success statements. Because this log has a tendency to grow rather large, I would like to write the failure events back to the same log file. If I could configure the application to log only errors I would, but unfortunately, that is not an option for this app. We are moving to Windows PowerShell 2.0 and consequently have been told we have to migrate all of our VBScripts to the new language. I would like to make the new Windows PowerShell script look like VBScript if I can.

-- ER

A: Hello ER, Microsoft Scripting Guy Ed Wilson here, summer is in full swing in Charlotte, North Carolina. It has been hot and hazy for weeks and everyone is watching the calendar carefully counting the weeks until fall approaches. Of course, the countdown to fall may also be parents longing for the schools to open back up so they can find some peace and quiet around the house … not sure of their exact motivation. Believe it or not, my hot tea habits do not abate during the summer months … in fact, I find that a nice cup of hot tea actually makes me feel cooler than the perennial southern favorite of ice tea. Southern ice tea is about 1 part tea, 2 parts sugar and three parts water (I believe this recipe to be correct, but I try to avoid the stuff so I am not certain of the exact composition). The Scripting Wife found a nice 70 percent cocoa bar to go with my afternoon tea—it goes real well with Earl Grey tea.

ER, it is possible to accomplish what you wish. For a basis of comparison, I found a Hey Scripting Guy! blog called How Can I Pick Out and Save Specific Lines in a Text File from October 2004. The script from that article is seen here.

CopyFailuresFromLogToLog.vbs

Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("c:\fso\HSG070110.txt", ForReading)
Do Until objTextFile.AtEndOfStream
strLine = objTextFile.ReadLine
If Left(strLine, 7) = "Failure" Then
strNewText = strNewText & strLine & vbCrLf
End If
Loop
objTextFile.Close
Set objTextFile = objFSO.OpenTextFile _
("c:\fso\HSG070110.txt", ForWriting)
objTextFile.Write(strNewText)
objTextFile.Close

This is the fourth article in a series of four articles about migrating VBScript code to Windows PowerShell. Other articles in this series appeared earlier in the week.

A direct translation of the CopyFailuresFromLogToLog.vbs script uses the filesystemobject to open the log file, and the left method to look for the word failure in the log file. It then uses the filesystemobject to open the text file for writing and writes the failure notifications to the file. The CopyFailuresFromLogToLogTransFmVBS.ps1 Windows PowerShell script is seen here.

CopyFailuresFromLogToLogTransFmVBS.ps1

add-type -AssemblyName microsoft.visualbasic
$strings = "microsoft.visualbasic.strings" -as [type]
$VbCrLf = "`r`n"
$forReading = 1
$forWriting = 2
$objFSO = New-Object -ComObject scripting.filesystemobject
$objFile = $objFSO.OpenTextFile("C:\fso\HSG070110.txt", $forReading)
Do
{
$strLine = $objFile.ReadLine()
If($strings::Left($strLine, 7) -eq "Failure")
{$strContents = $strContents + $strLine + $VbCrLf}
} Until($objFile.AtEndOfStream)
$objFile.Close()
$objFile = $objFSO.OpenTextFile("C:\fso\HSG070110.txt", $forWriting)
$objFile.Write($strContents)
$objFile.Close()

The first thing that is done is to add the microsoft.visualbasic assembly to the Windows PowerShell session. This assembly provides access to a number of .NET Framework classes, such as the strings class, that contain the functions you used in Visual Basic and in VBScript. There is no need to add the Microsoft.visualbasic assembly to gain access to the scripting.filesystemobject object because it is a COM object and as such can be directly created. There is no need to discount COM objects, or to discontinue using favorite COM objects you may have used in VBScript days. For example, if you wish to create a popup message box you can use the wshshell object as shown here.

PS C:\Users\ed.NWTRADERS> (New-Object -ComObject wscript.shell).popup("hi")
1

The contents of the HSG070110.txt log file are seen here.

Success – Operation succeeded 10/1/2004.
Success – Operation succeeded 10/2/2004.
Failure – Operation failed 10/3/2004.
Success – Operation succeeded 10/4/2004.
Failure – Operation failed 10/5/2004.
Success – Operation succeeded 10/6/2004.
Failure – Operation failed 10/7/2004.
Failure – Operation failed 10/8/2004.

A Windows PowerShell script can be written that will use the Get-Content cmdlet to open the file and pipeline the contents to the Select-String cmdlet to search for the word failure in a line. If the word failure is present, it stores the line in the $newcontent variable. The Set-Content cmdlet is then used to update the text file. The complete CopyFailuresFromLogToLog.ps1 script is seen here.

CopyFailuresFromLogToLog.ps1

$file = "C:\fso\HSG070110.txt"
$newContent = Get-Content -Path $file | Select-String -Pattern "failure"
Set-Content -Path $file -Value $newContent

It is possible to use the Select-String cmdlet to open a text file, and to display pattern matches. This is seen here.

PS C:\> Select-String -Pattern "failure" -Path C:\fso\HSG070110.txt

fso\HSG070110.txt:3:Failure ? Operation failed 10/3/2004.

fso\HSG070110.txt:5:Failure ? Operation failed 10/5/2004.

fso\HSG070110.txt:7:Failure ? Operation failed 10/7/2004.

fso\HSG070110.txt:8:Failure ? Operation failed 10/8/2004.

PS C:\>

This works well for quick searches, however, because it adds information, it does not meet the requirement of the scenario. To do this, use the Get-Content cmdlet to first retrieve the contents of the file. As seen here, this forces the Select-String cmdlet to display only the strings that match the pattern.

PS C:\> Get-Content C:\fso\HSG070110.txt | Select-String -Pattern "failure"

Failure - Operation failed 10/3/2004.

Failure - Operation failed 10/5/2004.

Failure - Operation failed 10/7/2004.

Failure - Operation failed 10/8/2004.

PS C:\>

The Set-Content cmdlet is used to write content to a text file. It differs from the Add-Content cmdlet in that it will overwrite existing content.

ER that is all there is to converting a VBScript to Windows PowerShell 2.0. This also concludes our discussion of migrating VBScripts to Windows PowerShell 2.0. Join us tomorrow for Quick Hits Friday.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

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
  • It's amazing how much more succinct the PowerShell version is. Thanks for another great article!

  • Is it possible to write text back to a specific line within the file?  I have an .ini file for an FTP site that I'd love to use this script on, but the .ini file requires that I add the text within the correct heading.  Is this possible?