Archive

Posts Tagged ‘New’

PowerShell 2.0 vs. 3.0 Syntax Differences And More

October 22nd, 2013 1 comment

I’m fortunate enough to work for a great company that tries to stay ahead of the curve and use newer technologies.  This means that when I’m writing my PowerShell (PS) scripts I typically don’t have to worry about only using PS v2.0 compatible syntax and cmdlets, as all of our PCs have v3.0 (soon to have v4.0).  This is great, until I release these scripts (or snippets from the scripts) for the general public to use; I have to keep in mind that many other people are still stuck running older versions of Windows, or not allowed to upgrade PowerShell.  So to help myself release PS v2.0 compatible scripts to the general public, I’m going to use this as a living document of the differences between PowerShell 2.0 and 3.0 that I encounter (so it will continue to grow over time; read as, bookmark it).  Of course there are other sites that have some of this info, but I’m going to try and compile a list of the ones that are relevant to me, in a nice simple format.

Before we get to the differences, here are some things you may want to know relating to PowerShell versions.

How to check which version of PowerShell you are running

All PS versions:

$PSVersionTable.PSVersion

 

How to run/test your script against an older version of PowerShell (source)

All PS versions:  use PowerShell.exe –Version [version] to start a new PowerShell session, where [version] is the PowerShell version that you want the session to use, then run your script in this new session.  Shorthand is PowerShell –v [version]

PowerShell.exe -Version 2.0

Note: You can’t run PowerShell ISE in an older version of PowerShell; only the Windows PowerShell console.

 

PowerShell v2 and v3 Differences:

 

Where-Object no longer requires braces (source)

PS v2.0:

Get-Service | Where { $_.Status -eq ‘running’ }

PS v3.0:

Get-Service | Where Status -eq ‘running

PS V2.0 Error Message:

Where : Cannot bind parameter ‘FilterScript’. Cannot convert the “[PropertyName]” value of the type “[Type]” to type “System.Management.Automation.ScriptBlock”.

 

Using local variables in remote sessions (source)

PS v2.0:

$class = "win32_bios"
Invoke-Command -cn dc3 {param($class) gwmi -class $class} -ArgumentList $class

PS v3.0:

$class = "win32_bios"
Invoke-Command -cn dc3 {gwmi -class $Using:class}

 

Variable validation attributes (source)

PS v2.0: Validation only available on cmdlet/function/script parameters.

PS v3.0: Validation available on cmdlet/function/script parameters, and on variables.

[ValidateRange(1,5)][int]$someLocalVariable = 1

 

Stream redirection (source)

The Windows PowerShell redirection operators use the following characters to represent each output type:
        *   All output
        1   Success output
        2   Errors
        3   Warning messages
        4   Verbose output
        5   Debug messages

NOTE: The All (*), Warning (3), Verbose (4) and Debug (5) redirection operators were introduced
       in Windows PowerShell 3.0. They do not work in earlier versions of Windows PowerShell.

 

PS v2.0: Could only redirect Success and Error output.

# Sends errors (2) and success output (1) to the success output stream.
Get-Process none, Powershell 2>&1

PS v3.0: Can also redirect Warning, Verbose, Debug, and All output.

# Function to generate each kind of output.
function Test-Output { Get-Process PowerShell, none; Write-Warning "Test!"; Write-Verbose "Test Verbose"; Write-Debug "Test Debug"}

# Write every output stream to a text file.
Test-Output *> Test-Output.txt

 

Explicitly set parameter set variable values when not defined (source)

PS v2.0 will throw an error if you try and access a parameter set parameter that has not been defined.  The solution is to give it a default value when it is not defined. Specify the Private scope in case a variable with the same name exists in the global scope or an inherited scope:

# Default the ParameterSet variables that may not have been set depending on which parameter set is being used. This is required for PowerShell v2.0 compatibility.
if (!(Test-Path Variable:Private:SomeStringParameter)) { $SomeStringParameter = $null }
if (!(Test-Path Variable:Private:SomeIntegerParameter)) { $SomeIntegerParameter = 0 }
if (!(Test-Path Variable:Private:SomeSwitchParameter)) { $SomeSwitchParameter = $false }

PS v2.0 Error Message:

The variable ‘$[VariableName]’ cannot be retrieved because it has not been set.

 

Parameter attributes require the equals sign

PS v2.0:

[parameter(Position=1,Mandatory=$true)] [string] $SomeParameter

PS v3.0:

[parameter(Position=1,Mandatory)] [string] $SomeParameter

PS v2.0 Error Message:

The “=” operator is missing after a named argument.

 

Cannot use String.IsNullOrWhitespace (or any other post .Net 3.5 functionality)

PS v2.0:

[string]::IsNullOrEmpty($SomeString)

PS v3.0:

[string]::IsNullOrWhiteSpace($SomeString)

PS v2.0 Error Message:

IsNullOrWhitespace : Method invocation failed because [System.String] doesn’t contain a method named ‘IsNullOrWhiteSpace’.

PS v2.0 compatible version of IsNullOrWhitespace function:

# PowerShell v2.0 compatible version of [string]::IsNullOrWhitespace.
function StringIsNullOrWhitespace([string] $string)
{
    if ($string -ne $null) { $string = $string.Trim() }
    return [string]::IsNullOrEmpty($string)
}

 

Get-ChildItem cmdlet’s –Directory and –File switches were introduced in PS v3.0

PS v2.0:

Get-ChildItem -Path $somePath | Where-Object { $_.PSIsContainer }	# Get directories only.
Get-ChildItem -Path $somePath | Where-Object { !$_.PSIsContainer }	# Get files only.

PS v3.0:

Get-ChildItem -Path $somePath -Directory
Get-ChildItem -Path $somePath -File

 

 

Other Links

Automatically Create Your Project’s NuGet Package Every Time It Builds, Via NuGet

June 22nd, 2013 15 comments

So you’ve got a super awesome library/assembly that you want to share with others, but you’re too lazy to actually use NuGet to package it up and upload it to the gallery; or maybe you don’t know how to create a NuGet package and don’t have the time or desire to learn.  Well, my friends, now this can all be handled for you automatically.

A couple weeks ago I posted about a new PowerShell script that I wrote and put up on CodePlex, called New-NuGetPackage PowerShell Script, to make creating new NuGet packages quick and easy.  Well, I’ve taken that script one step further and use it in a new NuGet package called Create New NuGet Package From Project After Each Build (real creative name, right) that you can add to your Visual Studio projects.  The NuGet package will, you guessed it, pack your project and its dependencies up into a NuGet package (i.e. .nupkg file) and place it in your project’s output directory beside the generated dll/exe file.  Now creating your own NuGet package is as easy as adding a NuGet package to your project, which if you’ve never done before is dirt simple.

I show how to add the NuGet package to your Visual Studio project in the New-NuGetPackage PowerShell Script documentation (hint: search for “New NuGet Package” (include quotes) to find it in the VS NuGet Package Manager search results), as well as how you can push your package to the NuGet Gallery in just a few clicks.

Here’s a couple screenshots from the documentation on installing the NuGet Package:

NavigateToManageNugetPackages   InstallNuGetPackageFromPackageManager

Here you can see the new PostBuildScripts folder it adds to your project, and that when you build your project, a new .nupkg file is created in the project’s Output directory alongside the dll/exe.

FilesAddedToProject     NuGetPackageInOutputDirectory

So now that packaging your project up in a NuGet package can be fully automated with about 30 seconds of effort, and you can push it to the NuGet Gallery in a few clicks, there is no reason for you to not share all of the awesome libraries you write.

Happy coding!

Create and publish your NuGet package in one click with the New-NuGetPackage PowerShell script

June 7th, 2013 No comments

I’ve spent a good chunk of time investigating how nuget.exe works and creating a PowerShell script called New-NuGetPackage to make it dirt simple to pack and push new NuGet packages.

Here’s a list of some of the script’s features:

  • Create the .nupkg package file and optionally push the package to the NuGet Gallery (or a custom gallery).
  • Can be ran from Windows Explorer (i.e. double-click it) or called via PowerShell if you want to be able to pass in specific parameters or suppress prompts.
  • Can prompt user for version number and release notes (prompts are prefilled with previous version number and release notes) or can suppress all prompts.

This makes packing and pushing your NuGet packages quick and easy, whether doing it manually or integrating it into your build system.  Creating NuGet packages wasn’t overly complicated before, but this makes it even simpler and less tedious.

Go to the codeplex page to download the script and start automating your NuGet package creating today.  The codeplex documentation describes the script in much more detail, as well as step by step instructions on how to get setup to start using it.

[UPDATE] I have also used this script in a new NuGet package that will automatically create a NuGet package for your own projects without you having to do anything. Read about it here. [/UPDATE]

 

Additional NuGet Information

During my investigation I compiled a list of what happens when doing “nuget spec” and “nuget pack” against the various different file types (e.g. dll vs. project vs. nuspec).  Someone else may find this information useful, so here it is:

Spec a Project or DLL directly (e.g. "nuget spec PathToFile"):
- Creates a partial .nuspec; still has placeholder info for some fields (e.g. Id, Dependencies).
- Creates [full file name with extension].nuspec file.
- The generated .nuspec file is meant to still be manually updated before making a package from it.

// TestProject.csproj.nuspec
<?xml version="1.0"?>
<package >
  <metadata>
    <id>C:\dev\TFS\RQ\Dev\Tools\DevOps\New-NuGetPackage\TestProject\TestProject\TestProject.csproj</id>
    <version>1.0.0</version>
    <authors>Dan Schroeder</authors>
    <owners>Dan Schroeder</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2013</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>
=====================================================================
Spec a DLL using "nuget spec" from the same directory:
- Creates a partial .nuspec; still has placeholder info for some fields (e.g. Id, Dependencies).
- Creates "Package.nuspec" file.
- The generated .nuspec file is meant to still be manually updated before making a package from it.

// Package.nuspec
<?xml version="1.0"?>
<package >
  <metadata>
    <id>Package</id>
    <version>1.0.0</version>
    <authors>Dan Schroeder</authors>
    <owners>Dan Schroeder</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2013</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>
=====================================================================
Spec a Project using "nuget spec" from the same directory:
- Creates a template .nuspec using the proper properties and dependencies pulled from the file.
- Creates [file name without extension].nuspec file.
- The generated .nuspec file can be used to pack with, assuming you are packing the Project and not the .nuspec directly.

// TestProject.nuspec
<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2013</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>
=====================================================================
Pack a Project (without accompanying template .nuspec):
- Does not generate a .nuspec file; just creates the .nupkg file with proper properties and dependencies pulled from project file.
- Throws warnings about any missing data in the project file (e.g. Description, Author), but still generates the package.

=====================================================================
Pack a Project (with accompanying template .nuspec):
- Expects the [file name without extension].nuspec file to exist in same directory as project file, otherwise it doesn't use a .nuspec file for the packing.
- Throws errors about any missing data in the project file if the .nuspec uses tokens (e.g. $description$, $author$) and these aren't defined in the project, so the package is not generated.

=====================================================================
Cannot pack a .dll directly

=====================================================================
Pack a .nuspec:
- Creates the .nupkg file with properties and dependencies defined in .nuspec file.
- .nuspec file cannot have any placeholder values (e.g. $id$, $version$).