Using-Object: PowerShell version of C#’s “using” statement.

function Using-Object
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [AllowEmptyCollection()]
        [AllowNull()]
        [Object]
        $InputObject,

        [Parameter(Mandatory = $true)]
        [scriptblock]
        $ScriptBlock
    )

    try
    {
        . $ScriptBlock
    }
    finally
    {
        if ($null -ne $InputObject -and $InputObject -is [System.IDisposable])
        {
            $InputObject.Dispose()
        }
    }
}

I don’t know why I did this. Performance is better if you use try/finally directly, rather than passing script blocks around. But, if you want PowerShell “using” syntax that looks similar to the C# examples you see on MSDN / etc, enjoy!

# Demonstrating the usage of Using-Object

Using-Object ($streamWriter = New-Object System.IO.StreamWriter("$pwd\newfile.txt")) {
    $streamWriter.WriteLine('Line written inside Using block.')
}

# The second call to $streamWriter.WriteLine() produces an error, because
# the stream is already closed.

$streamWriter.WriteLine('Line written outside Using block.')

Get-Content .\newfile.txt

About Dave Wyatt

Microsoft MVP (PowerShell), IT professional.
This entry was posted in PowerShell. Bookmark the permalink.

7 Responses to Using-Object: PowerShell version of C#’s “using” statement.

  1. 方大海 says:

    Great post, thanks!

    Like

  2. Pingback: Wrapping using statement with dispose in powershell - Alexander Williamson

  3. alx9r says:

    I like this idea. But this implementation never disposes $streamWriter because $streamWriter is never passed to Using-Object. Unlike for C#, variable assignments in PowerShell evaluate to $null so the assignment to $streamWriter occurs but the result is $null.

    Like

    • Dave Wyatt says:

      The parentheses in the example matter. 🙂 When you put an assignment expression in parentheses, in PowerShell, the value also surfaces as output. You can try it out at a console:

      $i = 1 # outputs nothing
      ($i = 2) # outputs 2

      Like

  4. PowerShellPls says:

    The only problem with this is that it’s not a true “using” statement – it’s basically a glorified function. The moment you enter it, scope goes bye bye.

    You can fix a hack with a hack – use [ref] on variables out of scope.

    function Main {

    $test1 = “foo”;
    $test2 = “foo”;

    Using-Object ($streamWriter = New-Object System.IO.StreamWriter(“$pwd\newfile.txt”)) {
    $streamWriter.WriteLine(‘Line written inside Using block.’)
    $test1 = “bar”;
    ([ref]$test2).Value = “bar”;
    }

    Write-Host $test1;
    Write-Host $test2;
    }

    Main;

    Like

    • Dave Wyatt says:

      If the Using-Object function is defined in a script module that’s separate from where the call comes from, it works fine. Another workaround if it’s defined in the same file / scope is to dot-source the call to Using-Object: . Using-Object ($object = Whatever) { $someVariable = ‘Value }

      Like

Leave a comment