C# question

chipke

New Member
Hello,

I have a little question about Progress. I have created a simple dll for Progress. (made in C#).

THE DLL: (Bankterminal application)
1. connect with a serial port
2. send an amount to pay
3. retrieve money
4. retrieve result

Now, I want to fire an event in C#, that fires an event in Progress every time I get a resultmessage from the BankTerminal. (there are 5-10 result messages from the BankTerminal, like ACK, NAK, ENQ,...)
an Event.

1. Is there anybody that knows how to expose a delegate in C# to the com object viewer from Progress? Because I can't see my delegate in the Progress Object Viewer.

2. How can I use the delegate in Progress to fire a certain procedure everytime the DLL fires an event?


Kind regards,
Tom
 

lloydt

New Member
Hey Tom,

If I understand you correctly, you want to capture a trigger event in the progress session based on your .net com object. Based on that, it's not possible with today's progress. My understanding is that in order to do that, the com object needs to have a certain type of signature, and .net com objects do not have that type of signature. I think it's due to ole / com+ vs com automation. At any rate, there's a couple knowledge base entries out there covering it and I believe one or two entries on here.

I believe 10.1.C (maybe a later version) is supposed to support .Net natively in which case this may well no longer be an issue.

One thing you may be able to do is to use Sonic and communicate with progress that way, your .Net event could throw a message in a queue and the progress app would see it.

The only problem with Sonic may be the licensing / $$$, not sure how that would work out if you have a psdn license. MSMQ is free, but you run into the same event / com issue. :mad:

Regards
 

chipke

New Member
Thank you for your fast respons. Idd I want to trigger an event from my component to Progress.

It's not a big problem because I used a while loop in Progress to read those variable with a wait function. This works great ofcourse. No memory problems, no cpu problems. But my colleage told me that this is not the appropriate programming technique for in Progress. It could give me some disadvantage in stability in time. The application is very critical because if a person can not pay, others have to wait. If persons wait too long, they don't buy.

If anybody else has a possible solution or any ideas are ofcourse welcome in this topic.


Kind regards,
Tom
 

lloydt

New Member
One other solution that may work for you if you are on progress 10 is to set up a proxygen and call a progress program on the back end via that, all it requires is an appserver. I use that approach in a couple applications and it works great.

Regards
--Lloyd
 

chipke

New Member
Hey LLoydt,

Ok and what is a proxygen in this case?
I use Progress 101B.
Can you give a little example, some more information please?

Thanks in advance,
Tom
 

lloydt

New Member
basically a proxygen is a means to run code as well as send and retrieve data with a progress database via appserver or webservice. FWIW I've found the appserver to be most useful, be sure to set it up as stateless though, otherwise weird things happen. Using prodatasets makes this really cool because they map to .net datasets and tie to .net data controls.

One performance tip I can give is to start your connection to the appserver broker at the beginning and let it run for the entire .net session. ever procedure call into the proxygen dll's will connect to available servers and disconnect when done (stateless nature of appserver), your broker connection won't take up connections on the server and with it running for the entire session you will have better performance, i.e. no time waiting to connect and build objects, etc. My apps had a pretty big boost in speed when doing this.


An introduction to the concept can be found here

http://www.psdn.com/library/servlet/KbServlet/download/1170-102-989/dvnet.pdf

And this is a link to demo code on the psdn site.

http://www.psdn.com/library/entry!default.jspa?categoryID=41&externalID=273&fromSearchPage=true

if the links don't work, search on dvnet.pdf and tips.zip at psdn.com

Regards
Lloyd
 

chipke

New Member
Hello,

I have done some tests with Visual Studio.NET. (C#)
I created an easy procedure like follows: (PROGRESS)

/* Test.p */
PROCEDURE ShowMe :
DEFINE INPUT PARAMETER cInput AS CHARACTER.
DEFINE OUTPUT PARAMETER cOutput AS CHARACTER.
ASSIGN cOutput = cInput + " --- " + cInput.
END PROCEDURE.

Then I saved the procedure and I created with the proxy generator tool a myprog.xpxg extension. Then i created with the bproxygen a dll file called myprog.dll in the namespace PSDN.

Then I added following code to my solution: (IN C#)
using Progress.Open4GL.Proxy;
using Progress.Open4GL;
using Progress.Open4GL.Exceptions;
using PSDN;

publicstaticConnection conn;
conn = new Progress.Open4GL.Proxy.Connection("tovp", "", "");
MyProg ts = newMyProg(conn);

I get the following error when adding the last line. (the line before doesn't give a problem)
{"Connectie Error: Application Service MyProg Unknown with NameServer on Host mypcname Port 5162. (8234) "}
==> nosuchappserviceexception
Do I have to register something? I don't know how to fix that error?

Kind regards,
Tom
 

chipke

New Member
Ok, I found my mistakes.

First of all I cannot add:
PROCEDURE NAME:
DEFINE INPUT PARAMETER cInput AS CHARACTER.
DEFINE OUTPUT PARAMETER cOutput AS CHARACTER.
cOutput = "OUTPUT " + cInput.
END.

I have to do it like follows:
DEFINE INPUT PARAMETER cInput AS CHARACTER.
DEFINE OUTPUT PARAMETER cOutput AS CHARACTER.
cOutput = "OUTPUT " + cInput.

My connection string was totally loss...
It has to be:
Connection conn = newConnection("AppServerDC://localhost:3091/", "", "", "");

The following works like a charm:
TestProc tp = newTestProc(conn);
tp.ShowMe(
"hello world", out strOutput);
 

chipke

New Member
Is it possible to access a structured procedure from C#?
Is it possible to access a .w form (inside procedure, for changing data) from C#?

I don't think so, do I overlook something?

Kind regards,
Tom
 

lloydt

New Member
Is it possible to access a structured procedure from C#?
Is it possible to access a .w form (inside procedure, for changing data) from C#?

I don't believe it's possible to access a .w form, the proxygen serves the purpose of exposing the Progress database and functionality as a backend and allows for setting up an n-tier/n-layer approach with the data access and potentially the business logic on that side of the fence so to speak.

Regarding the structured procedure, I've never attempted it but I've got to wonder if it is possible, I could see that one going either way and maybe someone else a little more knowledgeable than I could shed some light.

Regards
 

chipke

New Member
Ok then I have another possible solution. I thought, but I think it's not possible.

I could add a row in a table (Progress) in C#. Trigger with a session trigger in Progress an on create. But that doesn't work either.

The following code:
CREATE "ClassLibrary1.TestProgressCreateTable" hHdl.

Creates an instance of my DLL. Adds a row to my tmp table with proxygen. (row is added, but Progress doesn't triggers the rowchange) Maybe a database trigger? But then, I have to generate the database trigger inside my Progress application. (the event fired function) (on create of tmp) and that is not possible. When I add a database trigger, C# crashes. Also not possible. Shade!


E.g. code:
DEFINE BUTTON btnTest LABEL "Test".
DEFINE BUTTON btnHandle LABEL "HANDLE test".
DEFINE FRAME f-head btnTest btnHandle.
DEFINE VAR hHdl AS COM-HANDLE.

/* Triggers */
ON 'CHOOSE':U OF btnTest
DO:
CREATE tmp.
ASSIGN tmp.cStatus = "event fired".
END.
ON 'CHOOSE':U OF btnHandle
DO:
CREATE "ClassLibrary1.TestProgressCreateTable" hHdl.
END.
ON CREATE OF tmp
DO :
MESSAGE "event fired" VIEW-AS ALERT-BOX.
END.

/* */
DISPLAY btnTest btnHandle WITH FRAME f-head.
ENABLE btnTest btnHandle WITH FRAME f-head.
WAIT-FOR CHOOSE OF btnTest.

FOR EACH tmp NO-LOCK:
DISPLAY tmp.cStatus FORMAT "X(20)".
END.
FOR EACH tmp EXCLUSIVE-LOCK:
DELETE tmp.
END.

Anybody an idea?

Regards,
 

dwedgbury

New Member
lloydt,

With regards to one single session long connection:

We do a similar thing in our C# web services - we create a static instance of the connection object when the web service is started.

This does work well until the connection to the appserver gets severed for whatever reason. To re-establish the connection, the web service application needs to be restarted. Otherwise the next attempt to run a .r on the appserver via the proxy dll results in an extruciating long delay before an exception is thrown.

I've not been able to find a way to check programmatically if the connection is ok!? Am I missing something obvious. Visual Studio intellisense reveals loads of classes in the Progress namespace but where is the documentation?
 

lloydt

New Member
lloydt,


I've not been able to find a way to check programmatically if the connection is ok!? Am I missing something obvious. Visual Studio intellisense reveals loads of classes in the Progress namespace but where is the documentation?

One thing you may try is the NotAvailable property on the AppObject. I've not tried that before nor been concerned about the connection dropping itself, admittedly bad practice, but out of my control. I'm _guessing_ that would help... there is also a issessionavailable method on the AppObject as well. as far as documentation on this stuff, the best I can point to is PSDN.com and do some searches on .NET related terms. I think there were some links earlier in this thread that may give a good starting point.

Regards
 
Top