1 year ago

#272397

test-img

Jordan

PowerShell: waiting for output redirect file to unlock after killing process

I have a PowerShell script that:

  • Starts a new process and redirects the output to two files
  • Waits with a timeout for the process to complete
  • Kills the process if it timed out
  • Reads the contents from the redirected output files

It looks something like this:

$_timeout = 30
$_stdoutfile = "./stdout"
$_stderrfile = "./stderr"

# Start the process
$_process = Start-Process powershell.exe -ArgumentList "-file ""$_cmdfile""" -PassThru -NoNewWindow -RedirectStandardError "$_stderrfile" -RedirectStandardOutput "$_stdoutfile"

# Wait for it to complete, or time out
$_timeout_error = $null
$_process | Wait-Process -Timeout $_timeout -ErrorAction SilentlyContinue -ErrorVariable _timeout_error

# Check if it timed out
if ($_timeout_error) {
    # Kill it
    $_process | Stop-Process -Force

    # (1)
    # Wait for the process to exit after the kill command
    $_kill_timeout_error = $null
    $_process | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue -ErrorVariable _kill_timeout_error

    # If the process is still running 10 seconds after the kill command die with an error
    if ($_kill_timeout_error) {
        Write-Error "Failed to terminate process (waited for 10 seconds after initiating termination)."
        Exit 1
    }
}

# (2)
# Read the stdout and stderr content that was output
$_stdout = [System.IO.File]::ReadAllText("$_stdoutfile")
$_stderr = [System.IO.File]::ReadAllText("$_stderrfile")

# Delete the files after reading them
Remove-Item -Force "$_stdoutfile"
Remove-Item -Force "$_stderrfile"

The majority of this works properly; the process is killed as expected if it runs too long. The problem I'm having is with the ReadAllText functions. They work fine if the process exits on its own, but if they were killed due to a timeout, these functions fail with the error:

The process cannot access the file 
'C:\myfilename' because it is being used by another process.

I figured that perhaps it takes the OS a couple seconds to unlock the files after the process is killed, so I inserted a sleep-poll loop at # (2), but often several minutes later, they're still locked.

@Santiago Squarzon suggested (in the comments) a way to read the file while it's still locked, which may work, but I also need to be able to delete them after reading them.

So my questions are:

  1. Is there a way to get these files to naturally unlock more quickly after killing the process?
  2. Is there a way to force-unlock these files with a separate PowerShell command/function?
  3. Unrelated, but is the part in my code around the comment # (1) necessary (waiting for the process to stop after the kill command), or will Stop-Process block until the process is actually stopped?

powershell

process

file-locking

start-process

0 Answers

Your Answer

Accepted video resources