Hey, Scripting Guy! Awww—Windows PowerShell Plays Nice-Nice with VBScript and Batch!

Hey, Scripting Guy! Awww—Windows PowerShell Plays Nice-Nice with VBScript and Batch!

  • Comments 5
  • Likes

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I would like to be able to integrate VBScript scripts into my Windows PowerShell code. I also have some batch files I wish I could use with Windows PowerShell. I do not want to have to rewrite code that works perfectly fine. Is this possible?

-- SK

 

Hey, Scripting Guy! Answer

Hello SK,

Microsoft Scripting Guy Ed Wilson here. I have many VBScript scripts that I continue to use on a regular basis. I agree with you: In general, I consider rewriting scripts from one language to another language a waste of time, unless there is a compelling reason to do so. There are several reasons for this. Translating a VBScript script into Windows PowerShell is often more work than writing a new script that leverages Windows PowerShell native commands. If you have a script that works, there is little benefit (other than to learn Windows PowerShell) to performing a rewrite unless you add new features to the script. There are so many new things that I can do with Windows PowerShell that I could not do with VBScript, I have not run out of ideas for new scripts yet. Therefore, I do not have time to go back and translate old scripts.

One of my new friends that I met on Twitter is Sean Kearney. Sean was recently made a Microsoft MVP for Windows PowerShell, and he is a moderator for the Official Scripting Guys Forum. He also hung out with Craig and others at Tech·Ed 2010 North America in New Orleans. Let's just say that if you harnessed the natural energy in Sean’s body, you could power much of the massive New Orleans Convention Center.

So I asked Sean for ideas about integrating VBScript and Windows PowerShell. As usual he attacked the problem with exuberance. The following is Sean’s reply as part of Guest Blogger Week here on the Hey, Scripting Guy! Blog.

Photo of inimitable Sean Kearney

A little about Sean: Sean Kearney is a network administrator, a Microsoft Certified Technology Specialist in Windows Server Virtualization and Configuration, a Windows PowerShell MVP, and a Microsoft Certified Systems Engineer. Sean is a devoted and passionate computer enthusiast from the early 80s to the present day, having used just about every microcomputer ever. Sean taught himself computer programming with 65xxmachine code, working with many technologies―but primarily Microsoft. Sean deals with “anything thrown at him,” from gnawed keyboards to recovery of Exchange servers to networking setups and isolating the realm of the unknown. Currently, he tests and deploys just about any new Microsoft Technology; he also deals with users in an enterprise class environment. Sean loves Windows PowerShell, Windows 7, and Hyper-V, in that order.

Hi, I’m Sean. I’m a network administrator and a Tech. I’ll bet I’ve got a job a lot like yours. We deal every day with users and requests. Pull off the impossible now! We solve problems before they happen. And manage the systems.

More importantly, I’m a scripter. I automate my work. Consistency is king in my world. If there is a way to automate something (that is, when I’m not running about like a gerbil in a wheel), I’ll do it.

Most of all, I arm myself with Windows PowerShell. I use Windows PowerShell because it works with all my systems and technologies. It allows me to leverage what I have that is legacy with what I need to use that’s being released today.

As I write this after having come back from a huge conference I was able to sit and realize something. There seems to be a misconception among many IT pros and developers about Windows PowerShell: If you want to use Windows PowerShell, you have to drop what you already know in order to learn this new thing.

However, that couldn’t be further from the truth. Windows PowerShell is about enabling your environment and administrators. Windows PowerShell is an interactive management shell with scripting abilities. It will still allow you to run your VBScript scripts and will happily pass and receive parameters to them. It will pass and receive data to older applications from cmd.exe.

It’s not about disruption—it’s all about construction. It’s another tool for you to use and leverage in whatever way that suits you.

There are some things that work far better in Windows PowerShell. Querying and manipulating Active Directory and file systems? Windows PowerShell takes to that work naturally. Anything .NET related? That can be extended right to Windows PowerShell because it leverages the .NET Framework for most of its functions.

But there are applications on the market that still run and create automatic scripts in VBScript. Why not? It still works fine. And there are too many functions that run directly from the command prompt (NETSH, FTP, and LDIFDE among many others) in which administrators are fluent.

Windows PowerShell won me over because of some of the things it could perform on a file system easily (like manipulation of files by date/time). More importantly, it would still interact with both legacy technologies without any loss of functionality.

*Blink* *Blink* *Sputter* *Blink*

That’s right. Before you choke on that carbonated beverage in disbelief, Windows PowerShell will easily interact with legacy technologies.

For example, to call up a VBScript normally, I would typically execute:

CSCRIPT.EXE coolscript.vbs

There’s a familiar task and a familiar statement. Guess what? In Windows PowerShell, to run a VBScript I would execute:

CSCRIPT.EXE coolscript.vbs

No change!

So if you have a VBScript script that needs a parameter called up—say something that uses a name from a user—in the command shell you would have typed:

CSCRIPT UserScript.VBS USERNAME

If you’re working directly in the Windows PowerShell console, that doesn’t change. But if you’re incorporating that into a Windows PowerShell script, you need to make one change. Use a Windows PowerShell variable to the pass the information:

---------------------- SampleScript.PS1 -------------------------

$FIRST=’Dertie’
$LAST=’ Eyewitt’
$DISPLAY=$FIRSTNAME+’ ‘+$LASTNAME
$USERNAME=$FIRSTNAME.Substring(0,1)+$LASTNAME
$DOMAIN=”@HEADOFFICE.CONTOSO.COM”
$UPN=$FIRST+$LAST+$DOMAIN

NEW-ADUSER $USERNAME -Givenname $FIRST –Lastname $LAST –UserPrincipalName $UPN –DisplayName $DISPLAY

CSCRIPT.EXE NewUserScript.VBS $USERNAME

---------------------- SampleScript.PS1 -------------------------

Other than a minor change in syntax, it will work. There is an important rule though. Windows PowerShell passes objects not straight text or numeric information. But as long as the object in question contains data in a format VBScript is expecting, it should run properly.

Of course, test it before running in production. But you knew that already.

Conversely, you can have VBScript call up Windows PowerShell. Windows PowerShell is just another executable application in Windows. It can accept parameters and data just like any other application. Curious what you can send to it?

Just execute:

WINDOWS POWERSHELL.EXE /?

This will reveal all of the parameters and basic details on them:

Windows PowerShell[.exe] [-PSConsoleFile <file> | -Version <version>]

[-NoLogo] [-NoExit] [-Sta] [-NoProfile] [-NonInteractive]

[-InputFormat {Text | XML}] [-OutputFormat {Text | XML}]

[-WindowStyle <style>] [-EncodedCommand <Base64EncodedCommand>]

[-File <filePath> <args>] [-ExecutionPolicy <ExecutionPolicy>]

[-Command { - | <script-block> [-args <arg-array>]

| <string> [<CommandParameters>] } ]

In actual fact you’ll get a lot more than this, but this is just a quick glance at the parameters it will take.

For basic purposes, if you want to launch a Windows PowerShell cmdlet from VBScript, here’s how you could do it:

------------------ SampleScript1.vbs ----------------

Set WshShell= Wscript.CreateObject(“Wscript.Shell”)

WshShell.Run “C:\windows\system32\Windows PowerShell\v1.0\Windows PowerShell.exe –command Windows PowerShellStatement1; Windows PowerShellStatement2; Windows PowerShellStatement3”

------------------ SampleScript1.vbs ----------------

Or from within VBScript, you can launch a Windows PowerShell script:

------------------ SampleScript2.vbs ----------------

Set WshShell= Wscript.CreateObject(“Wscript.Shell”)

WshShell.Run “C:\windows\system32\Windows PowerShell\v1.0\Windows PowerShell.exe –file { Windows PowerShellScript.PS1 }”

------------------ SampleScript2.vbs ----------------

Not only can you launch Windows PowerShell cmdlets and scripts from VBScript, but also you can pass parameters to them. It works almost exactly as if in CMD from VBScript you were launching a batch file:

------------------ SampleScript3.vbs ----------------

Set WshShell= Wscript.CreateObject(“Wscript.Shell”)

PoshScriptName=”C:\Scripts\AliceinWonderland.PS1”

PoshParameter=”MadHatter”

Posh= “C:\windows\system32\Windows PowerShell\v1.0\Windows PowerShell.exe”

PoshLaunch=Posh & “ –file {“ & PoshScriptName & “ “ PoshParameter & “ }”

WshShell.Run PoshLaunch

------------------ SampleScript3.vbs ----------------

And just as you would pass parameters to your VBScript, you can insert them into the Windows PowerShell command or script (as long as the information matches what it’s expecting). Feel a little better? I thought it was the coolest thing when I found out Microsoft left the technologies able to interact with each other. This is not an “undocumented feature.” This is by design. Awesome.

Now all of you who are comfortable with using cmd.exe, you’re not left out. Windows PowerShell will interact with all of the classics (and not-so-classics) as well.

For example, you’re trying to do something with Robocopy, which wants information like this:

ROBOCOPY.EXE C:\FOLDERA D:\FOLDERB

Well again, in Windows PowerShell this is identical:

ROBOCOPY.EXE C:\FOLDERA D:\FOLDERB

But say you need it in a script? No problem. This follows the same rules as with VBScript. Just pass a Windows PowerShell variable to it. The Windows PowerShell console will do all the work to make that command application feel at home.

-------------- SampleScriptB.PS1 -------------

$FOLDERA=’C:\FOLDERA’
$FOLDERB=’D:\FOLDERB’

NEW-ITEM $FOLDERB –type Directory -Force

ROBOCOPY $FOLDERA $FOLDERB

-------------- SampleScriptB.PS1 -------------

It's nice to have that as an option. But of course every command-line guru knows they can launch parameters from cmd.exe as well. Pretend (just pretend) you need something from an application that only works in cmd.exe. The ability to launch cmd.exe still exists in Windows PowerShell. Running old legacy applications has not gone away.

Although this is not a very impressive use of Windows PowerShell with command, it does show you can pass parameters to DOS commands and applications from Windows PowerShell.exe:

-------------- SampleScriptC.PS1 -------------

$MESSAGEFORECHO=’Hello World, I’m using Windows PowerShell’

CMD.EXE /K “ECHO $MESSAGEFORECHO”

-------------- SampleScriptC.PS1 -------------

So wonderful, we’ve discovered everything works with everything else.

Why change? It’s the things Windows PowerShell offers you that VBScript can’t do easily. Hmm, I should be careful here. VBScript can do a lot. So can the command-line controls. That’s why we use them: They meet our needs.

But they will eventually be phased out. The newer servers such as Exchange 2010 and Windows Server 2008 R2 live in the land of Windows PowerShell. You’ll find there won’t be much support for VBScript.

Managing systems and data from a single line in Windows PowerShell session in part is something it does natively and easily. Controlling systems remotely is just a huge part of its nature.

Although VBScript can do WMI, and WMIC enables us in the command world, you should at least give Windows PowerShell a serious glance. All I need to do in Windows PowerShell to change the service tag on a Dell BIOS:

GET-WMIOBJECT Win32_bios | Select-Object SerialNumber

Or just type:

GET-WMIOBJECT –list | EXPORT-CSV C:\WMILIST.CSV

This lets you search and navigate a CSV file of all my WMI objects.

If I need to work with Active Directory and find a list of all users created in the last 30 days, I can type this in a Windows PowerShell prompt in Windows Server 2008 R2.

$DATE=(GET-DATE).AddDays(-30)

GET-ADUSER –filter ‘whenCreated -gt $DATE’

These are live and interactive commands I can execute in Windows PowerShell. The key word I have just said is “interactive.”The command is interactive, but it lacks the programmability of the higher end VBScript script. VBScript can do some beautiful and elegant things, but it’s not Interactive like command.

This is where Windows PowerShell seizes the day: It has the direct interaction of command with the power of VBScript, yet it has a set of capabilities unique to itself including one-liners, aliases, remoting, and user-customizable modules. More importantly, you can use the newer technology while still leveraging components and scripts you have already written.

Windows PowerShell is another tool for you to leverage in whatever way you need to use it. It is supported and driven not only by Microsoft, but also by us the community. The people that need the tools are those that shape and change Windows PowerShell.

So you can easily integrate that company script you wrote in VBScript with the new Exchange Server 2007 with a batch file that performs a series of tasks.

Windows PowerShell, VBScript and CMD are not three isolated technologies that won’t share. They are not three lone warriors. They are a team.

Here to seize the LAN and save your day.

Sean
The Energized Tech
www.PowerShell.ca

 

SK, that is all there is to integrating VBScript, Windows PowerShell, and batch. Guest Blogger Week will continue tomorrow.

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

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • When I run the code below I get "Expected End of Statement" when setting the PoshLaunch variable. I changed the quotes to be valid quotes in vbs and updated the paths and parameter, but it will not run. Any help?

    Set WshShell= Wscript.CreateObject(“Wscript.Shell”)

    PoshScriptName=”C:\Scripts\AliceinWonderland.PS1”

    PoshParameter=”MadHatter”

    Posh= “C:\windows\system32\Windows PowerShell\v1.0\Windows PowerShell.exe”

    PoshLaunch=Posh & “ –file {“ & PoshScriptName & “ “ PoshParameter & “ }”

    WshShell.Run PoshLaunch

  • Took a quick look (BTW, I love the sample names!)

    You shouldn't need the Parenthese at all (That's a script block and when you call the .PS1 with the file parameter they are not needed and probably cause confusion)

    If I had your AliceInWonderLand.Ps1 file I'd do a full test but try pulling those Paratheses out... :

  • So... what about returning data from a called script? As in, I have called a .vbs from within my .ps1, and when it completes and returns to the powershell script I'd like it to return values. I've seen some suggestions on this but all the examples I've seen (other than for your standard error codes) seem a bit convoluted.

  • @joey - for a good answer in this almost ancient blog post you question here: social.technet.microsoft.com/.../home\

  • @joey

    Here is the link again:

    social.technet.microsoft.com/.../home

    This forum/blog software is notorious for trashing posts.