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

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

  • Comments 1
  • Likes
Bookmark and Share

In this post:

 

Has the WMI Problem with Dates and Daylight Saving Time Been Resolved?

Hey, Scripting Guy! Question

Hey, Scripting Guy! Back in the spring, I ran into a problem using the Win32_NTLogEvent WMI class in a script. The problem was the change to daylight saving time (DST) back in March in the United States. After a couple of weeks, the problem corrected itself (when the original DST time was reached), but it was a major pain. Has the situation with incorrect dates being reported via WMI been fixed? I also noticed it seemed to affect the Win32_Process WMI class as well.

-- PG

Hey, Scripting Guy! AnswerHello PG,

Scripting Guy Ed Wilson here. I am completely familiar with the problem you describe, as I received several e-mails to scripter@microsoft.com describing the issue with dates and times in the Win32_NTLogEvent WMI class. I contacted the WMI team, and they tell me the problem has been resolved. The hotfix ID is KB 970413. Make sure you get the hotfix installed on all of your servers you will be querying via script.

 

How Can I Change the Color of Error Messages in the Windows PowerShell Console?

Hey, Scripting Guy! Question

Hey Scripting Guy! The lurid red on black error messages produced by Windows PowerShell are almost unreadable. How can I control the background and text colors of the error messages? I tried using the window properties, but they do not have an effect on this situation. Thanks.

-- DM

Hey, Scripting Guy! Answer

Hello DM,

To change the color of the error messages in Windows PowerShell, you need to set a new value for $Host.PrivateData.ErrorForegroundColor. If you query the privatedata property directly, you will see the current settings for the error, warning, debug, and other messages:

PS C:\> $Host.PrivateData

 

ErrorForegroundColor    : Red

ErrorBackgroundColor    : Black

WarningForegroundColor  : Yellow

WarningBackgroundColor  : Black

DebugForegroundColor    : Yellow

DebugBackgroundColor    : Black

VerboseForegroundColor  : Yellow

VerboseBackgroundColor  : Black

ProgressForegroundColor : Yellow

ProgressBackgroundColor : DarkCyan

If you wish to change the value, you assign a new color directly to the value you wish to change. This is seen here:

PS C:\> $Host.PrivateData.ErrorForegroundColor = "cyan"

Please note that the change will only work for that particular Windows PowerShell session, so you may want to add the changes to your Windows PowerShell profile.

To determine the colors that are available, you can use the GetNames static method from the System.Enum .NET Framework class. This is seen here:

PS C:\> [enum]::GetNames("System.ConsoleColor")

Black

DarkBlue

DarkGreen

DarkCyan

DarkRed

DarkMagenta

DarkYellow

Gray

DarkGray

Blue

Green

Cyan

Red

Magenta

Yellow

White

You can also simply supply a bogus value for the systemColor. When this happens, Windows PowerShell will generate an error that contains allowed enumeration values. This technique is seen here:

PS C:\> $Host.PrivateData.ErrorForegroundColor = "fusa"

Exception setting "ErrorForegroundColor": "Cannot convert value "fusa" to type "System.ConsoleColor" due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are "Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White"."

At line:1 char:19

+ $Host.PrivateData. <<<< ErrorForegroundColor = "fusa"

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : PropertyAssignmentException

 

PS C:\>

 

How Can I Read a Text File and Update 2,000 User Accounts?

Hey, Scripting Guy! Question

Hey, Scripting Guy! We were looking at updating the account expiry date for about 2,000 users; however, we really didn’t want to do this manually. We have a csv/text file of the users and their expiry dates that needs to be set. We have been able to find the VBScript for updating a single user, but this still means manual input for each user. Any help would be greatly appreciated. Here is the script we have:

strExpireDate = "<Date>"

strUserDN = "<UserDN>"

 

set objUser = GetObject("LDAP://" & strUserDN) objUser.AccountExpirationDate = strExpireDate objUser.SetInfo WScript.Echo "Set user " & strUserDN & " to expire on " & strExpireDate

 

' These two lines would disable account expiration for the user ' objUser.Put "accountExpires",0 ' objUser.SetInfo

 

-- CG

Hey, Scripting Guy! Answer

Hello CG,

You will need to read the CSV file first. To do this, you can use the FileSystemObject, and the ReadLine method. After you have read the line, you will need to use the split function to break up your line. Store the results in the strUserDN variable. A sample script is seen in the TechNet Script Center Gallery.  

You could also use a script similar to this one on the TechNet Script Center Gallery.

 

Can I Use a WildCard Character for File Names with the FileSystemObject?

Hey, Scripting Guy! Question

Hey, Scripting Guy! Please look at the following script, noting the last line:

    'Test Station File Cleaner


'4/17/09 S Barton
strcomputer="."
on error resume next
filename1="c:\tunnel\error.log"
Set fso = CreateObject("Scripting.FileSystemObject")
set filesize=fso.GetFile(filename1)
'wscript.echo filesize.size
If filesize.size >= 1000000 then
fso.deleteFile "c:\tunnel\error.log"
end if

filename2="c:\tunnel\data.log"
set filesize=fso.GetFile(filename2)
'wscript.echo filesize.size
If filesize.size >= 1000000 then
fso.deleteFile "c:\tunnel\data.log"
end if

FSO.DeleteFile("C:\Error*") 

I have been under the impression that the "*" wildcard character will not work in VBScript. Yet in this case, it does. Attached are two samples of the error files it removes. It does not work without the "*" or with the .log extension. This script is on our test stations and is run daily by Task Scheduler. Have I had the wrong impression?

-- SB

Hey, Scripting Guy! Answer

Hello SB,

According to MSDN, the DeleteFile method will accept wildcard characters in the last portion of the file path. Therefore, the command seen here will work:

FSO.DeleteFile("C:\Error*") 

However, when you attempt to use a wildcard character for the first portion of the file name, it does not work. This is seen here:

FSO.DeleteFile("C:\Error*.log")

 

How Can I Trim Strings That Are Returned from WMI Using Windows PowerShell?

Hey, Scripting Guy! Question

Hey, Scripting Guy! I was looking at one of the Windows Powershell Tips of the Week, but I am having an issue trying to duplicate one of the tips. Perhaps you can shed some light on why I can't reproduce your results. Go easy on me; I am a total newbie with Windows Powershell. Here is the tip I am talking about:

Bonus Tip: Removing Characters From the Beginning of a String

Consider a folder containing a bunch of files similar to this (a sight familiar to digital camera users):

HIJK_111112.jpg

HIJK_111113.jpg

HIJK_111114.jpg

HIJK_111115.jpg

Suppose you want to remove the HIJK_ prefix from each of these file names. How can you do that? Well, here’s one way, using a string value instead of a file system object and file name property (although the approach is exactly the same):

$d = "HIJK_111112.jpg"

$e = $d.TrimStart("HIJK_")

Here is the code I tried, but it is not working for me:

$computer = "LocalHost"

$namespace = "root\CIMV2"

$BIOSVer = Get-WmiObject -class Win32_BIOS | Select SMBIOSBIOSVERSION

$Model = Get-WmiObject win32_computersystem | Select Model

$GX280 = "08"

$GX270 = "07"

$GX260 = "09"

$BIOS = $BIOSVer.TrimStart("@{SMBIOSBIOSVersion=A")

$Dell = $Model.TrimStart("@{Model=OptiPlex ")

IF ($bios -eq $GX280)

{

write-host "GX280"

}

elseif ($bios -eq $GX270)

{

Write-host "2"

}

elseif ($bios -eq $GX260)

{

Write-host "3"

}

The error I am getting is seen here:

Image of error seen by MH

-- MH

Hey, Scripting Guy! Answer

Hello MH,

I see you are using the Windows PowerShell Scriptomatic I wrote. Of course I will help you. You are getting caught up in a rather interesting trap. Everything in Windows PowerShell is an object. When you see the file names, such as the ones that that were listed in the Tip of the Week article, you are working with strings. This is where the Get-Member cmdlet is so important. As seen here, the file names in quotation marks are strings. The String class has the TrimStart method:

PS C:\> "h1j.jpg" | Get-Member

 

 

   TypeName: System.String

 

Name             MemberType            Definition

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

Clone            Method                System.Object Clone()

CompareTo        Method                int CompareTo(System.Object value), int CompareTo(string strB)

Contains         Method                bool Contains(string value)

CopyTo           Method                System.Void CopyTo(int sourceIndex, char[] destination, int destinationIndex,...

EndsWith         Method                bool EndsWith(string value), bool EndsWith(string value, System.StringCompari...

Equals           Method                bool Equals(System.Object obj), bool Equals(string value), bool Equals(string...

GetEnumerator    Method                System.CharEnumerator GetEnumerator()

GetHashCode      Method                int GetHashCode()

GetType          Method                type GetType()

GetTypeCode      Method                System.TypeCode GetTypeCode()

IndexOf          Method                int IndexOf(char value), int IndexOf(char value, int startIndex), int IndexOf...

IndexOfAny       Method                int IndexOfAny(char[] anyOf), int IndexOfAny(char[] anyOf, int startIndex), i...

Insert           Method                string Insert(int startIndex, string value)

IsNormalized     Method                bool IsNormalized(), bool IsNormalized(System.Text.NormalizationForm normaliz...

LastIndexOf      Method                int LastIndexOf(char value), int LastIndexOf(char value, int startIndex), int...

LastIndexOfAny   Method                int LastIndexOfAny(char[] anyOf), int LastIndexOfAny(char[] anyOf, int startI...

Normalize        Method                string Normalize(), string Normalize(System.Text.NormalizationForm normalizat...

PadLeft          Method                string PadLeft(int totalWidth), string PadLeft(int totalWidth, char paddingChar)

PadRight         Method                string PadRight(int totalWidth), string PadRight(int totalWidth, char padding...

Remove           Method                string Remove(int startIndex, int count), string Remove(int startIndex)

Replace          Method                string Replace(char oldChar, char newChar), string Replace(string oldValue, s...

Split            Method                string[] Split(Params char[] separator), string[] Split(char[] separator, int...

StartsWith       Method                bool StartsWith(string value), bool StartsWith(string value, System.StringCom...

Substring        Method                string Substring(int startIndex), string Substring(int startIndex, int length)

ToCharArray      Method                char[] ToCharArray(), char[] ToCharArray(int startIndex, int length)

ToLower          Method                string ToLower(), string ToLower(System.Globalization.CultureInfo culture)

ToLowerInvariant Method                string ToLowerInvariant()

ToString         Method                string ToString(), string ToString(System.IFormatProvider provider)

ToUpper          Method                string ToUpper(), string ToUpper(System.Globalization.CultureInfo culture)

ToUpperInvariant Method                string ToUpperInvariant()

Trim             Method                string Trim(Params char[] trimChars), string Trim()

TrimEnd          Method                string TrimEnd(Params char[] trimChars)

TrimStart        Method                string TrimStart(Params char[] trimChars)

Chars            ParameterizedProperty char Chars(int index) {get;}

Length           Property              System.Int32 Length {get;}

 

 

PS C:\>


In your code, you are storing BIOS information in a variable, and then trying to call the TrimStart method. The code is seen here:

$BIOSVer = Get-WmiObject -class Win32_BIOS | Select SMBIOSBIOSVERSION

When you use the Get-Member cmdlet, you will see that there is no TrimStart method available because you are working with a System.Management.ManagementObject.

PS C:\> $BIOSVer = Get-WmiObject -class Win32_BIOS | Select SMBIOSBIOSVERSION

PS C:\> $BIOSVer | gm

 

 

   TypeName: Selected.System.Management.ManagementObject

 

Name              MemberType   Definition

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

Equals            Method       bool Equals(System.Object obj)

GetHashCode       Method       int GetHashCode()

GetType           Method       type GetType()

ToString          Method       string ToString()

SMBIOSBIOSVERSION NoteProperty System.String SMBIOSBIOSVERSION=7LETB7WW (2.17 )

 

 

PS C:\>

However, there is a ToString method. The ToString method will turn the ManagementObject into a string. The ToString method is also available against your property as well. This is seen here:

PS C:\> $BIOSVer.SMBIOSBIOSVERSION.ToString()

7LETB7WW (2.17 )

PS C:\> $BIOSVer.SMBIOSBIOSVERSION.ToString() | gm

 

   TypeName: System.String

After you use the ToString method to convert the ManagementObject into a string, you can call the TrimStart method. However, if you do not wish to go through an extra step, you can write the code as seen here:

PS C:\> $BIOSVer.SMBIOSBIOSVERSION.ToString().TrimStart()

7LETB7WW (2.17 )

PS C:\>

This brings us to the end of another Quick-Hits Friday. It is also the end of another week on the TechNet Script Center. Thank you for all of the questions sent to scripter@microsoft.com. Join us next week as we answer additional scripting questions.

If you want to know exactly what we will be scripting next week, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you on Monday. 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
  • I just stumbled upon your blog after reading your blog posts wanted to say thanks.i highly appreciate the blogger for doing this effort.