Bookmark and Share

 

(Note: These solutions were written for Beginner Event 4 of the 2010 Scripting Games.)

 

Beginner Event 4 (Windows PowerShell)


Photo of Gary Siepser

 

Gary Siepser is a senior premier field engineer (PFE) for Microsoft. He is a Microsoft Certified Master for Exchange Server 2007. As a PFE, he spends most of his time in front of Microsoft’s Premier customers delivering Windows PowerShell and Exchange workshops, Exchange Risk Assessments (ExRAP), various custom Exchange and Windows PowerShell knowledge transfers, and the occasional critical situation onsite assistance. He maintains a blog for Exchange and Windows PowerShell topics at http://blogs.technet.com/gary.

----------

For this event, we are challenged with determining the number of processors in a system and if there are enough of them to proceed with installing an application. Luckily, the screen shot and clue about environment variables that our boss provided gives us a clue about where we can get that information. That is the key to writing Windows PowerShell code that retrieves informationwhere do we get it from? Windows Management Instrumentation (WMI) is normally a great source for information about a computer, but in this case, the boss asked us not to use WMI.


Windows PowerShell makes accessing Windows environment variables very easy because there is a Windows PowerShell provider that is included in every Windows PowerShell installation (versions 1.0 and 2.0) that allows very simple file system-like access to them. To find out more about Windows PowerShell providers, check out the Windows PowerShell built-in help topic by typing the command
Get-Help about_Providers.


For this problem, we solve it by using the Windows PowerShell provider. I used the Windows PowerShell ISE, a graphical script editor/debugger included with Windows PowerShell 2.0, to compose this script. I decided that, because the solution to this problem is not very lengthy code, I would include very detailed comments in the code. Comments in Windows PowerShell are text that is after a pound character (#).  This text is ignored by Windows PowerShell when the code is run; therefore, it is a good technique to put notes in Windows PowerShell code that won’t affect the actual running of the script. Many script writers will use comments as notes to themselves so that when they need to read the code later, they have notes to help them understand or remember the details of the code.


In this solution will be two variations. Both use the Windows PowerShell provider, but they are two different flavors of accessing this environment variable.


The environment variable we are going to use is called NUMBER_OF_PROCESSORS. This variable contains the number of processors present on a computer. As shown in the screen shot that our boss provided (see next image), this variable is easily viewable in the GUI of the various versions of Windows. The procedure to view environment variables has changed through the versions of Windows, but it can generally be found in the system properties window.


As I mentioned above, I am providing two variations of the solution, which you will see in the code. The following image is a screen shot of the results of running this sample code.
 

Image of results of running code


You will find the code fully documented. To show the sheer simplicity of the code, I am including a version of it here with all comments removed:

"`n Solution Variation 1 `n"

"Number of Processors:"
$env:NUMBER_OF_PROCESSORS

If ($env:NUMBER_OF_PROCESSORS -gt 1)
{
   
"We have enough processors to proceed"
}
Else
{
    
"We do not have enough processors to proceed"
}


"`n Solution Variation 2 `n"

cd env:

"Number of Processors:"
dir NUMBER_OF_PROCESSORS

(
dir NUMBER_OF_PROCESSORS).Value


If ((dir NUMBER_OF_PROCESSORS).Value -gt 1)
{
   
"We have enough processors to proceed"
}
Else
{
   
"We do not have enough processors to proceed"
}

 

Here is the fully commented script.

Beginner Event 4.PS1

"`n Solution Variation 1 `n"

#Using the native Windows PowerShell Environment Provider
#Using the shortcut to access items by treating them like a Windows PowerShell
#variable with a $ followed by the full path to the item
#
#This line will simply echo out the environment variable
#which shows the number of processors as visible in the Windows GUI.
#Before seeing the value, we'll echo out or print a message to the
#host by simply placing a string or text inside quotes. In the
#top line above, we are simply echoing out the text "Solution
#Variation 1" with a new line at the beginning and end of the text.
"Number of Processors:"
$env:NUMBER_OF_PROCESSORS

#The following line uses a simple IF statment with an else to have
#Windows PowerShell tell us if there is more than one processor. The proper
#use of an IF statement can be found by looking at the help topic,
#"about_if", which is viewed by typing "Get-Help about_if" at the
#Windows PowerShell prompt. In this IF statement, we'll simply compare the
#value of this variable using the "Greater Than" comparison operator,
#which in Windows PowerShell is written as "-gt". Help about the comparison
#operators can be found by looking at the help topic,
#"about_comparison_operators", which is accessed by typing,
# "Get-Help about_Comparison_Operators”.
If ($env:NUMBER_OF_PROCESSORS -gt 1)
{
    "We have enough processors to proceed"
}
Else
{
    "We do not have enough processors to proceed"
}


"`n Solution Variation 2 `n"

#Again let’s use the provider, except this time we won’t use such a
#shortcut to access it. Instead, we'll use commands that a beginner
#will likely be very familiar with.

#As in CMD, let’s change the current working directory to the envinroment
#provider drive using cd, which in Windows PowerShell is an alias for a
#cmdlet called "Set-Location"
cd env:

#We can use a simple dir command to retrieve the name and value
#of this environment variable. We'll use dir, which in Windows PowerShell
#is an alias for the cmdlet "Get-ChildItem"
"Number of Processors:"
dir NUMBER_OF_PROCESSORS

#Now, how do we get to just the value portion of the results that
#were just returned? This is where things get a little more complicated
#for a beginner. The easiest way is to simply treat these results as an
#object. The object has the properties "Name" and "Value”. We can
#use a pretty common object-oriented language dotted notation to access
#the properties of an object. We need to place the command in a set
#of parentheses though in order to have Windows PowerShell run the command first
# and then let us treat the result as an object.
(dir NUMBER_OF_PROCESSORS).Value

#Once again, let’s use a simple IF statement to have Windows PowerShell let
#us know if we have enough processors. We'll use the same comnparison
#as syntax as we did in variation 1 above.
If ((dir NUMBER_OF_PROCESSORS).Value -gt 1)
{
    "We have enough processors to proceed"
}
Else
{
    "We do not have enough processors to proceed"
}

 

Beginner Event 4 (VBScript) 


Photo of Sean Kearney


Sean Kearney is a network administrator, MVP, Microsoft Certified Technology Specialist in Windows Server Virtualization and Configuration, and a Microsoft Certified Systems Engineer. He is a devoted and passionate computer enthusiast from the early 80s to the present day, having used just about every microcomputer ever. He is self-taught in computer programming with 65xx machine code, working with many technologiesbut primarily Microsoft. He deals with “anything thrown at him” from gnawed keyboards to recovery of Exchange servers to networking setups and isolating the realm of the unknown. His present position has him testing and deploying just about any new Microsoft technology he is asked to as well as dealing with users in an enterprise class environment. Prior to this, he spent more than eight years dealing with small business systems and home user environments. He absolutely loves Windows PowerShell, Windows 7 and Hyper-V and in that specific order.


The Story so Far
Intensive Deployment


Our company had been planning deployment of a new software application. Everything was ready to go. The development team had run the program through rigorous tests. All was signed off. The MSI file was packaged and ready to go.


Then the great curse of every IT department reared its ugly head: feature creep. Development had determined that the new feature would work, but because of last minute issues, workstations would need a strong CPU to handle itat least a hyper-threading chip or dual processor.


Normally in most environments, you could have VBScript pull out the information via WMI, but for security reasons, WMI was considered a risk by somebody higher up. Your head hangs low, doomed and vanquished of your normal solutions.


However, a ray of light appears. Your boss shows you a screenshot noting it appears there is a variable that could give the same information. The environment variable!


You double click on NUMBER_OF_PR with your mouse, and sure enough it reads, NUMBER_OF_PROCESSORS.


You compare against other machines with lesser and greater CPUs, and confirm it will yield a 2 for any CPU that has hyper-threading capability or better


Excellent!


In VBScript, you can script a link to the Explorer shell using the Wscript.Shell object in VBScript. This allows you to perform various functions in Windows Explorer using VBScript, such as launching an application or in this case, reading an environment variable.


Therefore, we first create a connection to that object in VBScript:


Set WindowsScriptShell=WScript.CreateObject("Wscript.Shell")


We next need to set the context to point the system to manipulate system-level objects as opposed to users:


Set Shell=WindowsScriptShell.Environment("System")


At this point we can directly access a variable in the Explorer shell by passing its name to the shell:


CPUCount=Shell(“NUMBER_OF_PROCESSORS”)


Now that we have the Information, we can echo it back to the screen using the Echo command in VBScript:


WScript.Echo "This computer has “ & CPUCount & “ Processors.”


There! You’ve done it! The day is saved. But then it dawns on you. Wouldn’t it be nice pass that information back to the installing software?


Use of the Wscript.Quit command and the CPU count will work for that. From the command prompt world, when CScript calls up your script, it will return a value in the %ERRORLEVEL% variable:


Wscript.Quit CPUCount


All tied together, you now will have a script that looks like this.


CPUCheck.vbs

‘ Initiate connection to shell object

Set WindowsScriptShell=WScript.CreateObject("Wscript.Shell")

 

‘ Change context of shell to “System” vs “User”

Set Shell=WindowsScriptShell.Environment("System")

 

‘ Read an environment variable

CPUCount=Shell("NUMBER_OF_PROCESSORS")

 

‘ Echo this information and a polite message on the screen

WScript.Echo "This computer has “ & CPUCount & “ Processors.”

 

‘ Return CPUCount back to the “real world” for installer script

Wcript.Quit CPUCount

 

If you run this script from the installer CMD or BAT, you could now do this to keep everything seamless. This is seen here:

CSCRIPT.EXE CPUCheck.vbs

IF NOT ERRORLEVEL 2 goto TooSlow

REM Insert line to launch your installer file

GOTO Done

:TooSlow

REM Whatever you want to do or not do if chip is too slow place here

:Done


There you have it. The day is saved thanks to you and your amazing scripting abilities! Take a bow, oh Mighty Scripter!

 

 

Beginner Event 4 (VBScriptanother approach)

Note from Scripting Guy Ed Wilson: What would such a huge project as the 2010 Scripting Games be without a snafu? I wound up sending Beginner Event 4 (VBScript) to two expert commentators and did not send out Beginner Event 3 (VBScript). Ugh. Oh, well, I guess all is not lost because I was able to write the scenario for Event 3. Without further ado here is a second expert commentator’s solution for Beginner Event 4 (VBScript).

Photo of Andrew Barnes 

Andrew Barnes
MCTS, MCITP.
http://uk.linkedin.com/in/andrewdbarnes


I am currently a senior IT systems administrator at the British Cycling Federation. I am also a Microsoft Certified IT Professional and a moderator on The Official Scripting Guys Forum where I share my experience and expertise. I have more than 20 years’ experience in the UK IT industry. Holding SC clearance in the past, I have worked for the Ministry of Defense, British Aerospace, and the Criminal Records Bureau.


My skills are broad I can do almost the entire spectrum of technical things from soldering components on circuit boards to scripting, operating system deployment, and configuration of server applications. My biggest sense of satisfaction comes from helping others to find solutions. I prefer to show people how to help themselves, rather than give them an answer. I also enjoy reducing workloads through automation.


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


In this event I’ve decided to be succinct so let’s go straight to the script. It’s just a standard environment variable lookup script. Double-click it, and it gives you this output:

Image of output of script


Here’s how I did it. But first, let me give you a quick history lesson.


Environment variables are among the oldest modern day technologies (Yea! An oxymoron! I know!), and they go way back to the earliest versions of DOS. I’m glad I used them so much on my DOS boot disks back in the day because now, 25 years later, they’re still used by system administrators such as yours truly.


From a command prompt, type SET to see all the environment variables running on your system. Just like old school. Fantastic!


Image of all environment variables on system


This output here gives you a whopping 30 lines of system information! Okay, so it’s not exactly Windows Management Instrumentation or the registry, but I like to think of it as the granddaddy of both these systems. These days, there are four types of environment variables: user, system, volatile, and process. We are only going to work with system today.


This is how the script works. In the first two lines of code, we create a collection object to access the “System” environment variable, and we store it in the variable, objEnv. Here’s that part of the script:

Set objShell = CreateObject("Wscript.Shell")

Set objEnv = objShell.Environment("System")


In the next three lines, we call on the collection and nest it in an If…Then condition. The script will quit if there are fewer than two processors in the system:

If objEnv("NUMBER_OF_PROCESSORS") < "2" Then

      WScript.Quit     

End If


The popup box will be displayed only if the process gets past the condition of the If routine (the underscore is used to split long lines of code):

objShell.Popup  "System has " & objEnv("NUMBER_OF_PROCESSORS")_

 & " Processors",, "Environment Variables", vbInformation + vbOKOnly

WScript.Quit


This line can be replaced with a command to run an executable.


Here is the full script:

 

Set objShell = CreateObject("Wscript.Shell")

Set objEnv = objShell.Environment("System")

 

If objEnv("NUMBER_OF_PROCESSORS") < "2" Then

      WScript.Quit     

End If

 

      objShell.Popup  "System has " & objEnv("NUMBER_OF_PROCESSORS")_

 & " Processors",, "Environment Variables", vbInformation + vbOKOnly

WScript.Quit 

 


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 your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
 

Ed Wilson and Craig Liebendorfer, Scripting Guys