DllCall naming convention

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
IRBaboon
Posts: 27
Joined: 11 Aug 2014, 07:48

DllCall naming convention

25 Feb 2016, 04:38

Hallo zusammen,

ich versuche eine Funktion aus einer dll aufzurufen. Leider bin ich nicht fähig die richtigen Argumente zu übergeben wie es scheint. Das ist mein erster Versuch mit DllCall, deswegen bin ich mit nicht sicher ob die class reference der dll überhaupt die benötigten Informationen hergibt. Das Laden der dll funktioniert soweit aber ErrorLevel sagt das die Funktion nicht in der dll existiert. Ich habe diverse Kombinationen für die Übergabe des Funktionsnamen für den default constructor durch aber komme nicht weiter. Geht das überhaupt so oder hab ich einen komplett falschen Ansatz?

Das steht in der reference (http://id3lib.sourceforge.net/api/class ... g.html#a49):

Code: Select all

ID3_Tag::ID3_Tag ( 	const char * name = NULL )
  	

Default constructor; it can accept an optional filename as a parameter.

If this file exists, it will be opened and all id3lib-supported tags will be parsed and converted to ID3v2 if necessary. After the conversion, the file will remain unchanged, and will continue to do so until you use the Update() method on the tag (if you choose to Update() at all).

Parameters:
    name  	The filename of the mp3 file to link to

Parameters:
    name  	
und das ist mein code:

Code: Select all

file = %A_ScriptDir%\id3com.mp3

hModule := DllCall("LoadLibrary", "Str", "id3com.dll", "Ptr")  ; Avoids the need for DllCall() in the loop to load the library.

tags := DllCall("id3com\ID3_Tag", "Str", file, "Cdecl Str")
MsgBox % "tags: " tags "`nerrorlevel: " ErrorLevel "`nlasterror: " A_LastError


result := DllCall("id3com\Find", "Str", ID3FID_ALBUM, "Cdecl Str")
MsgBox % "errorlevel: " ErrorLevel "`nlasterror: " A_LastError

MsgBox % "hmodule: " hModule "`nresult: " result


DllCall("FreeLibrary", "Ptr", hModule)  ; To conserve memory, the DLL may be unloaded after using it.
mfg IR
User avatar
nnnik
Posts: 4470
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall naming convention

27 Feb 2016, 08:40

Das ist eine schwierige Frage, da die Beschreibungen für die DLLs in der Objekt schreibweise sind, die man mit AHK so direkt nicht aufrufen kann. (Siehe ThisCall Convention)
Man kann die Funktionennamen die innerhalb einer dll vorhanden sind aber auch anzeigen lassen:
http://www.nirsoft.net/utils/dll_export_viewer.html
Wenn ich das mache finde ich keine Funktion mit dem Namen ID3_Tag und Find.
Im moment schaue ich mir die DLL im Disassembly an um zu schauen wie genau man sie benutzen muss.
Recommends AHK Studio
User avatar
nnnik
Posts: 4470
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall naming convention

27 Feb 2016, 10:49

Ich habe gerade herausgefunden, dass sich die DLL mit dem COM interface benutzen lässt. (Du brauchst glaube ich eine andere DLL um diese dann mit DllCall verwenden zu können.)
Du musst, damit die DLL als COM Object benutzen lässt sie zuerst registrieren. Das würdest du machen indem du regsvr32 id3com.dll ausführst.
Das folgende Script macht dieses jedoch automatisch:

Code: Select all

Loop
{
	try 
		Id3Tag := ComObjCreate("ID3COM.ID3COMTag")
	catch 
	{
		Path := "id3com.dll"
		If !FileExist("id3com.dll")
			FileSelectFile,Path,3,id3com.dll,Please select id3com.dll,id3com.dll (id3com.dll)
		If !Path 
			ExitApp
		DllCall("shell32\ShellExecute", "uint", 0, "str", "RunAs", "str", "regsvr32", "str", Path, "str", A_WorkingDir, "int", 1) ;registers the dll with admin rights
		goto,Start
	}
}
Id3Tag.Link(A_MyDocuments . "\song.mp3") 
Msgbox % Id3Tag.Album := "ABC"
Msgbox % Id3Tag.Artist
Id3Tag.SaveV2Tag()
Recommends AHK Studio
User avatar
IRBaboon
Posts: 27
Joined: 11 Aug 2014, 07:48

Re: DllCall naming convention

29 Feb 2016, 03:02

Vielen Dank das du dir so viel Zeit genommen hast! Nirsoft ist eine super Seite, hab dort schon oft nützliche tools gefunden.
Bei mir zeigt es exportierte Funktionen an, evtl. 32/64 bit Programm- bzw. dll-Version? (ID3Tag_Link 0x10006bc8 0x00006bc8 41 (0x29) Exported Function) Allerdings ist dort auch keine Find Funktion dabei.
Ich werde es aber über COM versuchen. Sieht auch wesentlich übersichtlicher aus. Das ich sie für COM Interface erst registrieren muss hätte ich mit Sicherheit übersehen, danke für den Hinweis :)
Gehe ich richtig in der Annahme das bei COM die dll bei jedem Aufruf neu geladen wird? Ist aber für meine Zwecke auch vernachlässigbar.

Vielen Dank noch mal!
User avatar
nnnik
Posts: 4470
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall naming convention

29 Feb 2016, 12:00

Die find Funktion heißt glaube ich ID3Tag_Find oder so.
Bei COM übernimmt das System das laden der DLL ich glaube sie bleibt geladen bis AHK keine Verbindungen mehr dazu hat.
Recommends AHK Studio
User avatar
IRBaboon
Posts: 27
Joined: 11 Aug 2014, 07:48

Re: DllCall naming convention

02 Mar 2016, 05:32

Code: Select all

DllCall("shell32\ShellExecute", "uint", 0, "str", "RunAs", "str", "regsvr32", "str", Path, "str", A_WorkingDir, "int", 1) ;registers the dll with admin rights
hier wird das RunAs anscheinend nicht beachtet, die Fehlermeldung sagt das die Ressource nicht vorhanden ist. Wenn ich die Admin Abfrage separat einbaue, funktioniert es:

Code: Select all

#SingleInstance force

...

Loop
{
	try 
		Id3Tag := ComObjCreate("ID3COM.ID3COMTag")
	catch 
	{
		if not A_IsAdmin
		{
			;das try/catch ist nötig um einen Benutzerabbruch mit einer ordentlichen Meldung abzufangen
			try
				Run *RunAs "%A_ScriptFullPath%"
			catch {
				MsgBox, 48, Error, The Program must be run as administrator on first run to register its ressources.
				ExitApp
			}
		}
		Path := "id3com.dll"
		If !FileExist("id3com.dll")
		{
			MsgBox, 48, %Path% missing., Select location to %Path%
			FileSelectFile,Path,3,id3com.dll,Please select id3com.dll,id3com.dll (id3com.dll)
		}
		If !Path 
			ExitApp
		DllCall("shell32\ShellExecute", "uint", 0, "str", "RunAs", "str", "regsvr32", "str", Path, "str", A_ScriptDir, "int", 0) ;registers the dll with admin rights, last parameter nShowCmd=0 suppresses success message
		If (A_LastError=1223) ; 1223 = Aborted by user
		{
			MsgBox, 48, Error, Could not register %Path%.
			ExitApp
		}
	}
	goto, Start
}
User avatar
IRBaboon
Posts: 27
Joined: 11 Aug 2014, 07:48

Re: DllCall naming convention

08 Mar 2016, 05:07

Ich versuche jetzt schon seit ein paar Tagen ein Objekt für Id3Frame zu bekommen. Habe mir die Referenz für COM Objekte usw. mehrmals durchgelesen und auch wikipedia etc. und ich bin noch nicht wirklich klüger.
Wie kommt man bei

Code: Select all

ComObjCreate("ID3COM.ID3COMTag")
auf das ID3COM und auf das ID3COMTag? Woher nimmt man diese Information? In den exportierten Funktionen, Propertys oder Methoden der dll ist diese Kombination nicht zu finden.
Ich habe noch andere Bibliotheken gefunden die für meinen Zweck taugen könnten aber alles ohne Doku. Jedoch gibt es Software welche diese dlls verwenden. Wie bekomme ich zB. heraus wie viele Parameter mit welchem Typ ich übergeben muss wenn es keine Dokumentation für die jeweilige dll gibt?
User avatar
nnnik
Posts: 4470
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall naming convention

09 Mar 2016, 08:04

Du musst nach der Dokumentation des Com Objectes gehen.
Die Funktionen in der Dll sind nur dafür da um von Windows als Com Obj benutzt werden zu können. Sie sind von daher gar nicht so wichtig.

Die Werte die ein Com Obj ausgibt konnte man mit dem oleviewer ansehen, den Microsoft netterweise heute nicht mehr kostenlos anbietet. :) (google einfach mal oleviewer.exe)
Ich habe den Oleviewer hier und mir mal die Mühe gemacht zumindest die Tag Klasse rausgeschrieben.
Die Frame könnte ich später auch noch machen.

Code: Select all

ID3COM := {}

						ID3COM.ID3ComTag.Link(Filename) ;Links this Tag to a file
						ID3COM.ID3ComTag.SaveV1Tag() ;Saves certain atributes to the linked file
						ID3COM.ID3ComTag.SaveV2Tag() ;Saves certain atributes to the linked file
						ID3COM.ID3ComTag.StripV1Tag() ;removes them??
						ID3COM.ID3ComTag.StripV2Tag() ;removes them??
						ID3COM.ID3ComTag.Clear()  ;removes all attributes and links probably

ID3COM.ID3ComFrame := 	ID3COM.ID3ComTag.FrameByNum(FrameNum) ;I guess it has a frame or more of them
ID3COM.ID3ComFrame := 	ID3COM.ID3ComTag.FindFrame(FrameId,Create_New_If_Not_Found_Flag := -1) ;Frames have ids
ID3COM.ID3ComFrame := 	ID3COM.ID3ComTag.FindFrameString(FrameId,FieldType,FindString,Create_New_If_Not_Found_Flag := -1) ;???

;-----

ID3COM.ID3ComTag.Artist 	:= ""
ID3COM.ID3ComTag.Album  	:= ""
ID3COM.ID3ComTag.Title  	:= ""
ID3COM.ID3ComTag.Comment	:= ""
ID3COM.ID3ComTag.Year   	:= ""

ID3COM.ID3ComTag.Genre  	:= Nr ;kk making the year a string but the genre a number
ID3COM.ID3ComTag.Track  	:= Nr
ID3COM.ID3ComTag.PlayCount  := Nr
ID3COM.ID3ComTag.Popularity := Nr

ID3COM.ID3ComTag.LastPlayed := DATE ;I'm not too sure what DATE means here
ID3COM.ID3ComTag.TagCreated := DATE

ID3COM.ID3ComTag.PercentVolumeAdjust := Nr
Recommends AHK Studio
User avatar
IRBaboon
Posts: 27
Joined: 11 Aug 2014, 07:48

Re: DllCall naming convention

15 Mar 2016, 08:32

Hallo nnnik,

vielen Dank noch mal und entschuldige die späte Antwort, mich hat die Grippe dahingerafft. Einen Versuch mach ich noch, danach lass ich dich in Ruhe da das Thema langsam nichts mehr mit ahk zu tun hat und mein Wissensstand auch nicht annähernd ausreicht um hier Fortschritte zu machen. Mein Ziel war es eigentlich ein Albumbild in eine mp3 einzubinden. Ich werde wohl eine Drittanbietersoftware nutzen müssen um es mit meinen Programmierkenntnissen hinzubekommen. Und nach fertigem code will ich hier auch nicht fragen.
Ich hab einen anderen oleviewer als den von Microsoft gefunden. Laut diesem habe ich 3 interfaces für id3com: ID3COMTag, ID3COMFrame und ID3COMField. Meinem Verständnis nach sollte das also funktionieren:

Code: Select all

Id3Frame := ComObjCreate("ID3COM.ID3COMFrame")
hier sagt ahk aber Ungültige Klassenzeichenfolge. Ist aber auch unwichtig weil das folgende steht in der Dokumentation der dll:
Almost all functionality occurs via an ID3_Tag object. An ID3_Tag object basically encapsulates two things: a collection of ID3_Frame objects and file information. The goal is to populate an ID3_Tag object with ID3_Frame objects, and the easiest way to do this is to associate the tag with a file.
...
The default behavior of Link() is to parse all possible tagging information and convert it into ID3v2 frames.
Also brauch ich das Frame interface eigentlich gar nicht weil ja alles schon geparsed wird. Der Picture Frame hat die FrameID 2 also hab ich das versucht:

Code: Select all

Id3Tag.Link("id3com.mp3")
image := FileOpen("pic.jpg", r)
Id3Tag.FindFrame(2) := image
Id3Tag.SaveV2Tag()
Id3Tag.SaveV1Tag()
Id3Tag.Clear
Id3Tag := ""
geht aber auch nicht. Mitglied nicht gefunden. Specifically: FindFrame

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 6 guests