title: How can I ensure Dispose() is called on an advanced function's local variable on stop signal?
body: <p>I have noticed that objects implementing <code>IDisposable</code> in advanced functions aren't reliably disposed of when a "stop" signal (eg. pressing <kbd>CTRL</kbd>+<kbd>C</kbd>) is sent during execution.  This is a pain when the object holds a handle to, for example, a file.  If the stop signal is received at an inopportune time, the handle doesn't get closed and the file remains locked until the PowerShell session is closed.</p>
  
  <p>Consider the following class and functions:</p>
  
  <pre><code>class f : System.IDisposable {
      Dispose() { Write-Host 'disposed' }
  }
  
  function g {
      param( [Parameter(ValueFromPipeline)]$InputObject )
      begin { $f = [f]::new() }
      process {
          try { 
              $InputObject
          }
          catch {
              $f.Dispose()
              throw
          }
      }
      end {$f.Dispose()}
  }
  
  function throws {
      param ( [Parameter(ValueFromPipeline)] $InputObject )
      process { throw 'something' }
  }
  
  function blocks {
      param ( [Parameter(ValueFromPipeline)] $InputObject )
      process { Wait-Event 'bogus' }
  }
  </code></pre>
  
  <p>Imagine <code>$f</code> holds a handle to a file and releases it when its <code>Dispose()</code> method is called.  My goal is that the lifetime of <code>$f</code> matches the lifetime of <code>g</code>.  <code>$f</code> is disposed correctly when <code>g</code> is invoked in each the following ways:</p>
  
  <pre><code>g
  'o' | g
  'o' | g | throws
  </code></pre>
  
  <p>I can tell as much because each of these outputs <code>disposed</code>.</p>
  
  <p>When the stop signal is sent while execution is occuring downstream of <code>g</code>, however, <code>$f</code> is not disposed.  To test that, I invoked</p>
  
  <pre><code>'o' | g | blocks
  </code></pre>
  
  <p>which blocks at the <code>Wait-Event</code> inside <code>blocks</code>, then I pressed <kbd>Ctrl</kbd>+<kbd>C</kbd> to stop execution.  In that case, <code>Dispose()</code> does not seem to get called (or, at least <code>disposed</code> is not written to the console).</p>
  
  <p>In C# implementations of such functions it is my understanding that <a href="https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.cmdlet.stopprocessing?view=powershellsdk-1.1.0#System_Management_Automation_Cmdlet_StopProcessing" rel="nofollow noreferrer"><code>StopProcessing()</code></a> gets called on a stop signal to do such cleanup.  However, there seems to be no analog to <code>StopProcessing</code> available for PowerShell implementations of advanced functions.</p>
  
  <p>How can I ensure that <code>$f</code> is disposed in all cases including a stop signal?</p>