Donnerstag, 24. Mai 2012


Artikel

Dezember 2009 | Artikel

They all come out in little boxes Teil 2 Fortsetzung, Teil 2

Teil 1   Teil 2   

Intelligente Installationen

Auch wenn der CAB Parser von Windows Mobile diverse nette Aktivitäten anhand von .xml-Dateien alleine durchführen kann, trifft man trotzdem von Zeit zu Zeit auf Aufgaben, die mit einer .xml-Datei allein nicht lösbar sind (z. B. das Löschen von zur Laufzeit erstellten Dateien). In so einem Fall kann nur selbst erstellter Code helfen. Doch wie soll man den ausführen, wenn die Anwendung schon längst gelöscht ist? Für dieses Problem hat Microsoft immerhin eine Lösung gefunden. Und die heißt Setup-DLL. Das ist eine native (also in C++ geschriebene) Bibliothek, die vom CAB Parser im Rahmen der Installation oder Deinstallation der Anwendung aufgerufen wird. Die Grundstruktur einer solchen DLL zeigt Listing 5:

  1. //
  2. #include "tchar.h"
  3. #include "stdafx.h"
  4. #include "ce_setup.h"
  5. #include "notify.h"
  6. #include <windows.h>
  7. #include <commctrl.h>
  8. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpvReserved)
  9. {
  10. return TRUE;
  11. }
  12. //these are needed according to MSDN, as the library is not
  13. //recognized otherwise
  14. codeINSTALL_INIT Install_Init(
  15. HWND hwndParent,
  16. BOOL fFirstCall, // is this the first time this function is being called?
  17. BOOL fPreviouslyInstalled,
  18. LPCTSTR pszInstallDir
  19. )
  20. {
  21. // TODO: Add custom installation code here
  22. // To continue installation, return codeINSTALL_INIT_CONTINUE
  23. // If you want to cancel installation,
  24. // return codeINSTALL_EXIT_UNINSTALL
  25. return codeINSTALL_INIT_CONTINUE;
  26. }
  27. codeINSTALL_EXIT Install_Exit(
  28. HWND hwndParent,
  29. LPCTSTR pszInstallDir,
  30. WORD cFailedDirs,
  31. WORD cFailedFiles,
  32. WORD cFailedRegKeys,
  33. WORD cFailedRegVals,
  34. WORD cFailedShortcuts
  35. )
  36. {
  37. // TODO: Add custom installation code here
  38. // To exit the installation DLL normally,
  39. // return codeINSTALL_EXIT_DONE
  40. // To unistall the application after the function exits,
  41. // return codeINSTALL_EXIT_UNINSTALL
  42. return codeINSTALL_EXIT_DONE;
  43. }
  44. codeUNINSTALL_INIT Uninstall_Init(
  45. HWND hwndParent,
  46. LPCTSTR pszInstallDir
  47. )
  48. {
  49. // TODO: Add custom uninstallation code here
  50. // To continue uninstallation, return codeUNINSTALL_INIT_CONTINUE
  51. // If you want to cancel installation,
  52. // return codeUNINSTALL_INIT_CANCEL
  53. return codeUNINSTALL_INIT_CONTINUE;
  54. }
  55. codeUNINSTALL_EXIT Uninstall_Exit(
  56. HWND hwndParent
  57. )
  58. {
  59. // TODO: Add custom uninstallation code here
  60. return codeUNINSTALL_EXIT_DONE;
  61. }

Diese Struktur muss zu 100 Prozent übernommen werden (inklusive der DLLMain). Fehlt auch nur eine einzige Funktion, wird die DLL nicht akzeptiert und zur Laufzeit vom CAB Parser stillschweigend (!!!) ignoriert. Die vier Routinen werden zu bestimmten Zeitpunkten während der Installation aufgerufen. Je nach Rückgabewert wird die Installation / Deinstallation abgebrochen oder fortgeführt.

Setup-DLL – Feuer frei!

Als abschließendes Beispiel wird hier eine Setup-DLL konstruiert, die eine Event-Registrierung aufhebt. Zuerst muss die Setup-DLL erstellt werden. Dazu dient ein „normales“ und MFC-freies Win32-Smartprojekt (zu finden unter VISUAL C++ | INTELLIGENTES GERÄT | WIN32-PROJEKT FÜR INTELLIGENTE GERÄTE). Man muss im Settings Wizard jedoch DLL wählen, um eine DLL zu erhalten.

Dann kopiert man die zuvor gezeigte DLL-Struktur ins Programm und fügt das in Listing 6 gezeigte Snippet anstelle des Funktionsskeletts ein. Es ruft mehrfach die Funktion zur Deregistrierung eines Eventhandlers auf – mehr dazu findet sich in der MSDN:

  1. codeUNINSTALL_INIT Uninstall_Init(
  2. HWND hwndParent,
  3. LPCTSTR pszInstallDir
  4. )
  5. {
  6. int i;
  7. _tcscat((TCHAR*)pszInstallDir,_T("\\DaquPopup.exe"));
  8. for(i=0; i<20; i++)
  9. {
  10. CeRunAppAtEvent((TCHAR*)pszInstallDir, NOTIFICATION_EVENT_NONE);
  11. }
  12. return codeUNINSTALL_INIT_CONTINUE;
  13. }

Damit ist die DLL eigentlich erledigt. Leider wissen außenstehende Anwendungen nichts davon, was in der DLL so alles schlummert – dazu benötigt man eine DEF-Datei, die dem Projekt hinzugefügt werden muss. In ihr definiert man die von außen sichtbaren Funktionen –hier ein Beispiel dafür:

  1. LIBRARY "SetupDLL"
  2. EXPORTS
  3. Install_Init
  4. Install_Exit
  5. Uninstall_Init
  6. Uninstall_Exit

Wenn sich die DLL problemlos kompilieren lässt, ist der Spuk auch schon vorbei – die DLL wird, wie oben gezeigt, dem CAB-Projekt hinzugefügt (auch hier lautet das Zauberwort Primäre Ausgabe). Dann wird sie in der Eigenschaftsseite dem Projekt als CE Setup-DLL zugewiesen und das CAB neu erstellt. Geschafft …

Tam Hanna befasst sich seit der Zeit des Palm IIIc mit Programmierung und Anwendung von Handcomputern. Er entwickelt Programme für diverse Plattformen und betreibt außerdem mehrere populäre Online-Newsdienste zum Thema.

Teil 1   Teil 2   

Kommentare