Laden...

.NET Control als ActiveX

Letzter Beitrag vor 18 Jahren 6 Posts 3.058 Views
.NET Control als ActiveX

Hallo!

Laut http://support.microsoft.com/default.aspx?scid=kb;en-us;311334 wird das ja allgemein nicht mehr unterstützt.
Allerdings findet man einiges darüber in div. Foren (auch hier). Deshalb hab ich mir gedacht, ich probier das einfach mal aus, was mir allerdings noch nicht gelungen ist.
Habe eine simple Klasse geschrieben, die noch nicht mal etwas von Forms beinhaltet. Trotzdem kommt wenn ich die Komponente im ActiveX TestContainer starten will, die Fehlermeldung: "Fehler beim Erstellen des Steuerelements: Unbekannter Fehler". Was kann der Grund dafür sein?


using System;
using System.Data;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace AXtest
{
	[GuidAttribute("6f1fa1d3-ec0a-43a5-8f61-e6daee906ec9") ]
	public interface myInterface
	{
		void doSomething();
	}

	[Guid("71456f5d-f045-42b7-941e-f1b3fd410424"), 
	InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
	public interface myEventsInterface
	{
	}

	[GuidAttribute("6f6e706f-8fa6-493e-becf-0ec9898e89dd"),
	ClassInterface(ClassInterfaceType.None),
	ComSourceInterfaces(typeof(myEventsInterface))]
	[ProgId("AXtest.dll")]
	public class myImplementation: myInterface
	{

		public void doSomething()
		{
		}

		#region com/interop		
		[ComRegisterFunction()]
		private static void RegisterClass ( string key )
		{ 
			StringBuilder sb = new StringBuilder ( key ) ;
			sb.Replace(@"HKEY_CLASSES_ROOT\","") ;

			RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);

			RegistryKey ctrl = k.CreateSubKey ( "Control" ) ; 
			ctrl.Close ( ) ;

			RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ; 
			inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ; 
			inprocServer32.Close ( ) ;

			k.Close ( ) ;
		}
		[ComUnregisterFunction()]
		private static void UnregisterClass ( string key )
		{
			StringBuilder sb = new StringBuilder ( key ) ;
			sb.Replace(@"HKEY_CLASSES_ROOT\","") ;

			RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);

			k.DeleteSubKey ( "Control" , false ) ;

			RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;

			k.DeleteSubKey ( "CodeBase" , false ) ;

			k.Close ( ) ;
		}
		#endregion
	}
}

ok, wenn man von System.Windows.Forms.UserControl erbt funktionierts ja...

allerdings hätt ich noch eine kurze Frage:
nachdem man die Komponente im TestContainer ausgeführt hat (und ihn wieder beendet) und man die Komponente neu erstellen will, kommt der Buildfehler dass die dll nicht in das Ausführungsverzeichniss kopiert werden kann, da sie von einem anderen Prozess verwendet wird. Wie kann man das unterbinden?

[Edit]
tja, der TestContainer beendet sich nicht richtig, was solls...

--> close/remove thread
[/Edit]

Hehe, genau das Thema hatte ich letzte Woche bei uns in der Firma.

Unsere Software ist noch zum großen Teil in C++ geschrieben und kann ActiveX Controls laden um die dann auszuführen und dem Benutzer damit arbeiten lassen zu können. Im Prinzip ne MDI Anwendung wo man sich die angezeigten Fenster per Drag' n Drop hinzufügen kann in Form von ActiveX Controls. - Das gleiche wollen wir jetzt auch für .Net User Controls bieten

Und .Net Controls als ActiveX Controls agieren zu lassen geht nicht, auch nicht nach deiner Methode, so hatte ich es auch versucht. Es sind einfach keine vollwertigen ActiveX Controls - auch wenn der Test Container die wegen dem COM Interface ausführt.

Naja, der .Net als ActiveX Ansatz ist rausgeflogen, haben welche bei uns was anderes geschrieben (weiß nicht genau wie sie des gelöst haben) und nun kann man in unsere Anwendung auch ganz normale .Net User Controls per Drag'n Drop einfügen obwohl die eigentliche Anwendung noch altes C++ ist 🙂.

Baka wa shinanakya naoranai.

Mein XING Profil.

instabil

Ich halte es für gefährlich, Bastellösungen in produktive Software einzubauen. Das Beispiel mit dem C++ Programm macht klar, warum es von Microsoft nicht unterstützt wird. Ein Mixer ist eben kein Kühlschrank, auch wenn ich ihm eine viereckige Tür anschraube. Mit .NET lassen sich definitiv keine vernünftigen ActiveX-Controls erzeugen. Also muss man das gute alte VB6 auspacken. Solange es COM gibt, sollte man VB6 lieber noch nicht ganz einmotten.

Eine andere Möglichkeit ist die API-Funktion SetParent. Damit können .NET Formulare innerhalb von beliebigen fenstern oder Controls (alles was einen eigenen Fensterhandle hat) gezeichnet werden. Wir haben z.B. in der Firma ein .NET Form ohne Rahmen mit SetParent und MoveWindow auf einer Registerkarte eines Access 2000-Formulars angezeigt. Mit VB6 ist schnell ein allgemeines CaptureWindow-ActiveX-Control gebaut, mit dem man seine .NET Formulare quasi als Controls überall einbetten kann.

hey, danke! Ist zwar nicht das was ich hören wollte, aber wichtig.

ok, also anders. Der VB6/SetParent-Ansatz gefällt mir.
Rainbird, könntest du mir vielleicht ein Beispiel geben, wie das mit SetParent funktioniert?
(ich habe keine Ahnung von VB)

ich hab das auch mal versucht, bei uns .NET entwicklungen auf COM zu portieren, bin aber auch gescheitert. Man kann einfach keine Garantie abgeben, dass die Controls in einer COM umgebung funktionieren. Im Detail bin ich dann an den Events gescheitert.