views:

823

answers:

3

If I am looking to reference a .NET dll from PowerBuilder (10 or 11.5), which of the following is the best practice?

1) Register the dll as a COM Object, and use the COM Object via an OleObject 2) Upgrade to 11.5, and convert to PB.NET so that I can actually have blocks of C# in the PowerBuilder code 3) Another method

What are some things I should be aware of with these approaches?

+2  A: 

I haven't done anything with PowerBuilder, but this is the technique we followed (pretty successfully) with a project that could not immediately be migrated from VB6.

1) We created a shim/facade with COM references to expose the .NET items we needed. (We also specified the GUID's using attributes so we had complete control over compatibility changes.)

2) We referenced the COM objects in our VB6 code (as you would in the PowerBuilder code) using the built in object handling (OleObject in your case).

3) As items were migrated (in our case to C#), they referenced the underlying .NET classes instead of the COM shim. (We tagged the shim with Obsolete tags to ensure that nobody used it accidentally.)

4) After all references to the shim were migrated, we removed the shim. (We actually did that in two phases. In the first phase, we left the shim in but modified it to throw exceptions and log what information it could about the calls. That way we would have an idea about where any calls to it were being made from. After confirming that there were no problems, the shim was removed in the next phase.)

The advantage of this to us was that the migration could occur incrementally. We chose not to expose the underlying .NET objects directly because there was still some risk of them changing and we needed the COM interface to be as stable as possible.

Upgrading to PB.NET is certainly a possibility... but I don't know how complex that migration will be. You may find the time necessary would make the migration a major project (it certainly would have been for us).

Other methods which we considered, but rejected as inappropriate for our needs were:

  • Wrapping the .NET components in another application (a "service") and talking to those components via socket communication.

  • "Shelling out" to utilities using the .NET framework and transferring the information via (for example) a file based mechanism.

Things to be aware of include:

  • The threading model in use on both sides of the link. (We hosed ourselves at first because one part of the system ran MTA instead of STA - see this question for more information.)

  • What an exception on the .NET side will look like from your application. It may be a very unhelpful "generic" error, and may even appear to be in the caller instead of the .NET code. We added logging on the .NET side which gave a more verbose record of any exception before re-throwing it and letting the caller handle things as best it could.

I hope this helps. Good Luck!

Richard J Foster
I'd say this is the solution. To add to it, Bruce Armstrong did a series on wrapping .NET in COM for PowerBuilder (http://pbdj.sys-con.com/node/397016).
Terry
Thanks Terry. That article looks like it will cover most (if not all) of the PoweBuilder specifics I know nothing about.
Richard J Foster
Thanks for the help, guys!
RepDetec
+5  A: 

Things to be aware of:

The first approach (COM Wrapper) works with any version of PowerBuilder, including 11.5 and above when you only want to create a Win32 app. However, there are some limitations with regard to what you can actually do. The assembly has to be marked as COM visible. The methods you want to call have to be public. If the methods are overloaded, you may experience versioning problems down the road. Exceptions are an issue as well, you'll have to implement a hooking mechanism on the .Net side in order to capture detailed exception info.

The second approach not only required 11.5 and above, but it also requires that you compile your application as one of the .Net target types (e.g., WinForm). Given that you might need to make other modifications in order to support compiling as WinForm, you may find that a bit too much work just to be able to call this one assembly. On the other hand, if you're headed towards .Net targets, then you're set.

Bruce Armstrong
A: 

I'm actually facing the same problem at the moment. We use PB 11.5, but there's no way we'll move our app to a .NET target at this point, and doing .NET stuff (PowerScript#...) is not possible in native PB apps. So, I asked our local support for advice, and they replied Sybase's recommendation was to use PBNI:

  1. Create a PBNI project using C++/CLI (rather than standard C++)
  2. Use the C++ part to create classes you can use in PB
  3. Use the CLI part to access the .NET assembly

There's a good example project by Roy Kiesler at CodeExchange called PB2DOTNET. Will help you skip the first few steps (note that the code is not new, and you'll have to migrate both the native PB and PBNI stuff).

The downside of this approach is that it adds an intermediate level you have to maintain. However, the PBNI classes should merely be a thin wrapper around the .NET classes so that you can easily get rid of the PBNI part as soon as you upgrade to PB12.

eran