#!C:/Perl/bin/Perl.exe -w # Program.. : zsln.pl: drive KMDLogonNET.exe through auto.logon to KMD MVS/CICS # Function. : GUI Robot for navigating and performing logon on to KMD backend. # Usage.... : zsln[.exe] (ON|OFF); if ON: optional params (userid, passwd, cics) # History.. : 20060713 - AND:Allan Dystrup, Ver.0.1-Initial version (prototype). # 20071030 - AND, Ver.0.2-Cmdline @ARGS with default to SDP logon. # 20071106 - AND, Ver.0.3-logon_state speedup (no sleep) # Copyright.: OS, - use as is (no warranty given). # ToDo......: logon_state: Get text via clip (^A^C) is fragile - a better way? # Implement usage & help # ============================================================================== ### ============================================================================ ### use ### ============================================================================ use strict; use warnings; use Data::Dumper; use IO::Handle; # autoflush use Win32::GuiTest qw(:ALL); use Win32::Clipboard; ### ============================================================================ ### global config ### ============================================================================ *STDOUT->autoflush(); # $| = 1, select $_ for select STDOUT; #use constant SW_SHOWNORMAL => 1; #use constant SW_SHOWMINIMIZED => 2; #use constant SW_MAXIMIZE => 3; ### ---------------------------------------------------------------------------- ### scan_proc ### ---------------------------------------------------------------------------- sub scan_proc { my $target = shift; my @status; print " Scanning running processes for '$target'...\n"; my @procs = `ps`; sleep(3); foreach my $proc (@procs) { chomp $proc; # print "[$proc]\n"; if ( $proc=~/$target/ ) { $proc =~ /\s+(\d+)\s+/; # print "***Found $proc\n"; push @status, $1; } } print "\tFound PIDs: " . (@status ? "@status" : "none") . "\n"; return "@status"; # Flattened PIDs } ### ---------------------------------------------------------------------------- ### kill_proc ### ---------------------------------------------------------------------------- sub kill_proc { my $procs = "@_"; # Flatten if ( $procs =~ /(\d+\s*)+/ ) { print "killing: $procs\n"; system "kill -1 $procs"; # SIGHUP - hang up system "kill -15 $procs"; # SIGTERM - terminale system "kill -9 $procs"; # SIGKILL - kill return 1; } return 0; } ### ---------------------------------------------------------------------------- ### start_proc ### ---------------------------------------------------------------------------- sub start_proc{ my ($path, $prog) = @_; print "\nStarting process $prog\n"; if ( scan_proc("$prog") =~ /(\d+)/ ) { print "\t$prog already running: $1 - OK\n"; return 1; } print "\t$prog not running, starting...\n"; system "start $path\\$prog"; TRY_C: for my $i (1..5) { sleep(2); if ( scan_proc("KMD\.YH.Security\.Winform\.Logon.exe") =~ /(\d+)/ ) { print "\t$prog started: $1 - OK\n"; last TRY_C; } return 1; } return 0; } ### ---------------------------------------------------------------------------- ### set_front_win ### ---------------------------------------------------------------------------- sub set_front_win { my $win = shift; my $status = 1; if (SetForegroundWindow($win)) { print "\tWindow $win: foreground - OK\n"; } else { my $fg_win = GetForegroundWindow(); my $fg_txt = GetWindowText($fg_win); print "\tCouldn't set: $win foreground!\n", "\t\tForegroundWindow: $fg_win ($fg_txt)\n"; $status = 0; } if (SetActiveWindow($win)) { print "\tWindow $win: active - OK\n"; } else { print "\tCouldn't set window $win active!\n"; $status = 0; } return $status; } ### ---------------------------------------------------------------------------- ### logon_state ### ---------------------------------------------------------------------------- ### Assuming KMD\.YH.Security\.Winform\.Logon.exe is running, cf. KMDLogonNET_process sub logon_state { my $Win = "KMD Logon"; # .NET 1.1 : "KMDLogon .NET" my (@logon, @list, $cont, $status); my $clip = Win32::Clipboard(); $clip->Empty(); print "\nChecking logon state...\n"; # 'KMDLogon .NET' @logon = FindWindowLike( undef, "^$Win" ); if (not @logon) { print "\tCan't locate $Win...\n"; return $status; } ShowWindow($logon[0], SW_SHOWNORMAL); set_front_win($logon[0]) or warn "Can't activate: $logon[0] - QUIT\n"; # Check logged onto # my $list_cls = "WindowsForms10.EDIT.app3"; # .NET 1.1 my $list_cls = "WindowsForms10.EDIT.app.0.378734a"; @list = FindWindowLike( $logon[0], ".*", "^$list_cls" ); if (not @list) { print "\tCan't find $list_cls $Win...\n"; return $status; } print "\tFound $list_cls\n"; # ... Activate editbox my ($l,$t,$r,$b) = GetWindowRect( $list[0] ); MouseMoveAbsPix( $l+1, $t+1 ); # sleep(1); SendMouse( "{LEFTCLICK}{LEFTCLICK}" ); # sleep(1); # ... Get Logon state my ($text, $h_log); set_front_win($logon[0]) or warn "Can't activate: $logon[0] - QUIT\n"; # ... ... Cut/Paste 'System Bruger' to clipboard (-- fragile) #for my $i (1..3) { # print "\t--- $i.try:\n"; # SendKeys("^A^C"); sleep($i-1); # mark for cut/paste # $text = $clip->GetText(); # do cut/paste # $status = ($text =~ /CICS/i ? 1 : 0); # last if $status; #} # ... ... Read text [Fjern|Log af] on 'KMD Logon' status window button my $btn_cls = "WindowsForms10.BUTTON.app.0.378734a"; my @btn = FindWindowLike( $logon[0], ".*", "^$btn_cls" ); for my $h (@btn) { $h_log=$h if (GetWindowText($h) =~ /Log af/i); } $status = ($h_log and IsWindowEnabled($h_log)) ? 1 : 0; print "\tLogon state: " . ($status ? " " : " NOT") . " Logged on\n"; ShowWindow($logon[0], SW_SHOWMINIMIZED); return $status; } ### ---------------------------------------------------------------------------- ### logon_KMD ### ---------------------------------------------------------------------------- sub logon_KMD { # KMD Logon v 3.0.0.0 New tmp splash winodow (ignore) # Class: WindowsForms10.STATIC.app.0.378734a # Text: 'Der indhentes logon oplysninger.' my ($UID, $PWD, $CICS) = @_; $UID ||= "T1SDP02"; # Def 'Brugernavn' $PWD ||= "abcd2222"; # Def 'Adgangskode' $CICS ||= "BCCICSTA"; # Def 'System' my (@logon, @result, $status); # .NET 1.1 component (proc: "KMD\.YH\.KMDLogonNET\.exe") # my $c_logon = "WindowsForms10.Window.8.app3"; # ClsName:'Log på KMD' Win # my $c_edit = "WindowsForms10.EDIT.app3"; # ClsName:'User/Pass' Edit # my $c_combo = "WindowsForms10.COMBOBOX.app3"; # ClsName:'System' Combo # .NET 2.0 component (proc: "KMD\.YH\.Security\.Winform\.Logon.exe") my $c_logon = "WindowsForms10.Window.8.app.0.378734a";# ClsName:'Log på KMD' Win my $c_edit = "WindowsForms10.EDIT.app.0.378734a"; # ClsName:'User/Pass' Edit my $c_combo = "WindowsForms10.COMBOBOX.app.0.378734a";# ClsName:'System' Combo TRY: for my $i (1..10) { # Grab logon window @logon = FindWindowLike(undef, "^Log p", $c_logon); if (not @logon) { print "\tScanning for Logon popup...\n"; sleep($i); } else { @result = (); # clear # Enter userid, password set_front_win($logon[0]) or warn "Can't activate: $logon[0]...\n"; my @UidPwd = FindWindowLike("$logon[0]", "^.*", $c_edit ); if (not @UidPwd) { warn "\tCan't find user/pwd edit...\n"; } push @result, WMSetText($UidPwd[1], $UID); sleep(1); push @result, WMSetText($UidPwd[0], $PWD); sleep(1); # Select cics my @system = FindWindowLike( "$logon[0]", "^.*", $c_combo ); if (not @system) { warn "\tCan't find System combobox...\n"; } my ($l,$t,$r,$b) = GetWindowRect( $system[0] ); MouseMoveAbsPix( $l+10, $t+10 ); sleep(1); SendMouse( "{LEFTCLICK}{LEFTCLICK}" ); sleep(1); push @result, SelComboItemText($system[0], $CICS); sleep(1); # Assert valid entries print "\tField check: >@result<\n"; foreach my $r (@result) { next TRY unless $r; } # Push 'OK'; - and return true for my $j (1..3) { set_front_win($logon[0]) or warn "Can't activate: $logon[0]...\n"; # SendKeys("{TAB}"); sleep(1); PushChildButton($logon[0], "OK"); sleep(3); @logon = FindWindowLike(undef, "^Log p", $c_logon); last if ! @logon; }; if (@logon) { warn "\tRetry $i...\n"; next TRY; } # Handle logon comm-errors (KWS, CICS) my @error = FindWindowLike( undef, "^Fejl under ExtranetLogon2" ); if (@error) { PushButton("OK"); sleep(5); } # &OK else { $status = 1; } last TRY; } } print "\tKMD\.YH.Security\.Winform\.Logon.exe: " . ($status ? "assuming OK" : "ERROR!"). "...\n"; return $status; } ### ---------------------------------------------------------------------------- ### logoff_KMD ### ---------------------------------------------------------------------------- sub logoff_KMD { if ( ! logon_state() ) { return 0; } print "\nLogging off KMD Logon...\n"; # --- The polite way (please...?) if ( logon_state() ) { print "\n\tLogoff using KMD Logon UI\n"; my $Win = 'KMD Logon'; my @logoff = FindWindowLike( undef, "^$Win" ); ShowWindow($logoff[0], SW_SHOWNORMAL); set_front_win($logoff[0]) or warn "Can't activate: $logoff[0]\n"; PushChildButton($logoff[0], 'Log af'); sleep(3); SendKeys("%{F4}"); sleep 3; # Alt-F4: close window } # --- The hard way... (Hasta la vista, baby!) #if ( logon_state() ) { # my $log = scan_proc("KMD\.YH\.KMDLogonNET\.exe"); # .NET 1.1 my $log = scan_proc("KMD\.YH\.Security\.Winform\.Logon.exe"); # .NET 2.0 if ($log) { print "\n\tKilling Logon.exe process: $log\n"; kill_proc($log); } #} return 1; } ### ============================================================================ ### MAIN ### ============================================================================ =cut # ----------------------------- TEST ------------------------------------------- my $log = scan_proc("KMD\.YH\.Security\.Winform\.Logon.exe"); $log and kill_proc($log); my $path = "C:\\Projects\\KMD.NI.EDagpengeSygdom\\KMD.NI.DPSagsbehandler"; $path .= "\\KMD.NI.DPSagsbehandler\\3PartyComponentsNet20"; my $prog = "KMD\.YH.Security\.Winform\.Logon.exe"; start_proc($path, $prog); if ( ! logon_state() ) { logon_KMD("T1SDP02", "abcd2222", "BCCICSTA"); logon_state(); } =cut # ------------------------------ PROD ------------------------------------------ if ("@ARGV" =~ /ON/i && !logon_state() ) { my ( $on, $usr, $pwd, $cics) = @ARGV; # Grab cmd.line args (override) $usr ||= "T1SDP00"; # Default to eDagpenge logon $pwd ||= "abcd2222"; $cics ||= "BCCICST8"; logon_KMD($usr, $pwd , $cics); } if ("@ARGV" =~ /OFF/i ) { logoff_KMD(); }