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

ScriptingGuy1

How Can I Tell if I’m Running a Script on the 32-Bit or the 64-Bit Version of Windows Vista?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need to be able to tell if the version of Windows Vista I am running a script on is 32 bit or 64 bit. I have tried looking at system variables, but it seems a bit complicated. I would rather just have something programmatically I can use. Any thoughts?

– CM

SpacerHey, Scripting Guy! Answer

Hi CM,

I always have thoughts. I am thinking right now about Freddie Mercury’s fantastic voice (since I am listening to “The Show Must Go On” on my Zune). I am also thinking about how much I love the little tea pot the Scripting Wife gave me for Christmas (because it is time for my afternoon tea). Oh, you probably wanted me to think about your script problem.

You can obtain this information from WMI very easily. Query the WIN32_OperatingSystem class. The property you want to use is OSArchitecture. To obtain this via Windows PowerShell, you can use this technique:

(Get-WmiObject win32_OperatingSystem).OSArchitecture

To obtain the information via VBScript, you can use this rather cool technique on Windows Vista. This is because in Vista, the WIN32_OperatingSystem class has been transformed into a singleton, which means there is only one instance of it. When that is the case, we can use the properties directly without the need to go through a For…Each…Next type of loop. This gives us a “one liner” just like the ones that the Windows PowerShell people are so proud of. (It is so quick—my cup of tea did not even get cold.)

Wscript.echo GetObject("winmgmts:win32_OperatingSystem=@").OSArchitecture

 

How Can I Create an Ubershortcut?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I often work with large groups of files across several applications, all associated with the same project. Can I create a script to act as a kind of ubershortcut that will open all the files I need at one go, rather than me having to click them all one by one? And if so, how can it be done? As you probably have guessed, I know nothing about scripting.

– HM

SpacerHey, Scripting Guy! Answer

Hi HM,

You can use something like the OpenArrayOfFiles.vbs script that I just wrote. This script opens a series of files that are placed in the array. It relies on the fact that file programs are registered with the extension. To add different files, include the path in quotation marks, separated by a comma. The OpenArrayOfFiles.vbs script is seen here:

AryFiles = Array("C:\Fso\Test.Doc", "C:\Fso\Test.Xlsx", "C:\Fso\Test.Txt")
Set wshShell = CreateObject("WScript.Shell")
For Each file In AryFiles
  wshShell.Run File
Next

To run the script, copy it to Notepad and save the file with a .vbs file extension. You will need to make sure you change the save file dialog to reflect all files; otherwise, you will end up with a text file and not a VBScript file. This is seen here:

Image of renaming the file with a .vbs file extension

 

You can double-click the file after that. You will, of course, want to change the files that need to be opened. Make sure that you include each file name in quotation marks, and that you have a comma between each file name. VBScript is rather picky about these kinds of things.

By the way, you will find some good beginning script information here. You may also want to check out the Microsoft VBScript Step by Step book.

 

How Can I Use Task Scheduler?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I copied a script from this “Hey, Scripting Guy!” article to create scheduled jobs. However, when I open the Task Scheduler in Control Panel, I am unable to change the credentials used by the script or any of the other items. Everything is grayed out. What gives?

– NJ

SpacerHey, Scripting Guy! Answer

Hi NJ,

You are absolutely correct. The WIN32_ScheduledJob WMI class creates jobs that are visible to the AT command. The AT command (I think AT stands for “arcane technology”) is the same task scheduler that Fred Flintstone used to use to do his backups back at the rock quarry.

The modern Task Scheduler uses a different interface. In previous versions of Windows, you could actually edit an AT command job with the Task Scheduler. It would BREAK the scheduled job, but hey, at least you could edit it. Beginning with Windows XP (I believe), this changed and the options are unavailable (or grayed out, as you say). This keeps you from changing and breaking the job. All jobs created with WIN32_ScheduledJob are run with system privileges. This is not configurable. If you need to interact with the modern Task Scheduler, you can use the schtasks.exe utility on Windows XP and later, or you can use the new Task Scheduler API (Schedule.Service) on Windows Vista and later. We have two good articles about using this API. The links are here.

Scheduled Tasks 1

Scheduled Tasks 2

 

How Can I Update Many Shortcuts at Once?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! In the case of this “Hey, Scripting Guy!” article, there is only one shortcut and the name of that shortcut is known. In my case, there are several shortcuts that target a specific server, each having its own distinct name (for example, Shortcut to Folder1.lnk, Shortcut to Folder2.lnk). Because these are targeted at a specific server that is no longer available and I have a duplicate dataset on an alternative server, I need to replace the \\server1 portion of the target with \\server2 and then replicate that in all instances of shortcuts pointing to server1. In effect, I’d be doing a find-and-replace job like in Office Word. Can this be scripted or will I have to bite the bullet and do each manually? Bear in mind that a replacement server1 will eventually be put in place and I’ll have to change them all back.

– DK

SpacerHey, Scripting Guy! Answer

Hi DK,

Manually making a bunch of changes to shortcuts sounds like it would be a bit of useless work. Kind of like when I was in boot camp and had to dig a hole one day, only to be required to fill the hole back up the second day. By the way, did you know that dirt evaporates? It is actually the moisture in the dirt that evaporates. But when I had to put the dirt back, there was not enough to fill the hole back up completely. So I had to do pushups for not completing the task. Needless to say, with a painful memory like that, I have a strong aversion to useless work. So here is a script I wrote to help you avoid having to do pushups for each shortcut that does not work (I will shut up lest I give the pointy-headed boss [PHB] any ideas.)

The ListModifyDeskTopShortCuts.vbs script obtains a collection of all the shortcuts on your desktop. It then iterates through the collection of shortcuts and builds the name of the shortcut. The ParseName method unfortunately cannot take the full path; it can take only the name of the link. But the value of the name property does not include .lnk. To solve this problem, I used a little concatenation and add the “.lnk” to the value we obtained from the name property. I then simply print out a couple of property values from the shellLinkObject object. I have commented out the code you would use to actually modify the shortcut. The ListModifyDeskTopShortCuts.vbs script is seen here:

Const DESKTOP = &H10&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(DESKTOP)
Set colItems = objFolder.Items
For Each item In colItems
 If InStr(item.name,"Shortcut") Then
   Set objFolderItem = objFolder.ParseName(item.name & ".lnk")
   Set objShellLink = objFolderItem.GetLink
   WScript.Echo item.Name
   wscript.Echo vbTab & objShellLink.WorkingDirectory
   wscript.Echo vbTab & objShellLink.Path
   'objShellLink.Path = "\\atl-fs-01\accounting\payable.exe"
   'objShellLink.Save()
 End If
Next

How Can I Sort the Output of the Get-ChildItem Cmdlet?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have a little question about sorting and formatting. For example, Get-Childitem in Windows PowerShell displays the length in bytes. I want to change this output into megabytes or gigabytes. I’m looking forward to receiving your answer. Thank you in advance!

– TN

SpacerHey, Scripting Guy! Answer

Hi TN,

(I asked Brandon, a Microsoft MVP, to assist me in answering your question. Here is his answer [thanks Brandon!]). For this you need to use what they call calculated properties (more information here and here). You will also want to use the -f (or format) operator defined (more information here).

Here is example of using the Get-ChildItem cmdlet and formatting the output:

# Gets all files, sorts them by size, and selects the top 20 by size. Outputs Name and Size
$SizeInMB = @{n="SizeInMB";e={"{0:n2}" -f ($_.length/1mb)}}
get-childitem –path c:\data -recurse |
Where-Object {!$_.PSIsContainer}  |
Sort-Object –descending -property Length |
Select-Object -Property Name, $SizeInMB -first 20

Here is an excerpt from the about_operator help topic from Windows PowerShell:

Format Operator
    -f      The format operator provides support for formatting strings
            via the .NET string object format method.  On the left hand
            side of the operator is the format string and on the right
            hand of the operator is the collection of objects to be
            formatted.
            The following example shows some of the capabilities of the
            format operator.
            PS> "{0} {1,-10} {2:N}" -f 1,"hello",[math]::pi
            1 hello      3.14

The about_operator Help topic can be displayed by typing the following command into Windows PowerShell:

Get-Help about_Operator

That’s it for another Quick-Hits Friday. This also brings to a close another exciting scripting week. Have fun this weekend, and we will see you back rested, refreshed, and raring to go on Monday. Until then, take care.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys