Laden...

ActiveX OCX oder "echte" DLL mit C# erstellen

Erstellt von tobias279 vor 19 Jahren Letzter Beitrag vor 19 Jahren 9.314 Views
T
tobias279 Themenstarter:in
16 Beiträge seit 2004
vor 19 Jahren
ActiveX OCX oder "echte" DLL mit C# erstellen

Hallo!

Ich bin neu in der Sparte C# Programmierung!
Meine Aufgabe ist es eine DLL zu erstellen, die von einem Externen Programmg genutzt werden soll! Der Code funktioniert schon (hab ich als .exe-Projekt schon ausprobiert!). Jetzt ist mein Problem, das wenn ich eine DLL erstelle, ich sie nicht in das externe Programm einbinden kann (Fehler:"Das OLE Control konnte nicht registriert werden").
Wie erstelle ich jetzt ein OLE Control mit C#???

MfG
Tobias

333 Beiträge seit 2004
vor 19 Jahren

Der Weg führt nur über COM. .NET-Bibliotheken sind ansonsten auch nur mit .NET-Anwednungen kompatibel. Es gibt im Internet zahlreiche Beispiele zur Thematik ActiveX und .NET. Mit relativ wenig Mühe lässt sich ein vorhandenes Control als ActiveX-Steuerelement einsetzen. Hier ist eines von vielen Beispielen.

([bb]|[^b]{2})

T
tobias279 Themenstarter:in
16 Beiträge seit 2004
vor 19 Jahren

Danke dafür!
Konnte die Dll zwar eibinden, aber da steht als Datei nur mscoree.dll! Meine Datei heißt aber anders!
Konnte die DLL auch nicht im Testcontainer testen, weil ein unbekannter Fehler aufgetreten ist!

Weißt du vielleicht noch mehr??

MfG
Tobias

333 Beiträge seit 2004
vor 19 Jahren

Also das bei deinem ActvieX-Fähigen .NET Control etwas von mscorree.dll steht hat nix weiter zu bedeuten. Warums net funktioniert kann ich so aber net sagen. Probleme gibts da öfters. Ich häng dir einfach mal ein Beispiel an. Der AssemblyName sollte "ActiveXExample.All" sein. Wichtig ist auch noch die Registrierung für COM-Interop auf true zu stellen. Dieses ActiveX-Kompatible Control kannst du unter VB6, wie unter C++ einsetzten sowie auch im ActiveX-Testcontainer ausprobieren.

using System;
using System.IO;
using System.Windows.Forms;

// Für COM & Co:
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
using Microsoft.Win32;

namespace ActiveXExample.All
{

    // WICHTIG für COM:
	// ProgId ist für VC++ relevant
	// VB6 orientiert sich am Assemblynamen
	// am besten man benennt Assembly und ProgId gleich

	[Guid("18FA222D-8C75-4032-A8F0-EA42EF5D46ED")] // GUID evtl. neu generieren
	[ProgId("ActiveXExample.All")]
	[ClassInterface(ClassInterfaceType.AutoDual)]
	public class ActiveXExampleAll : System.Windows.Forms.UserControl
	{

		private static ExtendedTextWriterTraceListener			mTraceListener	= null;

		private System.Windows.Forms.PictureBox pictureBoxGermany;
		private System.Windows.Forms.PictureBox pictureBoxItaly;
		private System.Windows.Forms.PictureBox pictureBoxFrance;
		private System.Windows.Forms.PictureBox pictureBoxUnitedKingdom;
		private System.Windows.Forms.PictureBox pictureBoxSpain;
		private System.Windows.Forms.Label labelQuestion;

		/// <summary>
		/// Erforderliche Designervariable.
		/// </summary>
		private System.ComponentModel.Container components = null;


		#region Constructors / Destructor

		public ActiveXExampleAll()
		{
			InitTraceListener();

			// Dieser Aufruf ist für den Windows Form-Designer erforderlich.
			InitializeComponent();

			// TODO: Initialisierungen nach dem Aufruf von InitComponent hinzufügen

			Trace.WriteLine("Instanz erzeugt");
		}

		~ActiveXExampleAll()
		{
			Trace.WriteLine("Instanz zerstört");
		}

		static ActiveXExampleAll()
		{
			try
			{
				InitTraceListener();

				Trace.WriteLine("Statisch konstruiert");
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace);
			}
		}

		#endregion

		#region Overrides

		/// <summary>
		/// Die verwendeten Ressourcen bereinigen.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if( components != null )
					components.Dispose();
			}
			base.Dispose( disposing );

			Trace.WriteLine("Instanz bereinigt");
		}

		#endregion

		#region COM Register / Unregister

		// Die beiden Methoden sind unabdingbar für ein COM-Control das unter VB6 und VC++
		// funktionieren soll.

		///	<summary>
		///	Registriert die Class als Control und setzt die Codebasis.
		///	</summary>
		///	<param name="keyPath">Der Registrierschlüssel</param>
		[ComRegisterFunction()]
		public static void RegisterClass(string keyPath)
		{
			Trace.WriteLine(string.Format("RegisterClass({0})", keyPath));

			try
			{
				Assembly thisAssembly = Assembly.GetExecutingAssembly();

				// key sieht etwas so aus:
				// HKEY_CLASSES_ROOT\CLSID\{18FA222D-8C75-4032-A8F0-EA42EF5D46ED}
				keyPath = keyPath.Replace(@"HKEY_CLASSES_ROOT\", "");

				// Schlüssel mit dem Pfad öffnen
				using (RegistryKey classKey = Registry.ClassesRoot.OpenSubKey(keyPath, true))
				{

					// Control-Schlüssel erstellen
					RegistryKey ctrlKey = classKey.CreateSubKey("Control");
					ctrlKey.Close();

					// Codebase festlegen
					using (RegistryKey subkey = classKey.OpenSubKey("InprocServer32",true))
					{
						subkey.SetValue("CodeBase", thisAssembly.CodeBase);
					}

					// ???
					using (RegistryKey subkey = classKey.CreateSubKey("MiscStatus")) 
					{
						subkey.SetValue("", "131457");
					}

					// GUID der TypeLib festlegen
					using (RegistryKey subkey = classKey.CreateSubKey("TypeLib")) 
					{
						Guid libID = Marshal.GetTypeLibGuidForAssembly(thisAssembly);
						subkey.SetValue("", libID.ToString("B"));
					}

					// Versionierung
					using (RegistryKey subkey = classKey.CreateSubKey("Version")) 
					{
						Version version = thisAssembly.GetName().Version;
						string versionString = string.Format("{0}.{1}",
							version.Major,
							version.Minor);

						if (versionString == "0.0")
						{
							versionString = "1.0";
						}

						subkey.SetValue("", versionString);
					}

				}
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex);
			}
			finally
			{
				Trace.WriteLine("RegisterClass finished");
			}
		}

		///	<summary>
		///	Deregistriert das Control.
		///	</summary>
		///	<param name="keyPath">Registrierschlüssel</param>
		[ComUnregisterFunction()]
		public static void UnregisterClass(string keyPath)
		{
			Trace.WriteLine(string.Format("UnregisterClass({0})", keyPath));

			try
			{
				keyPath = keyPath.Replace(@"HKEY_CLASSES_ROOT\", "");

				// Schlüssel löschen
				Registry.ClassesRoot.DeleteSubKeyTree(keyPath);
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex);
			}
			finally
			{
				Trace.WriteLine("UnregisterClass finished");
			}
		}

		#endregion

		#region Vom Komponenten-Designer generierter Code
		/// <summary>
		/// Erforderliche Methode für die Designerunterstützung. 
		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
		/// </summary>
		private void InitializeComponent()
		{
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(ActiveXExampleAll));
			this.pictureBoxGermany = new System.Windows.Forms.PictureBox();
			this.pictureBoxItaly = new System.Windows.Forms.PictureBox();
			this.pictureBoxFrance = new System.Windows.Forms.PictureBox();
			this.pictureBoxUnitedKingdom = new System.Windows.Forms.PictureBox();
			this.pictureBoxSpain = new System.Windows.Forms.PictureBox();
			this.labelQuestion = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// pictureBoxGermany
			// 
			this.pictureBoxGermany.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxGermany.Image")));
			this.pictureBoxGermany.Location = new System.Drawing.Point(80, 56);
			this.pictureBoxGermany.Name = "pictureBoxGermany";
			this.pictureBoxGermany.Size = new System.Drawing.Size(48, 40);
			this.pictureBoxGermany.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
			this.pictureBoxGermany.TabIndex = 0;
			this.pictureBoxGermany.TabStop = false;
			// 
			// pictureBoxItaly
			// 
			this.pictureBoxItaly.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxItaly.Image")));
			this.pictureBoxItaly.Location = new System.Drawing.Point(104, 104);
			this.pictureBoxItaly.Name = "pictureBoxItaly";
			this.pictureBoxItaly.Size = new System.Drawing.Size(48, 40);
			this.pictureBoxItaly.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
			this.pictureBoxItaly.TabIndex = 1;
			this.pictureBoxItaly.TabStop = false;
			// 
			// pictureBoxFrance
			// 
			this.pictureBoxFrance.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxFrance.Image")));
			this.pictureBoxFrance.Location = new System.Drawing.Point(32, 56);
			this.pictureBoxFrance.Name = "pictureBoxFrance";
			this.pictureBoxFrance.Size = new System.Drawing.Size(48, 40);
			this.pictureBoxFrance.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
			this.pictureBoxFrance.TabIndex = 1;
			this.pictureBoxFrance.TabStop = false;
			// 
			// pictureBoxUnitedKingdom
			// 
			this.pictureBoxUnitedKingdom.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxUnitedKingdom.Image")));
			this.pictureBoxUnitedKingdom.Location = new System.Drawing.Point(40, 8);
			this.pictureBoxUnitedKingdom.Name = "pictureBoxUnitedKingdom";
			this.pictureBoxUnitedKingdom.Size = new System.Drawing.Size(48, 40);
			this.pictureBoxUnitedKingdom.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
			this.pictureBoxUnitedKingdom.TabIndex = 1;
			this.pictureBoxUnitedKingdom.TabStop = false;
			// 
			// pictureBoxSpain
			// 
			this.pictureBoxSpain.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxSpain.Image")));
			this.pictureBoxSpain.Location = new System.Drawing.Point(8, 104);
			this.pictureBoxSpain.Name = "pictureBoxSpain";
			this.pictureBoxSpain.Size = new System.Drawing.Size(48, 40);
			this.pictureBoxSpain.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
			this.pictureBoxSpain.TabIndex = 1;
			this.pictureBoxSpain.TabStop = false;
			// 
			// labelQuestion
			// 
			this.labelQuestion.BackColor = System.Drawing.Color.Silver;
			this.labelQuestion.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.labelQuestion.Location = new System.Drawing.Point(0, 152);
			this.labelQuestion.Name = "labelQuestion";
			this.labelQuestion.Size = new System.Drawing.Size(168, 23);
			this.labelQuestion.TabIndex = 2;
			this.labelQuestion.Text = "Where are you?";
			this.labelQuestion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			this.labelQuestion.Click += new System.EventHandler(this.labelQuestion_Click);
			// 
			// ActiveXExample
			// 
			this.BackColor = System.Drawing.Color.White;
			this.Controls.Add(this.labelQuestion);
			this.Controls.Add(this.pictureBoxItaly);
			this.Controls.Add(this.pictureBoxGermany);
			this.Controls.Add(this.pictureBoxFrance);
			this.Controls.Add(this.pictureBoxUnitedKingdom);
			this.Controls.Add(this.pictureBoxSpain);
			this.Name = "ActiveXExample";
			this.Size = new System.Drawing.Size(168, 176);
			this.ResumeLayout(false);

		}
		#endregion

		#region Static Methods

		static void InitTraceListener()
		{
			Trace.AutoFlush = true;

			if (!Trace.Listeners.Contains(mTraceListener))
			{
			}
			
			Trace.WriteLine("Starte Log...");
		}

		#endregion

		private void labelQuestion_Click(object sender, System.EventArgs e)
		{
			MessageBox.Show(this, "Not here!");
		}

	}
}

([bb]|[^b]{2})

T
tobias279 Themenstarter:in
16 Beiträge seit 2004
vor 19 Jahren

Mahlzeit!

Vielen DANK!

Also ich habe deinen Code ausprobiert, und es ging!
Ich habe dann meinen Code mit deinem Code ergänzt, und es ging nicht!
Dann habe ich ein neues Projekt aufgemacht(WindowsControlLibrary) deinen code gekürzt, und meine dateien angehängt! also meine Klasse wird nun im LOAD ereignis des Controls aufgerufen!

[EDIT]
Wie registriere ich die Komponente jetzt auf einem fremden System ohne große Aufwendungen??
[end EDIT]

Es scheint so als könnte man nur mit WindowsControlLibrary so eine DLL machen!
Mit ner Klassenbibliothek gings nicht!

Nochmals Vielen Dank!

MfG
Tobias