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

ScriptingGuy1


How Can I List Files and Folders with Special Characters in Their Names?

Hey, Scripting Guy! Question

 Hey, Scripting Guy! First I would like to thank you for all the good humour you present me every time I need you. I’m trying to use one of your scripts to list the files and folders on my file server. My users are very creative and can manage to use all kind of characters in folder and file names. This script crashes on folder names including the ‘ (straight quote) character. An example of a folder that crashes the execution of this script is c:scriptsUser’s folder

Could you please point me to a solution for this problem?

– GV


Hey, Scripting Guy! Answer

Hi GV,

The single quote is a reserved string character for WMI. Unfortunately, it is allowed by Windows as a legitimate character for file and path names. The single quote character will need to be escaped with a single backslash character (). This Hey, Scripting Guy! article talks about this problem.

What’s the Difference Between ADODB.Recordset and ADOR.Recordset?

Hey, Scripting Guy! Question

 Hey, Scripting Guy! I was wondering if you could answer a question for me. Is there any difference between the objects ADODB.Recordset and ADOR.Recordset? Both program IDs appear to map to the same object. Am I missing something here? If they are different, is there an advantage one has over the other?

– RD

SpacerHey, Scripting Guy! Answer

 Hi RD,

According to MSDN ADOR.Recordset is outdated. You should use ADODB.Recordset in your scripts.

What Other Options Are Available for objUser and objGroup?

Hey, Scripting Guy! Question

 Hey, Scripting Guy! One thing that I would like to know is how I can find out other things I can do with your scripts. For example, many scripts have a similar format to this snippet here. How can I find out what other options are available for, say, objUser or objGroup:

  For Each objUser In objGroup.Members
        If  objUser.Name = UserAccount Then
          bMemberFound = True
     end if
   Next

– IA

SpacerHey, Scripting Guy! Answer

 Hi IA,

That is the perennial question. When I (Ed) write the Hey, Scripting Guy! articles (since August of last year), I always try to mention the name of the objects that I am working with. It is the object names that will help you out because you can look them up on MSDN. You can use this scoped Bing search that I use on a daily basis to look up object names and their associated members on MSDN.

Inside VBScript, there is a function that will be helpful for you. It is called the typename function and you can use it at anytime in your code to see what type of object you have. You then look up the value that is displayed from typename using the scoped Bing search. This technique is discussed in the Microsoft Press book, Microsoft VBScript Step by Step.

Here is an example of using the typename function.

DemoTypeName.vbs

Dim a
Dim b
Dim c
Dim d
Dim e
Dim f
Dim g
Dim h ‘date

b = “this is a string”
c = 55
d = Null
e = Array(1,2,3,4,5)
Set f = CreateObject(“wscript.shell”)
Set g = CreateObject(“scripting.filesystemObject”)
h = (#1/2/1957#) ‘uses date literal
i = CDate(1/2/1957)
j = DateValue(“1/2/1957”)

WScript.Echo TypeName (a)
WScript.Echo TypeName (b)
WScript.Echo TypeName(c)
WScript.Echo TypeName(d)
WScript.Echo TypeName (e)
WScript.Echo IsArray(e)
WScript.Echo TypeName (f)
WScript.Echo TypeName (g)
WScript.Echo TypeName (h)
WScript.Echo TypeName (i)
WScript.Echo TypeName (j)

Troubleshooting a Remoting Script

Hey, Scripting Guy! Question

Hey, Scripting Guy! Windows PowerShell really does rock! I’m using it automate just about everything I can! I have a problem that I can’t find an answer tocan you help? I am using WMI to collect various details from workstations, some of which are connected via VPN. I am attempting to export the results to a CSV file, but I have to run the command twice for it to work. Can you explain how to avoid this?

After the CSV is created, the contents are correct. For machines on the LAN, it works first time. 

– SM

SpacerHey, Scripting Guy! Answer

Hi SM,

What you describe sounds more like it is a WMI issue and network connectivity issue and not Windows PowerShell. WMI uses DCOM to connect to remote machines. DCOM was never intended to be used over the Internet; therefore, it does not have the error checking and handling required to work across unreliable networking typologies. WINRM is the solution to these kinds of connectivity issues. You can script WINRM using Windows PowerShell, but it is a bit tricky. It is fully documented in the SDK however.

In Windows PowerShell 2.0 we have better support for this, and even use WINRM for remoting of Windows PowerShell itself. In the meantime, one thing you might try to do is to send a ping to the remote machine to “wake up” the connection. You can stay with WMI and use the Win32_PingStatus class. After you get a good reply, you can proceed with your data gathering.

Here is a script that illustrates using the Win32_PingStatus class to ping a remote computer.

PingAndDoWmi.ps1

# —————————————————————————–
# # Ed Wilson, MSFT, 6/23/2009
# illustrates using the Win32_PingStatus WMI class to ping a remote range of
# addresses, and then when obtaining a reply, perform WMI query
#
# —————————————————————————–
[int]$intPing = 5
[string]$intNetwork = “192.168.1.”

for ($i=1;$i -le $intPing; $i++)
{
$strQuery = “select * from win32_pingstatus where address = ‘” + $intNetwork + $i + “‘”
   $wmi = get-wmiobject -query $strQuery
   “Pinging $intNetwork$i … “
   if ($wmi.statuscode -eq 0)
      { gwmi -class win32_bios -computername $intNetwork$i }
      else
         {“error: ” + $wmi.statuscode + ” occurred”}
} # end for

How Can I Replace a Special Character in a Text File?

Hey, Scripting Guy! Question

Hey, Scripting Guy! In your article, How Can I Find and Replace Text in a Text File, you have a routine that works really great. However, it does not work when I try to replace the quotation mark in my text file. I need to replace ” chr(34) with tab chr(9).  Can you help?

– LS

SpacerHey, Scripting Guy! Answer

Hi LS,

You need to use the VBScript method of specifying ASCII characters. Here is an example of doing this.

ReplaceQuoteWithTab.vbs

‘==========================================================================

‘ NAME: ReplaceQuoteWithTab.vbs

‘ AUTHOR: Ed Wilson , Microsoft
‘ DATE  : 6/19/2009

‘ COMMENT: This script opens a text file, and uses the replace
‘ function to replace a ” chr(34) with a <tab> chr(9)
‘ Modification to: http://tinyurl.com/ywtprz
‘==========================================================================

Const ForReading = 1
Const ForWriting = 2
Dim FilePath
FilePath = “C:fsotest.txt”
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objFile = objFSO.OpenTextFile(FilePath, ForReading)

strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText,Chr(34) ,Chr(9) )

Set objFile = objFSO.OpenTextFile(FilePath, ForWriting)
objFile.WriteLine strNewText
objFile.Close

Troubleshooting a Windows PowerShell Script with the PagedPoolBytes Object

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need to gather data on a particular object property in Windows PowerShell. The object, PagedPoolBytes, does not include the server property as far as I can tell. Here is what I need the results to look like:

Server           PoolPaged Bytes

ServerName1      Value
ServerName2      Value
ServerName3      Value

My script is seen here. 

$strComputers = get-content C:TEMPServers.txt

$PoolPagedBytes = {[math]::truncate($_.poolpagedbytes / 1000000)}

Foreach ($computer in $strComputers)
{
get-wmiobject Win32_PerfFormattedData_PerfOS_Memory -computername $strComputers |  Select-Object -Property $PoolPagedBytes | export-csv c:SCRIPTSDATAPPB-x.csv
}

Any help would be appreciated. Thank you. 

– MS

SpacerHey, Scripting Guy! Answer

Hi MS,

All WMI classes have a system property named _Server that is always available. Here is an example of obtaining the server name, and the performance information you seek:

get-wmiobject Win32_PerfFormattedData_PerfOS_Memory  | select p*, __Server

When you run the code above, here is the output you will receive:

PageFaultsPersec           : 586
PageReadsPersec            : 0
PagesInputPersec           : 0
PagesOutputPersec          : 0
PagesPersec                : 0
PageWritesPersec           : 0
PercentCommittedBytesInUse : 28
PoolNonpagedAllocs         : 301815
PoolNonpagedBytes          : 117280768
PoolPagedAllocs            : 221638
PoolPagedBytes             : 233611264
PoolPagedResidentBytes     : 223879168
Path                       : \MrEdComputerrootcimv2:Win32_PerfFormattedData_PerfOS_Memory=@
Properties                 : {AvailableBytes, AvailableKBytes, AvailableMBytes, CacheBytes…}
__SERVER                   : MrEdComputer

Troubleshooting a VBScript Script That Gives Error 80041001

Hey, Scripting Guy! Question

Hey, Scripting Guy! I am pretty new to using VBScript and seem to have hit a wall. I put together the script below to output a file containing all the software installed on a machine. Every time I run the script, I get an 80041001 error, which points to the line with the “Next” statement.  I have been scouring the Web for information about this particular issue, but cannot seem to find anything that might be related to the issue I am facing. I am on a Windows XP computer with Service Pack 3. This is part of a bigger project that I am working on that will query network machines for various properties such as CPU, OS, RAM, RAID, NIC, etc. I have managed to get all the other parts working except for this one. Any assistance would be greatly appreciated.

Here is the script that is giving me problems.

QueryProductsWriteToFile.vbs

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
 
Set objTextFile = objFSO.CreateTextFile(“C:software.txt”, True)
 
StrComputer = “.”
 
Set objWMIService = GetObject(“winmgmts:” & “{impersonationLevel=impersonate}!\” & strComputer & “rootcimv2”)
 
Set colSoftware = objWMIService.ExecQuery (“Select * from Win32_Product”)
               
For Each objSoftware in colSoftware
                                strDesc = objSoftware.Description
                                strIdent = objSoftware.IdentifyingNumber
                                strInstDate = objSoftware.InstallDate2
                                strName = objSoftware.Name
                                strVend = objSoftware.Vendor
                                strVer = objSoftware.Version
                                objTextFile.WriteLine strDesc & vbtab & strIdent & vbtab & strInstDate & vbtab & strName & vbtab & strVend & vbtab & strVer
Next  
 
objTextFile.Close
 
WScript.Quit()

– DM

SpacerHey, Scripting Guy! Answer

Hi DM,

The error you are receiving, 80041001, is WbemFailed. This means that the error is coming from WMI. I ran the QueryProductsWriteToFile.vbs script on my Windows 7 computer, and it runs just fine. By the way, that is a nice script, especially because you say you are new to VBScript. I believe you probably need to rebuild the WMI repository on your computer, because it has more than likely become corrupted.

 

This brings us to the end of another Quick-Hits Friday! It also brings to a close the first week after the 2009 Summer Scripting Games. The cheers, flags, pomp, and circumstance are still fresh in our minds as is the virtual popcorn. We sincerely hope you have a great weekend, and join us next week. If you want to know what we will be doing next week follow us on Twitter. Have you seen Script Center 101? Dude, the critics love it. Two thumbs up! Until Monday, peace!