in reply to Interact with mainframe screen

I automate 3270 applications from Perl by using the IBM Personal Communications 3270 terminal emulator on Win32 via Win32::OLE. It is very well documented and it works very good.

As an alternative if you are not on Win32, consider looking into s3270 resp. x3270 for automating your program, but these do not provide the good API that IBM does.

Here is a short extract I use to initialize and start a session:

package Host::PCOM; use strict; use Carp qw(croak carp); use Logger; use Win32; use Win32::OLE; Win32::OLE->Option( Warn => 3 ); sub new { my ($class,$connection_name) = @_; my $self = {}; bless $self, $class; $self->log("Creating connection manager"); my $connmgr = Win32::OLE->new("PCOMM.autECLConnMgr") or die "Couldn't create PCOMM.autECLConnMgr : $!\n"; $self->log("Creating session"); my ($session) = Win32::OLE->new("PCOMM.autECLSession") or die "Couldn't create PCOMM.autECLSession $!\n"; # Now connect the session my $session_info; $session_info = $connmgr->{autECLConnList}->FindConnectionByName($co +nnection_name); unless ($session_info) { $self->log("Personal Communications not found running. Starting se +ssion"); #my $hostname = Win32::NodeName; my $hostname = 'WSConfig'; $connmgr->StartConnection("profile=$hostname connname=$connection_ +name"); my ($count) = 20; while (! $session_info and $count--) { $connmgr->{autECLConnList}->Refresh(); $session_info = $connmgr->{autECLConnList}->FindConnectionByName +($connection_name); #sleep(2); select undef, undef, undef, 0.5 unless $session_info; }; sleep(5); }; die "Couldn't find or start session $connection_name\n" unless $session_info; $session->SetConnectionByHandle( $session_info->{Handle} ); my $ECLOIA = $session->autECLOIA(); die "Couldn't get ECLOIA : $!" unless $ECLOIA; my $ECLPS = $session->autECLPS(); while (! $session->Started) { $ECLPS->Wait(500); }; if (! $session->CommStarted) { $session->StartCommunication; while (! $session->CommStarted) { $ECLPS->Wait(500); }; }; $self->{conn} = $connmgr; $self->{session} = $session; $self->{ecloia} = $ECLOIA; $self->{eclps} = $ECLPS; $self; }; ... much domain specific code following which I won't post ...

Replies are listed 'Best First'.
Re^2: Interact with mainframe screen
by jeepj (Scribe) on Mar 05, 2008 at 11:42 UTC

    The documentation on available classes and methods for IBM Personal Communications 3270 through OLE is available on IBM site.

    Hope this can help someone, as I used it a lot to implement something equivalent to what Corion did.

Re^2: Interact with mainframe screen
by huzeh (Initiate) on Jun 30, 2007 at 09:25 UTC
    Hi, I am very interested in your solution of using OLE for perl access to the mainframe. I am trying to extend our (AIX/Windows based) environment for automated testing to the mainframe area. I have started work on a perl module that uses the Expect module on AIX to use the tn3270 emulator. But I think your approach is much better. I will try and see if I can use it with the 3270 emulator in our environment. The piece of code that you posted shows that it is a Host::PCOM module. Is it freely available? From your statement at the bottom I guess it is not. Is there a possibility for you to strip out the specific parts for your environment and publish the generic parts? I would be pleased to use it as a basis for further development and to help make this a general available perl module.

      No. Host::PCOM is a module I developed on the time and entirely for my employer. I don't feel it would be right to redistribute that code on my own, and I won't take it on me to involve the lawyers to get a release from my employer.

      That being said, it's not really hard to encapsulate the OLE API, as IBM provides plenty of good documentation.

        I don't feel it would be right to redistribute that code on my own, and I won't take it on me to involve the lawyers to get a release from my employer.
        You might find "How to convince a client to release Perl code to CPAN?" helpful to get your employer to release the code... ;-)

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re^2: Interact with mainframe screen
by Anonymous Monk on Apr 20, 2007 at 13:39 UTC
    Thank you for this bit of code... Everyone is so helpful in here. I will let you know how it goes. Thanks again everyone! Sincerely, Paul
Re^2: Interact with mainframe screen
by Anonymous Monk on Apr 20, 2007 at 13:53 UTC
    Could specify where I would use my login information to log into the mainframe? Im guessing $connection_name = login and password? Whats the exact syntax? and what is $profile, is it a file it reads from or is it a variable I assign?

      The above code is only the package to launch the connection to the 3270 window, not to give any input to it. I recommend that you read the documentation that accompanies IBM Personal Communications to find out how to automate stuff within it. I won't post my complete code as much of it belongs to my employer I guess. You will then need to employ the methods to read what is on the screen and which fields are available for input. For example, I have the following subroutine in Host::PCom:

      sub screen { my ($self) = @_; my ($cols,$rows) = ($self->cols,$self->rows); my ($line) = $self->eclps->GetTextRect(1,1,$rows,$cols); my @lines; while ( $line =~ s/(^.{1,$cols})//sm) { push @lines, $1; }; s!\0! !g for @lines; # Mark fields as dirty $self->log("Fields marked dirty"); $self->{fields} = undef; push @lines, $line if $line; @lines; };

      It returns the current screen (resp. a cached version of it) as a list of scalars which my programs then check. I also have two routines for getting and setting input fields:

      sub get_set_field { my $self = shift; my $field = shift; my $result; if (defined wantarray) { $result = $field->GetText(); $self->log("value is $result"); carp( "get_set_field() called in void context without a value",2 ) + unless @_; }; if (@_) { $field->SetText(@_); $self->log("Setting field to @_"); }; $result; }; sub field_by_index { my $self = shift; my $index = shift; my @fields = $self->fields; my $field = $fields[ $index ]; $self->get_set_field($field,@_); };
        Hello, I have learned a ton about OLE from you guys but there is very little documentation on the internet about OLE as it pertains to PCOM so there arent may examples to study. Corion, yours is a great example but I have a few issues.

        1. package Host::PCOM; #<-what is the signifigance of this?

        2. my ($class,$connection_name) = @_; #<- changed this to $class = "pcsws" and $connection_name = "P"

        3. my $hostname = 'WSConfig'; #<-changed this to $hostname = "MFrame1.ws"

        So I can spawn the PCOM session successfully. But I get errors when I try to read the presentation space. I think the problem is that I dont know exactly what parameters to send to the screen sub for @_. I tried hard coding @_ to lots of different values, just guessing at it. Can you tell me what parameters you are passing to the sub. Error message below.....

        Error message - "Can't locate object method "cols" via package "P" (perhaps you forgot to load "P"?) at C:\(path snipped)\MFtest.pl line 76."

        4. my ($self) = "@_"; #<-What value is expected from @_?

        Thanks in advance for your help.

        So does this mean we need IBM Personal Communications in order for this to work? How much would this software cost?
Re^2: Interact with mainframe screen
by Anonymous Monk on Jun 26, 2007 at 15:00 UTC
    Thanks for the script and pointing out the COM interface to IBM's Personal Communications. I doubt I would have been able to complete a project at work w/o your post...hacker in SD.