Ran Lottem
Ran Lottem

Reputation: 486

Recreate Write-Progress functionality

I have a script that's calling an external exe file, msdl.exe, which is a multi-protocol downloader for various streaming protocols that I've compiled for windows.

It's output while downloading looks like this:

download [ MechHand-1.wmv ]
Host: [ 132.68.3.150:554 ]    connected!
Host: [ 132.68.3.150:554 ]    connected!
Speed: 2.000
DL: 815061/313870475 B --   0%            150.2K/s     # this line updates

The line I use to call the exe from within the script is:

cmd /c .\msdl.exe -s2 $address -o $filename '2>&1'

I've compiled the script to an exe to run on client computers. When running as an exe, however, the progress line does not overwrite itself, instead it's a new line every time, like so:

download [ MechHand-1.wmv ]
Host: [ 132.68.3.150:554 ]    connected!
Host: [ 132.68.3.150:554 ]    connected!
Speed: 2.000

DL: 82992/313870475 B --   0%                          0B/s
DL: 158076/313870475 B --   0%                         158.1K/s
DL: 233160/313870475 B --   0%                         158.1K/s
DL: 301987/313870475 B --   0%                         143.9K/s
DL: 377071/313870475 B --   0%                         143.9K/s

What I think I need is to pipe the output of the command executing msdl.exe into a foreach loop, and based on the content of the line either print it regularly (like the line saying download [ filename ]) or overwrite the previous line.

However if I pipe the output my concern is that it will first run the command, which could take a long time based on file size, and then display the progress all at once when it is over, rather than display output while it is being generated.

Would this work, or how can I replicate the desired behavior?

PS: The stderr redirection is because MSDL writes to stderr, and while this doesn't matter when running the script, when running the exe each line is printed in red and prefixed with 'ERROR: '.

Upvotes: 0

Views: 130

Answers (1)

BenH
BenH

Reputation: 10054

First, can you drop the call to cmd and just execute in PowerShell? Second, pipe the output into a ForEach-Object loop, and each time there is output clear the host and just display what you want to display. For example you could save the first 5 lines as a in banner variable. Then you could display the banner and the output line.

& .\msdl.exe -s2 $address -o $filename | ForEach-Object {$i=0} {
   Clear-Host
   $Banner 
   if ($i -le 5) {
        $Banner += $_
   }
   $_
   $i++
}

Upvotes: 1

Related Questions