I have a pipe function that allocates some resources in begin
block that need to be disposed at the end. I've tried doing it in the end
block but it's not called when function execution is aborted for example by ctrl
+c
.
How would I modify following code to ensure that $sw
is always disposed:
function Out-UnixFile([string] $Path, [switch] $Append) {
<#
.SYNOPSIS
Sends output to a file encoded with UTF-8 without BOM with Unix line endings.
#>
begin {
$encoding = new-object System.Text.UTF8Encoding($false)
$sw = new-object System.IO.StreamWriter($Path, $Append, $encoding)
$sw.NewLine = "`n"
}
process { $sw.WriteLine($_) }
# FIXME not called on Ctrl+C
end { $sw.Close() }
}
EDIT: simplified function
It's possible to write it in C# where one can implement IDisposable - confirmed to be called by powershell in case of ctrl
-c
.
I'll leave the question open in case someone comes up with some way of doing it in powershell.
using System;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Internal;
using System.Text;
namespace MarcWi.PowerShell
{
[Cmdlet(VerbsData.Out, "UnixFile")]
public class OutUnixFileCommand : PSCmdlet, IDisposable
{
[Parameter(Mandatory = true, Position = 0)]
public string FileName { get; set; }
[Parameter(ValueFromPipeline = true)]
public PSObject InputObject { get; set; }
[Parameter]
public SwitchParameter Append { get; set; }
public OutUnixFileCommand()
{
InputObject = AutomationNull.Value;
}
public void Dispose()
{
if (sw != null)
{
sw.Close();
sw = null;
}
}
private StreamWriter sw;
protected override void BeginProcessing()
{
base.BeginProcessing();
var encoding = new UTF8Encoding(false);
sw = new StreamWriter(FileName, Append, encoding);
sw.NewLine = "\n";
}
protected override void ProcessRecord()
{
sw.WriteLine(InputObject);
}
protected override void EndProcessing()
{
base.EndProcessing();
Dispose();
}
}
}