PowerShell: $null and parameter type

One of those things that can take you ages to find out: I create a function where a parameters that can either have a string value or can be $null:

function doit
{
  param
  (
    [string]$a = $( throw "Missing: parameter a"),
    $b = $( throw "Missing: parameter b")
  )

  if ($a -eq $null) { Write-Host "a is null" } else { write-Host "a is not null" }
  if ($b -eq $null) { Write-Host "b is null" } else { Write-Host "b is not null" }
}

If I call this function with: doit $null $null

I get the following result:

a is not null
b is null

What happened: because I specified a type [string] for parameter a, the $null value gets casted to a string with value "". 

4 Comments

  • Any idea on how to stop it from doing that?

    It appears that Powershell does this cast even when calling into an assembly (such as the SharePoint API), and null != String.Empty.

  • I have the same problem calling tfs method QueryLabels.

    This code in Powershell

    $labels = $vcs.QueryLabels("REL_1_*","$/ProjectX",$null,$false)

    is not hte same as this in C#

    VersionControlLabel[] labels = vcs.QueryLabels("REL_1_*", "$/ProjectX", null, false);

  • The only workaround I have been able to find for calling .Net assemblies is to write a cmdlet to wrap your call to .net assembly. This works fine.

    WriteObject(Vcs.QueryLabels(label, Scope, User, IncludeItems));

    Full Code below:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Management.Automation;
    using System.Collections;
    using Microsoft.TeamFoundation.VersionControl.Client;

    namespace WindowsPowerShell1
    {
    [Cmdlet(VerbsCommon.Get, "Label", SupportsShouldProcess = true)]
    public class GetLabel : Cmdlet
    {
    private string label;
    private string scope;
    private VersionControlServer vcs;
    private string user;
    private bool includeItems;

    #region Parameters
    [Parameter(Position = 0,
    Mandatory = true,
    ValueFromPipelineByPropertyName = true,
    HelpMessage="The label name - * is wildcard")]
    [ValidateNotNullOrEmpty]
    public string Label
    {
    get { return label; }
    set { label = value; }
    }
    [Parameter(Position = 1,
    Mandatory = true,
    ValueFromPipelineByPropertyName = true,
    HelpMessage = "Scope")]
    [ValidateNotNullOrEmpty]
    public string Scope
    {
    get { return scope; }
    set { scope = value; }
    }
    [Parameter(Position = 2,
    Mandatory = true,
    ValueFromPipelineByPropertyName = true,
    HelpMessage = "VersionControlServer")]
    [ValidateNotNull]
    public VersionControlServer Vcs
    {
    get { return vcs; }
    set { vcs = value; }
    }
    [Parameter(Position = 3,
    Mandatory = false,
    ValueFromPipelineByPropertyName = true,
    HelpMessage = "VersionControlServer")]
    public string User
    {
    get { return user; }
    set { user = value; }
    }
    [Parameter(Position = 4,
    Mandatory = true,
    ValueFromPipelineByPropertyName = true,
    HelpMessage = "IncludeItems")]
    public bool IncludeItems
    {
    get { return includeItems; }
    set { includeItems = value; }
    }
    #endregion

    protected override void ProcessRecord()
    {
    try
    {
    WriteObject(Vcs.QueryLabels(label, Scope, User, IncludeItems));
    }
    catch (Exception)
    {
    }
    }
    }
    }

  • Wow! I could not even guess about it)) Not bad.

Comments have been disabled for this content.