drabelink Absent Member.
Absent Member.
2253 views

Reflection IBM 2014: close sessions programatically

Hi,

Our application automatically starts several sessions when the application starts, using command line:

Attachmate.Emulation.Frame.exe" -f "RIBM3270.rd3x" -ipcname K -uimode classic -N
Attachmate.Emulation.Frame.exe" -f "RIBM3270.rd3x" -ipcname L -uimode classic -N

This automatically starts a K and L session.

The application is a non-.NET application. It is pure Win32.

To control the sessions we use HLLAPI to connect and interact with the sessions.


The issue we have is when our application closes, it should automatically close the sessions. The session windows and processes must be closed.

We could not find a way using somekind of API to do this. Maybe there is a command line switch to close a particular session, but could not find such an option.

So we implemented this:

We know the window title of each started session.
Using WInAPI we get the window handle and send a WM_CLOSE to it.

This seems to work, but only when there are no other windows open in the session. When a error msgbox is displayed in the session, the close does not work.
So we get all opened windows within the session, find error msgboxes and WM_CLOSe them. Afterwards we send WM_CLOSE to the main session window.

BUt this is really not efficient and prone to errors.
When the session is starting for example, the title is not yet set to the window.
Also the title could be changed, which breaks this implementation.

What would be the best way for us to achieve the need to close sessions?

Be aware that we do not have a .NET application. We can use ActiveX/COM, but not .NET assemblies directly.

Any hint or tip is appreciated.

Best regards,
Dave
0 Likes
7 Replies
vfast Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Wow, so many things to mention...

First, if you are still using Reflection 2014, ditch that and get the latest build of Reflection Desktop which is 16.1, plus a couple of service pack releases beyond that. If for no other reason, do it for the security fixes that go into each release.

You can start Reflection on the command line as you have shown, but I would not recommend it, as it does not offer any control for for you after starting the session. And BTW, the -ipcname option does not refer to the HLLAPI short name the session will have. Don't bother with setting a custom -ipcname.

Reflection provides a complete COM interface that matches (almost) the .Net interfaces - this is what you would use if programming in Reflection VBA, or Excel VBA, etc. Documentation for this is on the Help menu, and there are a lot of great examples too. Here is the most recent editon: http://docs.attachmate.com/reflection/16-1-1/vba-prog-guide/

You can also use this COM interface in VBScript files, which beat .bat files any day. Here is an example of how to open a session using VBScript...you can copy this to a .vbs file and just run it...or ShellExecute it from your app:

dim reflection, terminal, frame, view
set reflection = CreateObject("Attachmate_Reflection_Objects_Framework.ApplicationObject")
set terminal = reflection.CreateControl("C:\Users\<name>\Documents\Micro Focus\Reflection\Mainframe.rd3x")
set frame = reflection.GetObject("Frame")
set view = frame.CreateView(terminal)
frame.Visible = true

You can't set the sessions to be in "Classic" UI mode specifically this way, so make sure that option is set before you start. You can still open multiple windows this way, which is much less efficient but some people like it.

To close all sessions programmatically, open in separate Reflection Workspace windows, you will need to get access to each running application object in script, then invoke its Close method. We have an example of getting access to all application objects, but it is a VBA example, not VBScript, but I think it would not be too difficult to adapt. https://support.microfocus.com/kb/doc.php?id=7022995
0 Likes
drabelink Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

vfast;2484841 wrote:
Wow, so many things to mention...


Thanks for your valuable info.

I will investigate your suggestions !!

Regards,
Dave
0 Likes
vfast Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Here is a VBScript you can run that will close all sessions in all Workspace windows.


const CloseAlwaysSave = 3
dim reflection, i
i = 0
on error resume next
do while true
i = i + 1
set reflection = GetObject("Reflection Workspace")
if err = 0 then
reflection.Close CloseAlwaysSave
Wscript.Sleep 1000 'wait for R to get closed
else
err.clear
exit do
end if
loop
0 Likes
TomFitz Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Hi Dave,

assuming you are using the before connect event to parse the command line, so you can pull out the -ipcname and hence set you HLLAPI shortname.

You could also use append extra information to that parameter which you could use later to close the session and the hosting workspace. In particular I'm thinking of the OLEServerName, by default it's RIBM, but if you have several sessions open then you nee to be able to ind the one your want to close quickly. By session the OLEServerName to something specific, the you can do a GetObject on the unique string and then you can close it using the legacy RIBM API.

e.g. command line to launch

Attachmate.Emulation.Frame.exe" -f "RIBM3270.rd3x" -ipcname K_SessionK -uimode classic -N

In your ProjectLegacy VBA project drop the following routine into ThisSession

Sub SetOLEServerName()
ThisSession.OLEServerName = ThisSession.MacroData
End Sub

now modify your Before_Connect event handler parse out the "L" and the "SessionK" from your -ipcname parameter.

Then after you have set the HLLAPI name, you can execute ThisSession.SetOLEServerName SessionK using

ThisIbmTerminal.Macro.RunLegacyReflectionMacro "ThisSession.SetOLEServerName", MyOLEName 'Where OLEServerName is the name you have parse from the -ipcname

At this point you have an OLEServerName you can use with GetObject in your application, or in VBScript etc. to close the Terminal Session

So you can

Dim myReflectionSession as Object
Set myReflectionSession = GetObject("SessionK")
myReflectionSession.Quit

End Sub

This will also close your workspace if you have the "Exit workspace when last document closed" checkbox checked in the workspace settings.



If you don't have the "Exit workspace when last document closed" checkbox checked, then you can simply set the AutomationServerName property on the Application object to something unique and then once you have closed your terminal session as above, you can do a GetObject on the Workspace and close it as demonstrated in the earlier reply from vfast.

e.g. In BeforeConnect

Application.AutomationServerName = "HelloDave"

and then in your app,

Dim MySessionKWorkspace as Object
Set MySessionKWorkspace = GetObject("HelloDave")
MySessionKWorkspace.Close 1 'ApplicationCloseOption_CloseNoSave = 1
Naturally, you'll want to set the ApplicationServerName to something including the L or the K so you know which one you are closing, but hopefully you'll see what I'm trying to do above.

This should allow you to safely close only the two sessions (and associated workspaces) which you are using with your HLLAPI application

Tom
0 Likes
drabelink Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Nice suggestions. I'm currently implementing this and will test.

Best regards,
Dave
0 Likes
drabelink Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Hi,

I have implemented the suggestions. And this works almost perfectly.

Indeed, by changing the COM server name, I can get the object and close or quit it from the application.

But there is one major issue:

When starting the session, it takes a while before the name is set. The processes need to get alive and the Before_Connect event handler is executed not immediately.

On my system it can take 10-20 seconds before the session COM server name is chaged in the Before_Connect event handler.

This is ok when the user of our application is working normally. But there are occasions when the user after login to the application immediately closes it.
That means that while the sessions are being started and not yet have changed the names, the application tries to find the COM server object but can not find it.

Having a nice tool like rotview:

http://alax.info/blog/1444

you can actually see that when a sessions starts, first the Reflection WOrkspace COM object is created.
Way after the session COM object.

I think that the best way here is to have the Reflection Workspace COM name changed and used for searching.
But the COM name here is also changed much later.

My question is:

Is there a way that i can set the default Reflection WOrkspace name to my own fixed name?
So that when the session starts, the first object to become active is the workspace having the custom name.

It should be a setting within RIBM3270.rd3x file I think, but can not find it.
It can only be changed using a VBA script on Before_Connect event handler.

But that is much too late. The workspace should initially start having the custom name i want.

Any suggestions?
0 Likes
TomFitz Absent Member.
Absent Member.

Re: Reflection IBM 2014: close sessions programatically

Hi Dave,

The AutomationServerName is the ROT entry for the Workspace (attachmate.emulation.frame.exe) and the OLEServerName is the ROT entry for the Terminal Session (R1Win.exe, R2Win.exe or R8Win.exe) which is running inside the wokspace.

The only way to set the AutomationServerName in a file is if you use a layout file, this is normally used to launch multiple sessions in a workspace, and it store window position size etc.

You can set the AutomationServer name via the GUI by going "File" | "Settings" | "Layout Settings"



The alternative would be to add a routine to the Common Project, and have that execute when an empty workspace is launched. i.e. tale the .rd3x file out of the command line.

I your workspace settings go to the configure Defaults, and set the startup action to execute a macro in the Common project



In project common you part out the command line parameters and set the Automation servername as appropriates and then launch your session or (if no HLLAPI name is specified) prompt for a file to open.

Sub SetAutomationServerName()
'Parse the Commandline
':
':
'Now I have my launch parameters
If MyHLLAPIShorNameFromCommandLine = "K" Then
Application.AutomationServerName = "K_WasHere"
OpenMySession
ElseIf MyHLLAPIShortNameFromCommandLine = "L" Then
Application.AutomationServerName = "L_WasHere"
OpenMySession
Else
PromptForOpenSession
End If
End Sub


Sub PromptForOpenSession()
Dim myApp As Object
Set myApp = GetObject(Application.AutomationServerName)

Dim myFrame As Object 'Attachmate_Reflection_Objects.frame
Dim myTerminal As Object

Set myFrame = myApp.GetObject("Frame")
myFrame.Visible = True

Set myTerminal = myApp.CreateControl2("09E5A1B4-0BA6-4546-A27D-FE4762B7ACE1")

Dim myOpen As New Attachmate_Reflection_Objects_Emulation_IbmHosts.InputMapAction

myOpen.ActionId = 43 'OpenActionID
myTerminal.Execute myOpen
myTerminal.Close 1
End Sub


Sub OpenMySession()
Dim myApp As Object
Set myApp = GetObject("Reflection Workspace")

Dim myFrame As Object 'Attachmate_Reflection_Objects.frame
Dim myTerminal As Object

Set myFrame = myApp.GetObject("Frame")
myFrame.Visible = True

Set myTerminal = myApp.CreateControl2("09E5A1B4-0BA6-4546-A27D-FE4762B7ACE1")

Dim myOpen As New Attachmate_Reflection_Objects_Emulation_IbmHosts.InputMapAction

myOpen.ActionId = 43 'OpenActionID
myOpen.AddParameter "C:\Users\TomFi.ATTACHMATE\Documents\Micro Focus\Reflection\RIBM3270.rd3x"
myTerminal.Execute myOpen
myTerminal.Close 1
End Sub


I appreciate this is quite cumbersome and may still prove problematic is the use closes your in-house app before the Workspace has been loaded, it might be easier to use ShowWindow (from User32.dll) to Hide the Workspace if the user triggers the exit routine your in-house App and wait for your Before_Connect routine set the OLEServerName in Reflection, and then close Reflection before exiting your application.
Regards,
Tom
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.