ActiveX/COM mit .NET

27/06/2008 - 12:43 von Marvin Massih | Report spam

ich habe eine Windows-Forms-Anwendung, die ich gern in eine alte
Nicht-.NET-Anwendung integrieren würde.

Diese Anwendung kann ActiveX-Controls einbinden; so habe ich etwa schon
den IE erfolgreich in diese Uralt-Anwendung integriert.

Wie aber bekomme ich jetzt meine Winform-Controls dort hinein?
Google sagte mir, man könne mit .NET kein ActiveX mit GUI bauen, aber
man könne Controls im IE anzeigen lassen. Wenn ich den dann wiederum in
meine Anwendung enbinden könnte, könnte das ja tatsàchlich funktionieren.

Hat jemand Beispielcode dafür?
Wie wird es in der Zukunft mit dieser Unterstützung sein? Wàre blöd,
wenn ich jetzt alles dafür umbaue und die nàchste IE-Version keine
WinForms mehr hosten kann. Da wàre es dann sinnvoller, die Controls
gleich als Webanwendung nachzubauen, aber das macht eben auch mehr Arbeit.



Lesen sie die antworten

#1 Frank Dzaebel
28/06/2008 - 09:51 | Warnen spam
Hallo Marvin,

ich habe eine Windows-Forms-Anwendung, die ich gern in eine alte
Nicht-.NET-Anwendung integrieren würde. [...]
Wie aber bekomme ich jetzt meine Winform-Controls dort [als
ActiveX-Controls] hinein?

[CodeProject: Exposing Windows Forms Controls as ActiveX controls.]

[Creating an ActiveX Control in Visual Studio 2005 - .Net Developement]

[COM Integration]

Beachte für die Redistribution, dass man hier nicht
RegSvr32 benutzen kann, um die ActiveX Controls zu registrieren, dann
würdest Du den klassischen Feher "DllRegisterServer entry point not found"
Fehler bekommen. Du müsstest schon regasm benutzen ... normal:

regasm MyControl.dll /tlb MyLib.tlb

Die weiteren Maßnahmen hier als Auszug:
The COM Interop works in both directions; the .NET Interop system acts as a
gateway between .NET components and COM Components, it makes the COM
component look like .NET component and a .NET component look like a COM
component. When a .NET object wishes to use a COM object, it uses a Runtime
Callable Wrapper (RCW). This is a .NET assembly that makes the COM object
look like a regular .NET object. When a COM object wishes to use a .NET
object the runtime creates a COM Callable Wrapper (CCW) that looks and works
just like a COM object.

In building a .NET component intended to be accessed from COM, we simply
check the Register for COM Interop checkbox on the project setting dialogue
box (setting the Register for COM interop option to True will create a type
library and make the correct registry entries for you.). Also, the .NET
project has to be a class library project to make it callable from COM. This
will result in a component that only supports late binding. I guess that is
not a problem at the moment. After all, it would avoid some versioning
problems and you won't get IntelliSense and of course you lose some
performance but hey! Let's get it working and consider performance L8R. ;)

During compiling (with all the above settings) you should have been notified
that only projects with strong names can be accessed from COM and will ask
if you would like to create a strong name for this assembly. Strong naming
is the feature that makes it possible for .NET to eliminate DLL Hell for
.NET components, alas, NOT with COM interop. You should have answered Yes to
the prompt? After you build the assembly it will be registered for access by
COM objects. A lot of .NET behind the scenes stuff occurs:

There should be an entry for the name of the object in
HKEY_LOCAL_MACHINE/Software/Classes key. Also, the ClassId of the object
should be there as well along with the type library entry under
HKEY_LOCAL_MACHINE/Software/Classes/TypeLib. So, to be complete COM expects
following in the Registry:

. The ProgIDs of each type I the binary
. The CLSIDs, LIBIDs and IIDs of all types
. An InProcServer32(DLL) that tells where the binary is

The command line Regasm (see below) updates the registry with info required.
The command line flags are important here! Regasm also registers and
generates the type library, which will be referenced in the VB6 client.

When you compile and run a COM Interop project VS.NET registration for the
DLL and type library is automatic and we don't really need to see it.
However, when deploying to a remote server things change. The DLL is not
converted through the Interop to 100% COM; there are limitations, that is
one of the many reasons why Regsvr32 can't be used.

The most promising however, is the use of Regasm.exe which is an assembly
registration tool used to register .NET assembly (managed code) as a COM
component (unmanaged code). It can register the DLL and the type library
(and unregister them too). The command lines should look like this:
Regasm ClassLibrayName.DLL - registers the DLL
Regasm ClassLibraryName.DLL /tbl - registers the type library

Regasm reads the metadata information within an assembly and adds the
corresponding COM-compatible registry entries.

Next we need to establish if the .NET DLL has a strong name or not. This has
probably been done inside VS.NET giving you a prompt (as above). So, from
this point, by using VS.NET we should have a strongly-typed DLL and type
library this needs to be copied to the directory of your choice and
registered using Regasm.exe (NOT regsvr32.exe.)
Note: I have tried the registration process on my laptop and it works no
problem. However, I can't get it to work on the (remote) server; it's
looking for System.Web.Services, or one of its dependencies - typical eh!.

It looks as though we need to add a GAC to the server.

Creating an assembly key file
The steps involved in adding an assembly to the GAC is not as simple as
adding the assembly to a web application. Since all applications can access
this library, some security precautions have been taken by Microsoft to
ensure uniqueness, version protection, and code integrity. This is achieved
by creating a strong name for your new assembly. A Strong Name consists of
the assembly identity and also a public key and digital signature.
To create a strong name, you use the syntax:

sn -k StrongNameFile.snk

(If your path environment variables isn't set properly, you'll have to go to
the C:\Program Files\Microsoft.NET\FrameworkSDK\Bin\ directory to run
Better still: The environment variables are set in a batch file called
SDKVARS.BAT at this location: C:\Program Files\Microsoft Visual Studio .NET
2003\SDK\v1.1\Bin. Run the SDKVARS batch file to set the paths for all the
.NET tools we need. This saves a lot of hassle - which is nice. :)

The filename "StrongNameFile.snk" can be anything you want of course. The
snk extension is used by convention.

Write/Edit your assembly
We now have our strong name for our assembly. To add this assembly to your
GAC, you need some special syntax. Before the namespace line, you have to
put a tag which will link your assembly key to this assembly, like so:
Imports System.Reflection

Namespace NameofWhatEver

Adding your assembly to your GAC
Phew!! We're almost done now. After you've created your strong name and your
assembly, compile your assembly as normal. To add your assembly to the GAC

gacutil /i BMS.RRTC.DLL and it can be uninstalled gacutil /u BMS.RRTC.DLL
(Notice that this is just the assembly's name. No extension).

Adding your assembly machine.config
We reach our final step and we shift our attention to the machine.config
file. The machine.config file is the configuration file for all the web
applications on the server. It is located at:

Locate the <assemblies> tag (which should be under
Between the <assemblies> tag, you should enter:
<add assembly="StrongFileName, Version=n.n.n.n, Culture=neutral,
PublicKeyToken=xxxxxxxxxxxxxxxxx" />

To get the information that goes into the assembly attribute, you can run
the gacutil /l command which will return a list of all the assemblies in the
GAC. You will have to look for the one you just added and copy the entire
line (minus the Custom=null part at the end).
If you have problems finding the assembly in the gacutil /l list, you can do
"gacutil /l > gac.txt" and it will put it all into a textfile, then you can
use notepad's find function.

Wie wird es in der Zukunft mit dieser Unterstützung sein? Wàre blöd, wenn
ich jetzt alles dafür umbaue und die nàchste IE-Version keine WinForms
mehr hosten kann. Da wàre es dann sinnvoller, die Controls gleich als
Webanwendung nachzubauen, aber das macht eben auch mehr Arbeit.

Für die Zukunft ist das Neuschreiben in .NET eher anzuraten,
auch wenn neue IE Versionen ActiveX Controls weiterhin hosten
werden können. Nur man wird u.a. sicher mit Security Issues zu
kàmpfen haben und die bekannten Probleme von COM sind
ebenfalls zu berücksichtigen.

ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]

Ähnliche fragen