Problems with GenerateConsoleCtrlEvent and SendInput

Discussion in 'Perl Misc' started by mike_cole@adaptec.com, Nov 7, 2005.

  1. Guest

    I am running a Perl script and within that script, I create a process
    which starts up a 3rd party console app. At a later point I want to
    send a ctrl-c to that console app. I tried using Win32::API to send a
    ctrl-c via GenerateConsoleCtrlEvent(), but it keeps sending ctrl-c to
    *my* application, not to the app I want to close. I also tried using
    SendInput, but the return value indicates that it did not work because
    one or more of the parameters was incorrect. Has anybody used either of
    these two functions successfully to send a ctrl-c to a console app?
    BTW, I am using ActiveState Perl 5.8. I tried adding in snippets of
    code, but there is not enough space or else I don't know to access more
    space :-(

    Thanks,
    Mike
     
    , Nov 7, 2005
    #1
    1. Advertising

  2. wrote in
    news::

    > I am running a Perl script and within that script, I create a process
    > which starts up a 3rd party console app. At a later point I want to
    > send a ctrl-c to that console app. I tried using Win32::API to send a
    > ctrl-c via GenerateConsoleCtrlEvent(), but it keeps sending ctrl-c to
    > *my* application, not to the app I want to close. I also tried using
    > SendInput, but the return value indicates that it did not work because
    > one or more of the parameters was incorrect.


    Please post a short but complete script illustrating the problem. For
    suggestions on how to prepare such a post, please read the posting
    guidelines for this group.

    > of these two functions successfully to send a ctrl-c to a console app?
    > BTW, I am using ActiveState Perl 5.8. I tried adding in snippets of
    > code, but there is not enough space or else I don't know to access
    > more space :-(


    That makes no sense.

    Sinan
    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 7, 2005
    #2
    1. Advertising

  3. Guest

    The code that I was using is shown below. The API calls were declared
    using Win32::API, Win32::API::prototype and Win32::process

    A portion of the creation routine:

    Win32::process->Create ($ProcessObj, "E:\Tools\Hdeperf.exe","", 0,
    CREATE_DEFAULT_ERROR_MODE |
    CREATE_NEW_CONSOLE |
    CREATE_NEW_PROCESS_GROUP, "." );
    return($ProcessObj);


    Attempting to use GenerateConsoleCtrlEvent():

    sub HaltHdPerf
    {
    my ($Pid) = @_;
    my $CTRL_C_EVENT = pack('L',0);
    # my $CTRL_C_EVENT = pack('L',1); # ctrl break
    my $ProcessID = pack('L',$Pid->GetProcessID());

    LogPrint("pid for hdperf = ".$Pid->GetProcessID()."\n");
    LogPrint("pid for perl = $$ \n");
    LogPrint("Halting HdPerf on pid ".unpack('L',$ProcessID)."\n");
    my $Status = GenerateConsoleCtrlEvent($CTRL_C_EVENT, $ProcessID);
    my $lasterror = GetLastError();
    LogPrint("Status = $Status and last error = $lasterror\n");
    }

    Output from above code using a ctrl-c event:

    pid for hdperf = 3424
    pid for perl = 3436
    Halting HdPerf on pid 3424
    Terminating on signal SIGINT(2)
    Status = 1 and last error = 183

    Unfortunately it is my program that was terminated.
    If I use ctrl break instead of ctrl c I get:

    pid for hdperf = 3244
    pid for perl = 4064
    Halting HdPerf on pid 3244
    Terminating on signal SIGINT(2)

    And, again, it is my program that terminates. After failing at this, I
    tried using SendInput(). This would be my preferred method (as if I had
    a choice) since I need to send a ctrl-c to stop the program and then
    follow that with a "Y" to actually close the window. The code for using
    SendInput() is as follows. It is messier and there are better ways to
    do it, but I went for the most simplistic since this was new to me.

    sub HaltHdPerf2
    {
    my ($Pid) = @_;
    my $ProcessID = pack('L',$Pid->GetProcessID());
    my $CTRL_C_EVENT = pack('L',0);
    my $INPUT_KEYBOARD = 1;
    my $KEYEVENTF_KEYUP = 2;
    my $KEYEVENTF_KEYDOWN = 0;
    my $VK_CONTROL = 17;
    my $StructSize = 20;

    # This is an INPUT struct
    Win32::API::Struct->typedef( KBD_INPUT => qw {
    DWORD inputType; # 4 bytes
    WORD wVK; # 2 bytes start of KEYBDINPUT struct
    WORD wScan; # 2 bytes
    DWORD dwFlags; # 4 bytes
    DWORD dwTime; # 4 bytes
    DWORD dwExtraInfo; # 4 bytes end of KEYBDINPUT
    struct
    } ); # total = 20 bytes

    LogPrint("size of DWORD = ".Win32::API::Type->sizeof('DWORD')." and
    size of WORD = ".Win32::API::Type->sizeof('WORD')."\n");

    # Create a structure for SendInput
    my $kbdInput = Win32::API::Struct->new ( 'KBD_INPUT' );
    $kbdInput->{inputType} = $INPUT_KEYBOARD;
    $kbdInput->{wVK} = $VK_CONTROL;
    $kbdInput->{wScan} = 0;
    $kbdInput->{dwFlags} = $KEYEVENTF_KEYDOWN;
    $kbdInput->{dwTime} = time();
    $kbdInput->{dwExtraInfo} = 0;

    # Use the topmost window as a starting point
    my $hWnd = GetTopWindow( 0 );
    my $CharSize = 1 + Win32::API::IsUnicode();

    # Cycle thru each window and find the one with the desired string in
    the title
    do {
    # Allocate a buffer for the window title and set it to all null
    characters
    my $Size = ( GetWindowTextLength( $hWnd ) + 1 ) * $CharSize;
    my $Buff = "\x0" x $Size;

    # Get the window's title and get rid of any remaining null characters
    from above
    GetWindowText( $hWnd, $Buff, $Size );
    $Buff =~ s/\x0//g;

    # If the title matches then send crtl-c to the window
    if( $Buff =~ m/WINDOWS\\system32\\cmd.exe/i ) {
    LogPrint("HdPerf window found\n");

    # Bring this window into focus
    SetForegroundWindow($hWnd);

    LogPrint("Sending ctrl-c command to HdPerf\n");

    # Press ctrl key
    my $InsertedEvents = SendInput(pack('I',1), $kbdInput,
    pack('i',$StructSize));
    LogPrint("InsertedEvents = $InsertedEvents\n");

    # Press 'c' key
    $kbdInput->{wVK} = 'c';
    $InsertedEvents = SendInput(pack('I',1), $kbdInput,
    pack('i',$StructSize));
    LogPrint("InsertedEvents = $InsertedEvents\n");

    # Release 'c' key
    $kbdInput->{dwFlags} = $KEYEVENTF_KEYUP;
    $InsertedEvents = SendInput(pack('I',1), $kbdInput,
    pack('i',$StructSize));
    LogPrint("InsertedEvents = $InsertedEvents\n");

    # Release ctrl key
    $kbdInput->{wVK} = $VK_CONTROL;
    $InsertedEvents = SendInput(pack('I',1), $kbdInput,
    pack('i',$StructSize));
    LogPrint("InsertedEvents = $InsertedEvents\n");
    }
    }
    while( $hWnd = GetWindow( $hWnd, 0x02 ) ); # get the next window
    LogPrint("All done\n");
    }
    }


    Output from the above code:

    size of DWORD = 4 and size of WORD = 2
    HdPerf window found
    Sending ctrl-c command to HdPerf
    InsertedEvents = 0
    InsertedEvents = 0
    InsertedEvents = 0
    InsertedEvents = 0
    All done
     
    , Nov 8, 2005
    #3
  4. wrote in
    news::

    [ Please get in the habit of quoting an appropriate amount of context. ]

    > The code that I was using is shown below.


    You did not post a short but complete script that others can run simply by
    copying and pasting.

    > The API calls were declared
    > using Win32::API, Win32::API::prototype and Win32::process
    >
    > A portion of the creation routine:
    >
    > Win32::process->Create ($ProcessObj, "E:\Tools\Hdeperf.exe","", 0,
    > CREATE_DEFAULT_ERROR_MODE |
    > CREATE_NEW_CONSOLE |
    > CREATE_NEW_PROCESS_GROUP, "." );


    It looks like you do not have:

    use strict;
    use warnings;

    in your code. In addition, you do not check the return value of
    Win32::process::Create. Did you try printing the string you are passing to
    Create?

    Now, given that you haven't posted a short but complete script I can run
    without a lot of effort, and your call to Create is likely failing (unless
    E:ToolsHdeperf.exe really exists), I am not inclined to spend much time on
    your question at this point.

    Please read the posting guidelines for this group. They contain invaluable
    information on how to make it easier for other people to help you.

    Sinan
     
    A. Sinan Unur, Nov 8, 2005
    #4
  5. Guest

    Sinan,

    "You did not post a short but complete script that others can run
    simply by copying and pasting."

    The program we are using constitutes several thousand lines. The
    portion I posted needs several hundred lines of setup code involving
    our libraries just to get to that point. The program HdPerf is a load
    generator which has the potential to wipe out any disks you may have on
    your system. Therefore, I cannot post some code which you can just cut
    and paste and run.

    "Now, given that you haven't posted a short but complete script I can
    run without a lot of effort, and your call to Create is likely failing
    (unless E:ToolsHdeperf.exe really exists), I am not inclined to spend
    much time on your question at this point."

    My call to Create works just fine. The program is executed and runs.
    The problem is in getting the program to stop by sending it a ctrl-c. I
    have tried using SendInput() and GenerateConsoleCtlrEvent() both within
    Perl and as a call to a VC++ program. Neither works. From the posts
    that I have read, it seems that this has befuddled many other people. I
    was just trying to find out if anybody recently has had success using
    either of these.
     
    , Nov 9, 2005
    #5
  6. wrote in news:1131570960.366337.318320
    @f14g2000cwb.googlegroups.com:

    > "You did not post a short but complete script that others can run
    > simply by copying and pasting."
    >
    > The program we are using constitutes several thousand lines. The
    > portion I posted needs several hundred lines of setup code involving
    > our libraries just to get to that point. The program HdPerf is a load
    > generator which has the potential to wipe out any disks you may have
    > on your system. Therefore, I cannot post some code which you can just
    > cut and paste and run.


    Put your question is about a very specific aspect that need not involve
    any of that stuff. You should make an effort to reduce the script to the
    bare minimum required to exhibit the problem.

    > "Now, given that you haven't posted a short but complete script I can
    > run without a lot of effort, and your call to Create is likely failing
    > (unless E:ToolsHdeperf.exe really exists), I am not inclined to spend
    > much time on your question at this point."
    >
    > My call to Create works just fine.


    The call to Create that you posted:

    > wrote in
    >news::
    >
    >> Win32::process->Create ($ProcessObj, "E:\Tools\Hdeperf.exe","", 0,
    >> CREATE_DEFAULT_ERROR_MODE |
    >> CREATE_NEW_CONSOLE |
    >> CREATE_NEW_PROCESS_GROUP, "." );


    cannot work because you are passing "E:ToolsHdeperf.exe" to it.

    > Perl and as a call to a VC++ program. Neither works. From the posts
    > that I have read, it seems that this has befuddled many other people.
    > I was just trying to find out if anybody recently has had success
    > using either of these.


    Have you had success in the simplest case?

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 9, 2005
    #6
  7. "A. Sinan Unur" <> wrote in
    news:Xns9709BD39D105asu1cornelledu@127.0.0.1:

    > wrote in news:1131570960.366337.318320
    > @f14g2000cwb.googlegroups.com:


    ....

    >> My call to Create works just fine.

    >
    > The call to Create that you posted:
    >
    >> wrote in
    >>news::
    >>
    >>> Win32::process->Create ($ProcessObj, "E:\Tools\Hdeperf.exe","", 0,
    >>> CREATE_DEFAULT_ERROR_MODE |
    >>> CREATE_NEW_CONSOLE |
    >>> CREATE_NEW_PROCESS_GROUP, "." );

    >
    > cannot work because you are passing "E:ToolsHdeperf.exe" to it.


    In addition, you are calling the way you are calling Create, the first
    argument passed to the sub is *not$ $ProcessObj.

    Sinan
    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 10, 2005
    #7
  8. "A. Sinan Unur" <> wrote in news:Xns9709BD39D105asu1cornelledu@127.0.0.1:

    > wrote in news:1131570960.366337.318320
    > @f14g2000cwb.googlegroups.com:


    ....

    >> The program we are using constitutes several thousand lines.


    ....

    > Have you had success in the simplest case?


    So, I tried to come up with the simplest case. First, note that using

    > my $CTRL_C_EVENT = pack('L',0);


    is wrong. pack returns a string.

    Anyway, I wrote a short script:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Win32;
    use Win32::API;
    use Win32::API::Type;
    use Win32::process;

    my $GenerateConsoleCtrlEvent = Win32::API->new(
    'kernel32',
    'BOOL GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId)'
    );

    my $process;

    unless( Win32::process::Create($process, 'program.exe', q{}, 0,
    CREATE_DEFAULT_ERROR_MODE
    | CREATE_NEW_CONSOLE
    | CREATE_NEW_PROCESS_GROUP,
    ".")
    ) {
    die Win32::FormatMessage( Win32::GetLastError() );
    }

    warn $process->GetProcessID, "\n";

    sleep 1;

    my $result = $GenerateConsoleCtrlEvent->Call(
    0, $process->GetProcessID
    );

    unless ($result) {
    die Win32::FormatMessage( Win32::GetLastError() );
    }

    my $t = <STDIN>;

    __END__

    program.exe is just a simple C program that is waiting for
    input on stdin.

    When I run the program, a new cmd window is created with
    program.exe running in it. Here is the output I get from
    the Perl script:

    D:\Home\asu1\UseNet\clpmisc\ctrlc> ctrlc.pl
    2876
    The parameter is incorrect.

    Hmmm ... Let's check Microsoft's documentation
    for GenerateConsoleCtrlEvent available at

    <URL: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/generateconsolectrlevent.asp>

    Identifier of the process group to receive the signal.
    A process group is created when the CREATE_NEW_PROCESS_GROUP
    flag is specified in a call to the CreateProcess function.
    The process identifier of the new process is also the process
    group identifier of a new process group. The process group
    includes all processes that are descendants of the root process.
    Only those processes in the group that share the same console as
    the calling process receive the signal. In other words,
    if a process in the group creates a new console, that process
    does not receive the signal, nor do its descendants.

    So, I do not see any hope of using this API call to send a CTRL-C
    or CTRL-BREAK to a process in a different process group.

    You could have figured out up to this point by actually enabling
    warnings, and checking return values of calls.

    On the other hand:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Win32;
    use Win32::API;
    use Win32::API::Type;
    use Win32::GuiTest qw(FindWindowLike SendKeys SetForegroundWindow);
    use Win32::process;

    my $GenerateConsoleCtrlEvent = Win32::API->new(
    'kernel32',
    'BOOL GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId)'
    );

    my $process;

    unless( Win32::process::Create($process, 'program.exe', q{}, 0,
    CREATE_DEFAULT_ERROR_MODE
    | CREATE_NEW_CONSOLE
    | CREATE_NEW_PROCESS_GROUP,
    ".")
    ) {
    die Win32::FormatMessage( Win32::GetLastError() );
    }

    sleep 1;

    my ($window) = FindWindowLike(0, '^program\.exe');
    SetForegroundWindow($window);
    SendKeys '{BREAK}';

    my $t = <STDIN>;

    __END__

    I hope this demonstrates that one can write short but
    complete scripts without the danger of crashing the hard drive.

    Sinan
    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 10, 2005
    #8
  9. Guest

    Sinan,

    In your previous post, you asked about the simplest case. This prompted
    me to put together the simplest script I could. I always use strict and
    use warnings, but this did not help me. Below is the program I wrote
    this morning before I read your latest reply (which, BTW, is one of the
    most complete replies to a post I have seen in a long time) and my
    results did not indicate an error from GetLastError(). I had read the
    Windows documentation before, but I guess I had interpreted wrongly. I
    don't quite understand about using the pack operation though. When I
    did not use it, I got an "invalid param" error in my call to
    GenerateConsoleCtrlEvent(). Thank you for taking the time to help me
    out.

    ======================================================================

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Win32;
    use Win32::API;
    use Win32::API::prototype;
    use Win32::process;

    my $ProcessObj;
    my $FullPath = "E:\\callmon.bat";

    Win32::API::prototype::ApiLink( 'kernel32.dll', 'BOOL
    GenerateConsoleCtrlEvent( DWORD dwCtrlEvent, DWORD wProcessGroupId )'
    );
    Win32::API::prototype::ApiLink( 'kernel32.dll', 'DWORD GetLastError( )'
    );

    print("Process ID for this app = $$ \n");

    #Win32::process::Create($obj,$appname,$cmdline,$iflags,$cflags,$curdir)

    #Creates a new process.
    # Args:
    # $obj container for process object
    # $appname full path name of executable module
    # $cmdline command line args
    # $iflags flag: inherit calling processes handles or not
    # $cflags flags for creation (see exported vars below)
    # $curdir working dir of new process
    #Returns non-zero on success, 0 on failure.

    print("Creating console app\n");
    Win32::process::Create( $ProcessObj, $FullPath, "", 0,

    CREATE_DEFAULT_ERROR_MODE|CREATE_NEW_CONSOLE|CREATE_NEW_PROCESS_GROUP,
    "." ) || die "Could not create process\n";

    my $Pid = pack('L', $ProcessObj->GetProcessID);
    my $CTRL_C_EVENT = pack('L',0);

    print("Process ID for console app = ".unpack('L',$Pid)."\n");
    print("Halting console app\n");
    print("Delay for a bit\n");
    sleep(5);
    my $Status = GenerateConsoleCtrlEvent($CTRL_C_EVENT, $Pid);
    my $lasterror = GetLastError();
    print("Status = $Status and last error = $lasterror\n");
    sleep(5);
    print("Notice that this line does not execute and the other app is
    still running\n");

    ========================================================================
    Here is the batch file (callmon.bat) that is called by the above
    program:

    start perl mon.pl

    ========================================================================
    Here is the code for the program (mon.pl) started by the batch file:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my ($ddir, $results);

    print "Running monitor daemon - do not close window!\n";

    while (1){
    # Check for tokens
    $_=`dir /b`;

    if(m/kill.dat/) {
    print "Found program exit token\n";
    system "del kill.dat";
    last;
    }
    sleep(5);
    }
    =============================================================
    The output from above was:

    E:\>perl closeapp.pl
    Process ID for this app = 300
    Creating console app
    Process ID for console app = 3232
    Halting console app
    Delay for a bit
    Terminating on signal SIGINT(2)
    Status = 1 and last error = 0
     
    , Nov 10, 2005
    #9
  10. wrote in news:1131630947.343529.187440
    @o13g2000cwo.googlegroups.com:

    > I don't quite understand about using the pack operation though. When I
    > did not use it, I got an "invalid param" error in my call to
    > GenerateConsoleCtrlEvent().


    I think the invalid parameter error is due to the second argument to
    GenerateConsoleCtrlEvent, not the first. If you run the first example I
    gave with the packed argument, you will still get an invalid parameter
    error. That is because, as the GenerateConsoleCtrlEvent does not allow
    you to send the event to a process group outside of the one in which the
    controlling process is running.

    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > use Win32;
    > use Win32::API;
    > use Win32::API::prototype;


    I do not have Win32::API::prototype installed, so I'll keep using just
    the Win32::API.

    > use Win32::process;
    >
    > my $ProcessObj;
    > my $FullPath = "E:\\callmon.bat";


    my $FullPath = 'E:/callmon.bat';

    would also work.

    > my $Pid = pack('L', $ProcessObj->GetProcessID);
    > my $CTRL_C_EVENT = pack('L',0);


    I really think this is a red-herring. You do not need any of the packs.

    Just to illustrate my point about the packs, here is a cut down version
    of your script (using Win32::API and without the comments):

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Win32;
    use Win32::API;
    use Win32::API::Type;
    use Win32::process;

    my $GenerateConsoleCtrlEvent = Win32::API->new(
    'kernel32',
    'BOOL GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD
    dwProcessGroupId)'
    );

    print("Process ID for this app = $$ \n");
    print("Creating console app\n");

    my $ProcessObj;
    my $FullPath = q{callmon.bat};

    Win32::process::Create($ProcessObj, $FullPath, q{}, 0,
    CREATE_DEFAULT_ERROR_MODE
    | CREATE_NEW_CONSOLE
    | CREATE_NEW_PROCESS_GROUP, q{.})
    or die Win32::FormatMessage(Win32::GetLastError());

    my $Pid = pack('L', $ProcessObj->GetProcessID);
    my $CTRL_C_EVENT = pack('L',0);

    print("Halting console app\n");
    print("Delay for a bit\n");

    sleep(5);

    my $Status = $GenerateConsoleCtrlEvent->Call($CTRL_C_EVENT, $Pid);
    warn Win32::FormatMessage(Win32::GetLastError());

    sleep(5);

    print("Notice that this line does not execute and the other app is
    still running\n");

    Notice the warnings I get:

    D:\Home\asu1\UseNet\clpmisc\proc> proc.pl
    Process ID for this app = 2612
    Creating console app
    Halting console app
    Delay for a bit
    Argument "\0\0\0\0" isn't numeric in subroutine entry at D:\Home\asu1
    \UseNet\clpmisc\proc\proc.pl line 36, <DATA> line 164.
    Argument "¿^B\0\0" isn't numeric in subroutine entry at D:\Home\asu1
    \UseNet\clpmisc\proc\proc.pl line 36, <DATA> line 164.
    Terminating on signal SIGINT(2)

    > print("Process ID for console app = ".unpack('L',$Pid)."\n");

    ....
    > my $Status = GenerateConsoleCtrlEvent($CTRL_C_EVENT, $Pid);


    I suspect that $Pid, being non-numeric, is being passed as 0 which means
    "send the CTRL-C even to the *this* process group".

    > Here is the code for the program (mon.pl) started by the batch file:


    I think this code could be written in a better way, but let's not worry
    about that right now. Basically, this app will not terminate properly on
    a SIGINT.

    The only solution I can think of, and my Win32 knowledge is fairly
    limited, is to use SendKeys, along with a properly written version of
    mon.pl.

    This will require that you supply a title to start when you call mon.pl:

    start "My monitor application" perl.exe mon.pl

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Win32;
    use Win32::GuiTest qw(FindWindowLike SendKeys SetForegroundWindow);
    use Win32::process;

    print("Process ID for this app = $$ \n");
    print("Creating console app\n");

    my $ProcessObj;
    my $FullPath = q{callmon.bat};

    Win32::process::Create($ProcessObj, $FullPath, q{}, 0,
    CREATE_DEFAULT_ERROR_MODE
    | CREATE_NEW_CONSOLE
    | CREATE_NEW_PROCESS_GROUP, q{.})
    or die Win32::FormatMessage(Win32::GetLastError());

    print("Halting console app\n");
    print("Delay for a bit\n");

    sleep(5);

    my ($window) = FindWindowLike(0, '^My monitor application');
    SetForegroundWindow($window);
    SendKeys '^{BREAK}';

    __END__

    You will notice that mon.pl, as you have it now, will not terminate
    properly:

    Running monitor daemon - do not close window!
    Terminating on signal SIGBREAK(21)
    The process tried to write to a nonexistent pipe.
    The process tried to write to a nonexistent pipe.
    The process tried to write to a nonexistent pipe.

    If you want to force it terminate, you can just close the window using
    SendKeys:

    SendKeys q{% c};

    Hope this helps.

    Sinan
    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 10, 2005
    #10
  11. Guest

    A. Sinan Unur wrote:
    > The only solution I can think of, and my Win32 knowledge is fairly
    > limited, is to use SendKeys, along with a properly written version of
    > mon.pl.


    > Hope this helps.


    Yes, it helped a lot! I ran the code you provided using SendKeys(). By
    sending '^C' and then following it with 'Y~', I was able to close the
    HdPerf application. Also, the code you provided gave me some tips on
    coding style and some ideas on how to simplify things. Thanks.

    Mike
     
    , Nov 10, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Barb

    SendInput too slow

    Barb, Oct 3, 2003, in forum: C++
    Replies:
    1
    Views:
    1,838
    Thomas Matthews
    Oct 3, 2003
  2. Susan Baker
    Replies:
    2
    Views:
    860
    kelvSYC
    Jun 26, 2005
  3. Adam W.

    How do I use SendInput in Python?

    Adam W., Feb 16, 2008, in forum: Python
    Replies:
    1
    Views:
    683
    Gabriel Genellina
    Feb 16, 2008
  4. Peter C. Verhage

    Ruby/DL SendInput

    Peter C. Verhage, May 8, 2005, in forum: Ruby
    Replies:
    5
    Views:
    360
    Peter C. Verhage
    May 9, 2005
  5. Sak Na rede
    Replies:
    0
    Views:
    440
    Sak Na rede
    Jan 30, 2009
Loading...

Share This Page