C# / VB .NET DLLs in AutoIt verwenden

01/08/2014 16:28 alpines#1
Einen guten Mittag euch allen da draußen!

Mir ist in letzter Zeit (oder generell) auf gefallen das einige versuchen .NET DLLs in AutoIt zu verwenden aber es nicht schaffen. Damit keine weiteren Threads oder Fragen darüber gestellt werden wie man es schafft eine .NET DLL in AutoIt zu verwenden und nicht C++ oder ähnliches (Delphi exportiert ebenfalls vernünftig) zu lernen habe ich für euch dieses Tutorial geschrieben.
Ich hoffe ich kann euch damit helfen .NET DLLs in AutoIt einzubinden.

In diesem Tutorial werde ich hauptsächlich auf C# zurückgreifen und nicht auf Visual Basic, da mir C# lieber ist. Fangen wir an!
__________________________________________________ _________________________

Zunächst brauchen wir Microsofts Visual Studio, das gibts in der Express Version 30 Tage lang gratis und danach kann man sich kostenfrei registrieren.
Den Link dazu findet ihr hier: [Only registered and activated users can see links. Click Here To Register...]
Einfach zu Visual Studio Express scrollen, Visual Studio Express 2013 für Windows Desktop anklicken und herunterladen.
Das Tutorial sollte eigentlich auch mit anderen Versionen von Visual Studio kompatibel sein.

Nachdem ihr VS installiert habt öffnet ihr es und es taucht der Startbildschirm auf.
[Only registered and activated users can see links. Click Here To Register...]

Wir gehen auf Neues Projekt und wählen Klassenbibliothek aus.
[Only registered and activated users can see links. Click Here To Register...]

Ich habe das Projekt jetzt checkPrime genannt, da ich eine Funktion dort exportieren möchte Primzahlen errechnet. Weiteres später.
Nach einer recht kurzen Wartezeit öffnet sich anschließend unser C# Projekt.
[Only registered and activated users can see links. Click Here To Register...]

Ihr könnt auch eine einfache Addition schreiben um es zu testen, achtet aber auf die Datentypen!

Die Funktion primeCheck (warum ich mehr oder weniger dieses komplizierte Beispiel genommen habt sehr ihr später!)
[Only registered and activated users can see links. Click Here To Register...]

Zuerst sollte man seinen NuGet-Packet-Manager updaten.
Das geschiet in dem ihr hier klickt und von dort auf Updates > Produktupdates. Ich würde es gerne zeigen, allerdings ist das Update bei mir nicht mehr sichtbar, weil ich es schon aktuell hab.
Sofern das Update da nicht zu sehen ist spielt das keine Rolle und ihr könnt mit dem nächsten Schritt weitermachen.
[Only registered and activated users can see links. Click Here To Register...]

Nachdem ihr euren Paket-Manager geupdatet habt, oder auch nicht, fahren wir mit folgendem Schritt vor. Dem installieren der benötigten Pakete.
Wo und wie man den PM findet, sehr ihr hier.
[Only registered and activated users can see links. Click Here To Register...]

Und schon taucht ein neues Fenster auf, ich habs mir nach links gezogen, weil es mir da besser gefiel. Falls oben nicht nuget.org steht (in der ComboBox) stellt es um, das dort nuget.org steht.
[Only registered and activated users can see links. Click Here To Register...]

Wir tippen dort Install-Package UnmanagedExports ein und drücken die Enter-Taste.
[Only registered and activated users can see links. Click Here To Register...]

Wenn alles gut läuft sollte es wie dort oben gezeigt aussehen.

So, die DLL Funktionen für dieses Projekt wurden installiert, nun müssen wir eine kleine Einstellung übernehmen.
Statt Any CPU müssen wir das auf x86 setzen, aber x86 ist oben nicht vertreten, wie man das hinzufügt sehr ihr hier. Desweiteren von Debug auf Release.
[Only registered and activated users can see links. Click Here To Register...]

Danach erscheint der Konfigurations-Manager.
[Only registered and activated users can see links. Click Here To Register...]

Wir wählen in Aktive Projektmappenplattform: Neu aus und schon erscheint ein neues Fenster.
[Only registered and activated users can see links. Click Here To Register...]

Wir stellen die Einstellungen auf folgendes um damit die DLL kompatibel ist.
[Only registered and activated users can see links. Click Here To Register...]

Anschließend klicken wir auf OK und Schließen das Fenster. Sofern ihr alles bisher richtig gemacht habt sollte oben wo Any CPU stand jetzt x86 stehen und statt Debug Release.

So, soweit so gut. Aber eins haben wir noch vergessen, nämlich die Funktion zu exportieren dies geschieht indem wir erstmal
Code:
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
oben hinzufügen.

So, jetzt haben wir alles was wir zum Exportieren brauchen, jetzt schreiben wir noch eine Zeile zum Exportieren selbst hin.
Diese Zeile lautet in meinem Fall
Code:
[DllExport("checkPrime", CallingConvention = CallingConvention.StdCall)]
DllExport sagt sicherlich schon was es ist, "checkPrime" ist die Funktion und den Rest dafür das es ein StdCall ist (StdCall = Standard-Funktionsaufruf)

Mittlerweile sieht mein Code so aus.
[Only registered and activated users can see links. Click Here To Register...]

Jetzt ist eigentlich alles fertig und nichts steht mehr im Weg unsere DLL endlich zu kompilieren, also können wir entweder F7 drücken oder F5
Der Unterschied zwischen F7 und F5 ist der, dass F7 das Projekt kompiliert und F5 kompiliert sowie debugged.
F5 wird zwar das Projekt kompilieren aber spuckt unnötigerweise eine Fehlermeldung aus die wir mit F7 vermeiden können.

Also drücken wir F7!
[Only registered and activated users can see links. Click Here To Register...]

Damit sollte in Dokumente > Visual Studio 2013 > Project > checkPrime > checkPrime > bin > x86 > Release die checkPrime.dll liegen.
[Only registered and activated users can see links. Click Here To Register...]

Ich hab einen kleinen Test vorbereitet, das war auch eigentlich der Grund warum ich Primzahlen für den Test genommen hab.
Denn ich möchte euch den Geschwindigkeitsunterschied zwischen AutoIt und C# zeigen.

So sieht mein Testordner aus.
[Only registered and activated users can see links. Click Here To Register...]

Das Testscript sieht so aus.
Code:
; Speedtest.au3

$hTimer = TimerInit()

Local $a = 2, $b = 2, $c = 0

Do
	$b = 2
	While $a >= $b
		If mod($a, $b) = 0 Then $c += 1
		$b += 1
	WEnd

	If $c > 2 Then $c = 0 ;keine Primzahl
	If $c = 1 Then $c = 0 ;Primzahl

	$a += 1
Until TimerDiff($hTimer) >= 5000

ConsoleWrite("Speedtest AutoIt 5 Sec Prime: " & $a & @CRLF)

$hTimer = TimerInit()

Local $a = 2

Do
	DllCall("checkPrime.dll", "bool", "checkPrime", "int", $a)
	$a+=1
Until TimerDiff($hTimer) >= 5000

ConsoleWrite("Speedtest C# 5 Sec Prime: " & $a & @CRLF)
So, kommen wir zu dem Aspekt den ich schon die ganze Zeit erwähnen möchte, die Geschwindigkeit.
Da bei C# kein Interpreter den AutoIt Code noch in C++ Code interpretieren muss, verliert man kaum an Geschwindigkeit.
Das ist sehr deutlich durch die Speedtest.au3 zu erkennen, trotz dem zusätzlichen DllCall ist die C# DLL schneller, hier die Ergebnisse.

Code:
Speedtest AutoIt 5 Sec Prime: 2697
Speedtest C# 5 Sec Prime: 50696
Man sollte noch anmerken, das bei Primzahlen die Anzahl nicht steigt wie man einfachen Rechnungen, da hier die Zahl selbst und alle Zahlen dadrunter bis 2 durchgerechnet werden um einen Teiler zu finden.
Man kriegt deutlich eindeutigere Resultate wenn man eine DLL mit Addition exportiert aber das könnt ihr ja versuchen ;)

Wichtig! Wenn die Funktion string returned oder als Parameter string hat dann düft ihr sie in AutoIt nicht mit string als Typ definieren sondern str!
Wichtig! Setzt den Accessor auf Public, da einige Sprachen (vb) Probleme haben die Funktion zu importen!

Im Anhang ist der Testordner + Projektmappe der DLL als .zip!

__________________________________________________ _________________________

Zum Abschluss möchte ich noch sagen, das es mir Spaß gemacht hat das Tutorial zu verfassen, ich hoffe ich konnte euch damit helfen .NET DLLs erfolgreich in AutoIt zu verwenden.
Lob, Kritik und jegliches Feedback ist jederzeit gerne gesehen! :)

// VT ist denke ich nicht notwendung, da nur Source + DLL dadrinne liegen und man die DLL neu kompilieren kann wenn man skeptisch ist!
08/16/2014 14:56 GatewayToEPVP#2
Dein Programm funktioniert wie du es beschrieben hast, aber die Funktionen der DLL werden nie ausgeführt! Ich habe Berechnungen in die DLL eingebaut, die nur maximal 1000 Ausführungen haben müssten. Es bleibt aber konstant bei den 21000. Das ist der Unterschied zur Geschwindigkeit. Autoit führt wirklich checkPrime durch, aber der Aufruf der DLL ergibt eine sofortige Rückkehr.
08/16/2014 15:14 alpines#3
Quote:
Originally Posted by GatewayToEPVP View Post
Dein Programm funktioniert wie du es beschrieben hast, aber die Funktionen der DLL werden nie ausgeführt!
Kann doch gar nicht sein, wenn ich mir das Ergebnis von dem DllCall ausgeben lasse dann sehe ich doch das der mir 0 zurückgibt, wenn es keine Primzahl ist und eine 1 zurückgibt wenn es eine ist.