Skip to content

Instantly share code, notes, and snippets.

@IISResetMe
Created April 29, 2025 19:08
Show Gist options
  • Save IISResetMe/226e9767d308f9e1953a8eca8ae329bd to your computer and use it in GitHub Desktop.
Save IISResetMe/226e9767d308f9e1953a8eca8ae329bd to your computer and use it in GitHub Desktop.
Wrap Stream to prevent Close/Dispose in PowerShell classes
class IndisposableStream : IO.Stream {
hidden [IO.Stream] $_inner
IndisposableStream([IO.Stream]$inner) {
$this._inner = $inner
}
# proxy (almost) everything back to the inner stream object
hidden [bool] get_CanRead() { return $this._inner.CanRead }
hidden [bool] get_CanWrite() { return $this._inner.CanWrite }
hidden [bool] get_CanSeek() { return $this._inner.CanSeek }
hidden [long] get_Length() { return $this._inner.Length }
hidden [long] get_Position() { return $this._inner.Position }
hidden [void] set_Position([long]$value) { $this._inner.Position = $value }
[long]
Seek([long]$offset, [IO.SeekOrigin]$origin) {
return $this._inner.Seek($offset, $origin)
}
[void]
SetLength([long]$length) {
$this._inner.SetLength($length)
}
[int]
Read([byte[]]$buffer, [int]$offset, [int]$count) {
return $this._inner.Read($buffer, $offset, $count)
}
[void]
Write([byte[]]$buffer, [int]$offset, [int]$count) {
$this._inner.Write($buffer, $offset, $count)
}
[void]
Flush() {
$this._inner.Flush()
}
# ... but shield inner stream from premature closure
#
# Sixel will now be calling either of these without changing
# the state of the inner stream object.
# This will allow Invoke-WebRequest's clumsy attempt to read
# it to end to actually succeed (since it remains unclosed)
[void]Dispose() {}
[void]Close() {}
}
# et voila, no more closed stream access error
Invoke-WebRequest -Uri https://pngimg.com/d/brain_PNG99.png -UseBasicParsing | ConvertTo-Sixel -Stream {[IndisposableStream]$_.RawContentStream}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment