I wrote the following function as a start, but I haven't been able to
find an easy way to capture a CTRL+C.
function ping([string] $hostToPing) {
$ping = new-object Net.NetworkInformation.Ping
$ip = $ping.Send($hostToPing).Address
write-host -s '' "PING $hostToPing ($ip): 32 data bytes"
$count = 0
while (1) {
$r = $ping.Send($hostToPing)
$count++
if ($r.Status -eq [Net.NetworkInformation.IPStatus]::Success) {
write-host -s '' -n "$($r.Buffer.Length) bytes from $($r.Address): "
write-host -s '' -n "icmp_seq=$count ttl=$($r.Options.Ttl) "
write-host -s '' "time=$($r.RoundtripTime) ms"
}
else {
write-host $r.Status
}
sleep 1
}
}
What I'd like is to have something like:
.{
trap SOME_CTRL_C_EXCEPTION { ...; continue }
$count = 0
while (1) { ... }
}
write-host 'summary info'
Is there any way of accomplishing something like this?
Thanks for any help,
- J.
I may have answered my own question. In looking at this further, it
seems there is no way to do this in a function, but I can in a cmdlet by
overriding the StopProcessing method, right?
Has any thought been given to providing a way to implement cmdlets from
within PowerShell?
- J.
Powershell does provide a way to write cmdlets through scripts. For example,
function scriptcmdlet
{
begin
{
$a = 5;
}
process
{
$_ * $a;
}
end
{
"every item is scaled by $a"
}
}
This script can work like a cmdlet. Begin/process/end blocks correspond to
BeginProcessing, ProcessingRecord, EndProcessing in cmdlet interface.
However, there is no block corresponding to StopProcessing for now.
Thanks,
--
George Xie [MSFT]
Microsoft Command Shell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
"J. McConnell" <j-...@kant.overstock.com> wrote in message
news:slrnejsbh9...@kant.overstock.com...
--- test-ctrlc.ps1 ---
[console]::TreatControlCAsInput = $true
while ($true)
{
write-host "Processing..."
if ([console]::KeyAvailable)
{
$key = [system.console]::readkey($true)
if (($key.modifiers -band [consolemodifiers]"control") -and
($key.key -eq "C"))
{
"Terminating..."
break
}
}
}
--- end of script ---
Regards,
Jacques
"George Xie [MSFT]" <gx...@online.microsoft.com> wrote in message
news:%23gJOyV5...@TK2MSFTNGP04.phx.gbl...
I like this syntax a lot. Thank you for this information.
> However, there is no block corresponding to StopProcessing for now.
Are there any plans to add a "stop" block?
- J.
Ahh, that's great. Thank you for the info, that's what I'll go with.
From a function, would it be recommended that the function restore the
value of [console]::TreatControlCAsInput? E.g.
fuction test {
$oldValue = [console]::TreatControlCAsInput
[console]::TreatControlCAsInput = $true
while ($true) { ... }
[console]::TreatControlCAsInput = $oldValue
}
Thanks,
- J.
Good catch. If you don't dot source your script, the change implemented in
the script will be lost as the script ends so other scripts won't be
impacted. But saving and restoring a "global" value is a good practice in
general.
Jacques
Thanks,
--
George Xie [MSFT]
Microsoft Command Shell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
"J. McConnell" <j-...@kant.overstock.com> wrote in message
news:slrnejsmq3...@kant.overstock.com...
As you're speaking about blocks, what about a "preparam" block (or
eventualy allow Begin block before param() definition) ?
As a scenario :
We want to write a script using an assembly not loaded by default.
If a "preparam" block exists we are able to load the assembly before
"param" and then use assembly's types to define param parameters.
AFAIK we can't do that in RC2 (we can load assembly in Begin but it's
too late to use its types in param).
Something like :
#---8<---
preparam{
[void][System.Reflection.Assembly]::`
LoadWithPartialName('System.Drawing')
}
param([drawing.fontstyle]$style='Bold')
begin{
#....code
}
process{
#....code
}
end{
#....code
}
#---8<---
Regards,
--
Jean - JMST
Belgium
Strike out those words :-)
--
George Xie [MSFT]
Microsoft Command Shell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
"Jean" <repo...@groupe.svp> wrote in message
news:mn.c8107d6a8ca49192.56820@windows...
After Jacque pointed out that I could handle a CTRL+C from within a
function, my need to implement StopProcessing went away. I was only
considering a cmdlet because I didn't realize there was another suitable
way for handling a CTRL+C.
In case anyone is interested, I wrote a helper function for this
purpose. Here it is:
function handleCtrlC($codeToRun) {
function handleIt($whatToDo) {
if ([console]::KeyAvailable) {
$key = [console]::readKey($true)
if (($key.modifiers -band [consolemodifiers]"control") `
-and ($key.key -eq "C")) {
&$whatToDo
}
}
}
$oldControlCValue = [console]::TreatControlCAsInput
[console]::TreatControlCAsInput = $true
&$codeToRun
[console]::TreatControlCAsInput = $oldControlCValue
}
It accepts a function that it calls after setting
[console]::TreatControlCAsInput to $true. From within that function,
you can call the "handleIt" function, which accepts a function that it
runs when the user has entered CTRL+C. I imagine it should be useful
anywhere you have a while ($true) { ... } loop.
Here's an example of what it looks like:
handleCtrlC {
function getTemp() { return (new-object Random).Next(100) }
$exit = $false
while ($true) {
$curTemp = getTemp
write-host "the current temperature is: $curTemp F"
$totalTemp += $curTemp
$count++
for ($i = 0; $i -lt 10; $i++) {
handleIt { set-variable exit $true -scope 2; break }
sleep -milliseconds 100
}
if ($exit) {
break
}
}
write-host "the temperature averaged $($totalTemp / $count) F"
}
While the example is pretty contrived, you can imagine the getTemp
function hitting some web service and all of a sudden it's almost
useful. I'm using this for a simple ping implementation which is
actually useful.
- J.
+ Scripts/functions that use out-of-process applications to perform some
work may leave the application running if aborted. Any special application
started as a new process and any out-of-process COM server are examples.
Word in particular is a good illustration; if you have Word doing work for a
script, it will not be visible by default and if the script/function
invoking it is aborted while it has a "dirty" document, it may continue
running. A stop block would permit you to directly exit Word.
+ Temp file cleanup
+ Logging information about an important script being halted.
+ Using a script _specifically_ to log information or perform cleanup for
cmdlets or console applications that don't clean up nicely when halted.
"George Xie [MSFT]" <gx...@online.microsoft.com> wrote in message
news:%23EWVu56...@TK2MSFTNGP04.phx.gbl...
If you don't know what I mean or want to try that, post back; if you're
still looking at other bits of the process, ignore this for now. :)
"J. McConnell" <j-...@j-dotonline.com> wrote in message
news:slrnejpoug...@kant.overstock.com...