4

I've got a script that's chewing through a lot of objects, and sometimes I want to kill it in the middle of the run because I see something going south. Unfortunately, I'm writing to a log file using System.IO.StreamWriter, and whenever I send a Ctrl-C, my log files are stuck open.

Is there any way I can define some kind of handler or exiting function that allows me to gracefully close filehandles and connections that I have open?

3 Answers 3

4

Might try using Try/Catch/Finally, putting your close() commands in the Finally block.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm doing that in several parts of the program for various things, but it's more like I need something like the equivalent of "trap control_c SIGINT" from Bash. Although I guess I could put the entire script in a giant try{} statement and throw a finally{}. Can you nest try statements? This just seems like the wrong way.
Yes, you can nest Try statements.
2

With PowerShell 2.0 and up, you can define a Trap which will fire when a terminating error occurs. You can define multiple traps to capture different exceptions. This could result in much cleaner code than try/catch littered everywhere, or wrapping the entire script in one big try/catch.

1 Comment

Sadly, it doesn't look like I can trap Ctrl-C (whatever that appears as, to the script itself). At least, I haven't figured out how to do it yet.
1

To terminate a script, use exit .If an exception is thrown, use try/catch/finally with close() commands in finally. If it's just an if-test, try something like this:

function Close-Script {
    #If stream1 is created
    if($stream1) { 
        $stream1.Close()
    }

    #Terminate script
    exit
}

$stream1 = New-Object System.IO.StreamWriter filename.txt


If(a test that detects your error) {
    Close-Script
}

If the amounts of streamwriters varies from time to time, you can collect them to an array and close them. Ex:

function Close-Script {
    #Close streams
    $writers | % { $_.Close() }

    #Terminate script
    exit
}

$writers = @()
$stream1 = New-Object System.IO.StreamWriter filename.txt
$writers += $stream1
$stream2 = New-Object System.IO.StreamWriter filename2.txt
$writers += $stream2

If(a test that detects your error) {
    Close-Script
}

2 Comments

Thanks. It's less that there are actual errors that an If statement would catch. It's more like I'm watching debugging output and say, "oh, that's wrong, I've got to fix it", but I can't kill it until it's finished the loop of 150+ entities.
if you want a cleanup function after you use ctrl+c, you could use the function as I provided, but you would need to make the vars in the global scope(e.g. $global:writers), OR dot-source when running the script (. .\myscript.ps1), then calling Close-Script after ctrl+c

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.