| Autor |
Beitrag |
Seven of Nine
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Fr 26.06.09 11:32
Folgender Code hat unter Delphi 7 und einer älteren BASS-Version einwandfrei funktioniert um Music-Module (MODS) aus einem kompilierten ResourcenFile zu laden.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| modc := 3; for i:= 1 to modc do begin case i of 1: begin MyResource :=FindResource(HInstance, 'RES7', RT_RCDATA); end; 2: begin MyResource :=FindResource(HInstance, 'RES8', RT_RCDATA); end; 3: begin MyResource :=FindResource(HInstance, 'RES9', RT_RCDATA); end; end; MyGlobal := LoadResource(HInstance,MyResource); pResource:= LockResource(MyGlobal); mods[i] := BASS_MusicLoad(True, pResource, 0, 0, BASS_MUSIC_RAMP OR BASS_UNICODE,0); FreeResource(MyGlobal); end; |
Unter Delphi 2009 lässt sich der Code zwar ebenfalls compilieren (das BASS_UNICODE Flag ist mit gesetzt) allerdings werden die Sound-Module nicht ordnungsgemäß geladen
- Handle auf modc steht nach dem laden weiter auf 0
- der Bass ErrorCode steht auf -1 / unknown Error
- Das Modul ist nicht abspielbar
Interessanterweise funktionieren einige fast identische Codezeile mit BASS/samples" (BASS_SampleLoad) einwandfrei
was mache ich hier falsch? was muss ich ändern?
lG Martin
|
|
Sinspin
      
Beiträge: 1340
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Fr 26.06.09 12:51
Haben sich die Resourcen geändert, so das du nun Unicode verwenden musst? Wenn du die resfile nicht geändert hast müssten die doch noch gleich sein.
Zudem sind Mods doch eh Binärdateien. Wenn ich mich nicht irre ist Unicode doch nur für die Strings von nöten.
Berichtigt mich wenn ich falsch liege.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Fr 26.06.09 13:55
Die Idee das es daran liegt, dass sich das *.res File durch D2009 geändert hat, hatte ich auch schon.
habe es daraufhin mit dem Compiler der D2009 beiliegt erneut kompiliert.
Funktioniert leider trotzdem nicht.
lG Martin
--- Moderiert von Narses: Beiträge zusammengefasst---
Ich habe gerade einen Tipp vom Programmierer der Komponente bekommen.
-> Die neuen Versione von BASS benötigen jetzt auch die Angabe der Länge des MOD-Files
geänderter Sourcode der funktioniert anbei
lG Martin
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| modc := 3; for i:= 1 to modc do begin case i of 1: begin MyResource :=FindResource(HInstance, 'RES7', RT_RCDATA); end; 2: begin MyResource :=FindResource(HInstance, 'RES8', RT_RCDATA); end; 3: begin MyResource :=FindResource(HInstance, 'RES9', RT_RCDATA); end; end; MyGlobal := LoadResource(HInstance,MyResource); pResource:= LockResource(MyGlobal); ResSize := SizeOfResource(HInstance,MyResource); mods[i] := BASS_MusicLoad(True, pResource, 0, ResSize, BASS_MUSIC_RAMP OR BASS_UNICODE,0); FreeResource(MyGlobal); end; |
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Fr 26.06.09 14:27
Moderiert von Narses: Komplett-Zitat des letzten Beitrags entfernt.
also irgendwie verstehe ich nicht warum du immer wieder MyResource überschreibst. In der Schleife wird 3 schließlich immer erreicht, es sollte also jedes mal MyResource = FindResource(HInstance,'RES9',RT_RCDATA); sein. :scratch:
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Fr 26.06.09 15:14
ich verstehe nicht ganz was du meinst.
- MyResource verweist bei unterschiedlicher Zählernummer jeweils auf ein anders MOD-File innerhalb des Resourcenfiles (RES7 -> RES8 -> RES9)
- Die Zuweisung, Längenermitllung und das finale Laden des Modules wird dann außerhalb von case bearbeitet um ein paar Zeilen Code zu sparen
...sollte doch ok so sein oder?
btw: das in der case anweisung noch begin/end; mit drinsteht ist so natürlich nicht nötig. In meinem Code stehen da allerdings jeweils noch weitere Codezeilen die ich aber entfernt habe um das Bsp. hier nicht zu verkomplizieren
lG Martin
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Fr 26.06.09 16:02
ja funktionieren wirds, aber wenn eine Schleife von 1-3 durchgeht und dann je durchlauf eine unterschiedliche Aktion macht, kann man dann nicht die Aktionen ohne Schleife untereinander setzen?
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Fr 26.06.09 16:09
Die Schleife macht je bewusst bei jedem Durchlauf "eine andere Funktion", nämlich das laden eines weiteren Sound-Moduls. Das solange bis alle Module geladen sind.
Aber vlt. "stehe ich auch nur auf dem Schlauch" was du mir sagen möchtest.
lG Martin
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Fr 26.06.09 16:23
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Fr 26.06.09 16:27
Ja, aber in der for-Schleife ist ja nicht nur die case-Anweisung drin. 
_________________ We are, we were and will not be.
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Fr 26.06.09 16:29
ok, jetzt habe ich dich verstanden !Danke für die Geduld.
der Grund für die Schleife bei mir liegt darin das ich (wie schon erwähnt) in der Case Anweisung noch zusätzlich Codezeilen habe welche die Schleifenvariable (i) dazu verwenden ein bestimmte Arrays mit Daten zu füllen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| case i of 1: begin MyResource :=FindResource(HInstance, 'RES7', RT_RCDATA); ModPlayTime[i] := (3*60 + 39) * 1000 ; ModText[i] := 'Title: XTC Artist: Sat'; end; |
Aber auch das kann man natürlich anders machen. Auf diese Weise ist aber die Case-Anweisung (...die hat bei mir im Code auch deutlich mehr Zeilen..) schneller erstellt gewesen -> Copy & Paste. Notwendig für den Code ist das natürlich nicht.
lG Martin
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Fr 26.06.09 16:30
@GAUSI:die könnte man dann aber aus Zeitgründen vor die for-schleife setzten
Was ich jetzt immer noch nicht verstanden habe:
MyResource verwendest du wozu? Weil du der ja sofort wieder einen anderen Wert zuweist, ohne sie zu benutzen. (es sei denn, du enthälst uns noch Code vor)
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: So 28.06.09 05:04
MyResource enthält ja jedesmal ein anderes Handle das gleich darauf benötigt wird (siehe zB 1.tes Codeschnipsel).
Aber, wie schon erwähnt, man könnte das ganze natürlich auch ohne die for-Schleife machen, dann wäre es "offensichtlicher".
Momentan kämpfe ich mit einem weiteren Problem.
Die Applikation wurde bisher mit einer alten bass.dll installiert die vom Installer im InstallationsDir gepeichert wird.
Die neue Version meiner Applikation braucht wegen D2009 aber unbedingt eine neuere bass.dll.
Ich liefere im neuen Installer-Paket dann einfach die nuee bass.dll mit..soweit alles bestens. ABER
Meine Applikation hat eine Autoudate-Funktion. Bereits installierte Versionen "haben" mur die alte "bass.dll", Wird diese aufgerufen gibt es ein Problem, denn die "neue Applikation" braucht ja die "neue" bass.dll.
Nach dem Auto-Update würde es also bei diesen Usern zu Fehlern kommen, deswegen kann ich diese Version noch nicht releasen, sondern muss zuerst das Problem lösen.
Hier mein bisheriger Lösungsansatz, der leider noch nicht funktioniert
- "Neue" bass.dll wird als Resource der Applikation beigegeben
- Beim Start der Applikation wird in FormCreate des Hauptformulars die Version der bass.dll geprüft. Ist diese zu alt, soll sie mit der neueren aus der Resource überschrieben werden (mittels ResourceStream ... Res.SavetoFile).
soweit kein Problem...dachte ich... ABER das gestaltet sich nicht so einfach. Dadurch das die Funktionen der DLL ja in Uses referenziert sind, wird die DLL von der Applikation benützt. Ich kann sie also, vor dem extrahieren der neuen DLL-Version, nicht so einfach löschen. Zusätlich dazu befindet sie sich auch noch im Windows ProgramFiles Ordner wo die UAC auch noch hinzukommt.
Henne vs Ei Problematik ??
kennt jemand einen besseren Ansatz?
lG Martin
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 28.06.09 09:16
Benenne die DLL beim Update einfach um (das geht mit Exen und DLLs, wenn sie gerade laufen) und kopiere die neue an deren Stelle. Danach startest du die eigene Anwendung neu und gibst den Parameter zum Löschen mit.
Ich bin gerade dabei eine entsprechende Updateklasse für Delphiprojekte zu entwickeln. Wegen den notwendigen Rechten passiert das mehrstufig. Ich habe das Ablaufdiagramm (eigene Notation  ) einmal als PDF angehängt.
Vorteile des Verfahrens: das vorher und nachher laufende Programm hat keine Adminrechte, diese werden angefordert ohne eine zusätzliche Exe oder DLL und eine recht gute Fortschrittsanzeige ist auch möglich.
Einloggen, um Attachments anzusehen!
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Di 30.06.09 19:32
@Sebastian: Lässt sich eine Datei (DLL)
a) wenn sie gerade verwendet wird und gleichzeitig
b) im Windows-ProgramFiles Ordner liegt
mit RenameFile(Oldfilename,Newfilename) wirklich bei allen Win-OS-Versionen aus dem aktuell laufenden Programm heraus umbenennen?
Bei mir funktioniert das irgendwie nicht, RenameFile gibt mir als Ergebnis "False" zurück, obwohl die Notation stimmen müsste.
Aber ich würde das ganze ganz gerne ohne den von Dir in deinem Ablaufdiagramm beschriebenen Zusatzweg über eine 2.te Instanz der Anwendung machen. Möglich?
lG Martin
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.06.09 19:38
Ohne zweite Instanz geht das wegen den Rechten schon normalerweise nicht. Das Umbenennen selbst sollte nicht das Problem sein, das geht sogar mit Windows-Systemdateien. So kann man die ersetzen obwohl Windows sie benutzt.
Ich werde das Umbenennen gleich nochmal kurz testen.
// EDIT:
Es funktioniert wie ich mir schon dachte bereits ab Windows 2000.
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Di 30.06.09 20:46
Ok hier ist mal ein Teil meines Codes. Das ist sicher nicht besonders elegant aber es funktioniert hiermit. Evtl. hilft es mal jemandem mit einem ähnlichen Problem.
Eins Vorab: RenameFile(Oldfilename,Newfilename); funktionierte bei mir leider NICHT.
Was aber funktiert ist folgende Funktion (Anmerkugn: sie ist nicht von mir; Autor ist mir derzeit nicht bekannt)
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function RenameFileEx(const AOldName, ANewName: string; ARenameCheck: boolean = false): boolean; var sh: TSHFileOpStruct; begin sh.Wnd := Application.Handle; sh.wFunc := fo_Move; sh.pFrom := PChar(AOldName + #0); sh.pTo := PChar(ANewName + #0); sh.fFlags := fof_Silent or fof_MultiDestFiles; if ARenameCheck then sh.fFlags := sh.fFlags or fof_RenameOnCollision; Result:=ShFileOperation(sh)=0; end; |
Der folgende Code
- fragt ab ob ein Update notwendig ist (anhand des ermittelten datums der bass.dll auf dem PC und dem "Soll-Versions-Datum" das im Code als "Const" definiert ist.
Erforderlich = Ja, kein problem...weiter im Takt...starten
Erforderlich = Nein. Die Routine zum updaten wird gestartet.
- IsBassLoaded gibt an ob die bass.dll aktuell ist.
Falls Nein wird KEINE der Bass Funktione im Programm aufgerufen (-> exit)
und bei Application.terminate wird die Bass.dll aus dem Speicher freigegeben nicht freigegeben
(ansonsten würde es zu Fehlermedlungen kommen)
- Die Codezeilen fürs Updaten der Bass.dll selbst sind halbwegs kommentiert
Anbei ebenso noch die benötigte Funktion CopyFileEx (Autor siehe oben)
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| function TMainForm.CopyFileEx(const ASource, ADest: string;ARenameCheck: boolean = false): boolean; var sh: TSHFileOpStruct; ABool: Boolean; ACount:Integer; begin ACount := 0; If ARenameCheck = False then If FileExists(ADest) then begin ABool := DeleteFile(ADest); while (ABool = False) AND (ACount < 40) do begin Inc(ACount); sleep(50); end; end; sh.Wnd := Application.Handle; sh.wFunc := FO_COPY; sh.pFrom := PChar(ASource + #0); sh.pTo := PChar(ADest + #0); sh.fFlags := fof_Silent or fof_MultiDestFiles; if ARenameCheck then sh.fFlags := sh.fFlags or fof_RenameOnCollision; Result:=ShFileOperation(sh)=0; end; |
und hier der Code der die Updates durchführt
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
| AFileName := PathExeFile + '\' + FNameBassDLL; DateBassResource := MyDecodeDate(VerDate_Bassdll); DateBassPC := MyDecodeDate(FormatDateTime('dd.mm.yyyy', GetFileModifyDate(AFileName)));
if (DateBassResource > DateBassPC) then begin IsBassLoaded := False; Screen.Cursor := crHourglass;
AFileName := PathExeFile + '\' + FNameBassDLL; AFileNameBak := PathExeFile + '\' + FNameBassDLLBak; AFileTemp := PathSave + '\' + FNameBassDLL;
showmessage('TrainIt wird nun ein Update des Sound-Modules (bass.dll) ausführen'+ #13+#10+ 'Bestätigen sie dazu evtl. stattfindende Abfragen Ihres Windows-Betriebsystemes');
If FileExists(AFileNameBak) then DeleteFile(AFileNameBak); RenameFileEx(AFileName,AFileNameBak,False);
If FileExists(AFileTemp) then DeleteFile(AFileTemp); Res := TResourceStream.Create(Hinstance, 'Music_DLL', RT_RCDATA); try Res.SavetoFile(AFileTemp); finally Res.Free; end;
CopyFrom := AFileTemp; CopyTo := AFileName; If FileExists(CopyFrom) then begin copyfileEx(CopyFrom, CopyTo); DeleteFile(CopyFrom); end;
Screen.Cursor := crDefault; showmessage('Update durchgeführt. Bitte starten Sie TrainIt nun erneut'); Application.Terminate; exit; end
else begin Load_BASSDLL(AFileName); if not BASS_Init(-1, 44100, 0, Handle, nil) then begin Showmessage('Error initializing audio!'); IsBassLoaded := False; end else IsBassLoaded := True; end; |
..wie gesagt, sicher nicht besonders schön, aber effizient.
lG Martin
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.06.09 20:49
Wobei du ja anbieten kannst die Exe mit Adminrechten zu starten, wenn du beim Update merkst, dass du keine Schreibrechte hast in dem Verzeichnis.
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Di 30.06.09 20:52
Ja, das könnte ich.
Aber ob das "Otto-Nomaluser" versteht ???
wobei das natürlcih schon gut wäre weil die UAC (Vista) 2 x zuschlägt (beim rename, und beim Copy)
oder gibt es eine Möglichkeit innerhalb einer Anwendung nachträglich auf "als Admin ausführen" umzuschalten?
lG Martin
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.06.09 20:58
Seven of Nine hat folgendes geschrieben : | | oder gibt es eine Möglichkeit innerhalb einer Anwendung nachträglich auf "als Admin ausführen" |
Nein, das ist aus Sicherheitsgründen nicht möglich. Die Rechte werden beim Start zugeteilt und können danach nicht mehr verändert werden.
Es gibt nur zwei Möglichkeiten:
Die eigene oder eine zweite Exe mit Adminrechten starten.
Oder ein COM-Server, was aber eine mit Adminrechten (z.B. beim Setup) registrierte DLL voraussetzt.
|
|
Seven of Nine 
      
Beiträge: 132
Erhaltene Danke: 1
Win XP, Win Vista HomePro
Delphi 2009
|
Verfasst: Mi 01.07.09 04:32
Ok, danke dir Sebastian !
lG Martin
|
|