Monday, February 10, 2014

Running an older script in PowerShell 3 or 4 generates the following error id: InvalidVariableReferenceWithDrive

Today's post deals with a problem in a few of my scripts that I encountered after upgrading to PowerShell 3 from version 2. We'll discuss both the problem and the simple regex pattern I used to identify where it may have existed in all of our other scripts. 

The problem has to do with variables used inside a string, followed immediately by a colon. Say what? Read on…

The below code is interpreted correctly in PowerShell 1 & 2 but in PowerShell 3 and 4 it is expecting a mount point or a “drive” immediately following the colon. 

Example:
log "Installing Beyond Compare $exeversion:"
log "$exeversion: Already Installed."

Error:
+         log "Installing Beyond Compare $exeversion:"
+                                        ~~~~~~~~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidVariableReferenceWithDrive

To correct this, the line needs to be updated to encapsulate the variable so it is processed first and then returned to the string.

log "Installing Beyond Compare $($exeversion):”
log "$($exeversion): Already Installed."

You probably already know whether you've coded a string using a variable this way or not but we weren't sure how prevalent it was in our organization. 

Finding the errant code:
So now that we were aware of the problem, we had to identify all of our scripts that contained the errant code conditions. In essence we had to do the following:

  1. Get all occurrences of our "*.ps1" script files with a recursive child item query.
  2. Search each script for the occurance of our regex pattern.
  3. Display the full file name, line number, and string

Here is the command line we used to do just that and its resulting output.

PS C:\windows\system32> Get-ChildItem \\server\share -include *.ps1 -recurse | select-string -pattern '\".*\$\w+\:[\s*\"]'


\\server\share\Adobe\script\CommonFunctions.ps1:2864:            } Else {Write-Output "$FontFile: Already present"}    
\\server\share\Scooter Software\3.3.5\setup.ps1:161:        log "Installing Beyond Compare $exeversion:"
\\server\share\SunGard\Fonts\CommonFunctions.ps1:2864:            } Else {Write-Output "$FontFile: Already present"}

In a repository with 100's of scripts, only 3 presented this unique condition. The output of this query contains the file location, line number, and code line that needs to be corrected. At this point it wouldn't take much effort to automate the correction of the code as well but hey, I wouldn't want to steal all the fun!

What's truly great about this method is that you can search any text readable file for anything! In a later post, I'll show you how I used this search method to tame the driver store beast in SCCM.

Breaking down the regex:
As promised, here's the breakdown of the regular expression I used.

'\".*\$\w+\:[\s*\"]'

\"          - Expression must begin with a quote
.*           - Any amount of characters
\$           - The dollar sign or beginning of the broken variable we are looking for
\w+        - A series of characters with no spaces
\:             - the colon or end of the broken variable we are looking for
[\s*\"]   - A space followed by anything and then a quote

For an excellent PowerShell regex reference, check out this link: 
PowerShell Cookbook: Regular Expression Reference

Thanks for checking out this article. I hope you find it informative. Until next time...

Thursday, February 6, 2014

Welcome to Life in Powershell

Welcome to Life in Powershell

Welcome to "Life in PowerShell" where I'll be writing about some of the scripts and techniques I use on a daily basis. I've been using PowerShell for about two years and the many blogs and contributions by the PowerShell community have been very helpful to me along the way. This blog is my attempt at giving back to the community. 

In my professional life I am the lead administrator for System Center Configuration Manager at a large insurance company. Serving in this role provides me many unique challenges and opportunities. PowerShell is the main tool I use to meet these challenges. Since most of my time is spent in ConfigMgr, many of my posts will revolve around it as well. I hope you find this blog informative. 

Well that's it for my introduction. Now to come up with the first topic...