Problemstellung
Bildschirmschoner oder Präsentation in AIR anlegen. Dieser soll per Installer ausgeliefert werden und sich in ein System integrieren (Bildschirmschoner registrieren)
Aus einigen Referenzen konnte ich erste Ansätze herrauslesen. Dieser Eintrag soll nun eine Zusammenstellung einer Lösung mit Kompromissen aufzeigen.
Adobe AIR Applikation
Wir versuchen dieses Problem mit Adobe AIR zu lösen. Und zwar weil sich bei Screensavern mit Animation (Fotos/Videos) die Runtime von Flash besonders eignet. Das Grundpaket bitet zudem die Basis für eine plattformunabhänige Entwicklung, was besonders bei Präsentationsumgebungen sinnvoll ist. Bei einem Screensaver muss man verschiedene plattformbedingte Gegebenheiten beachten. Ein weiters Feature der AIR Runtime ist, dass wir keinen ActiveX Flash Player oder sonstige Software auf dem System (vor-)installieren müssen. Dies wird aus Sicherheitsgründen häufig von grösseren Firmen verlangt.
Grundvorraussetzung ist das FLEXSDK + AIR SDK. Die verwendeten Features setzen mindestens AIR 2.0 voraus. Ich verwende die aktuelle Version 2.7.
Wir verwenden das Adobe AIR Template von Flash Develop (in den neuen Builds enthalten). Hier sind die Standard Aktionen wie Keystore generieren und Package exportieren in BAT-Dateien schon vorhanden. Das Testen ist direkt aus FlashDevelop per adl.exe (im Framework enthalten) möglich. Das Template sollte ohne zusätzlichen Code sofort laufen.
Mehrere Bildschirme
Bildschirmschoner müssen auch mehrere Bildschirme abdecken können. Wir lesen per Screen.screens alle verfügbaren Bildschirme aus und erstellen jeweils einzelne Native Windows die wir mit Fullscreen aufschalten.
for (var i:int = 0; i > Screen.screens.length; i++) { var screen:Screen = Screen.screens[i]; var sbounds:Rectangle = screen.bounds; var wndo:NativeWindowInitOptions = new NativeWindowInitOptions(); var wnd:NativeWindow = new NativeWindow(wndo); wnd.x = sbounds.x; wnd.y = sbounds.y; wnd.width = sbounds.width; wnd.height = sbounds.height; wnd.visible = true; wnd.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; wnd.stage.addEventListener(MouseEvent.MOUSE_DOWN, onUserPresent); wnd.stage.addEventListener(KeyboardEvent.KEY_DOWN, onUserPresent); }
Bildschirmschoner Startparameter
Ein Bildschirmschoner unter Windows wird von der SCRSAV.exe mit Parametern aufgerufen:
/c = Einstellungsmodus
/p = Vorschau
/s = Als Screensaver ausführen
Da wir auf den Applikationsstart mit Invoke hören können wir auch auf die Startparameter zugreifen.
var args:Array = e.arguments; txt.appendText("started with: " + args.join(",") + "\n"); txt.appendText("started with: available screens: "+Screen.screens.length+"\n"); if (args.indexOf("/s")>-1 || args.indexOf("/S")>-1 || args.length==0) { //application started as screensaver txt.appendText("go on with screens\n"); } else { txt.appendText("exit because params\n"); NativeApplication.nativeApplication.exit(); return; }
Den Settingsmodus könnten wir mit /c abfangen und Einstellungen zulassen. Diese wären möglich in einer XML Datei zu speichern.
Gedacht wäre beim Parameter /p eine Preview darzustellen in dem kleinen Fenster. Wie sich das Microsoft gedacht hat: http://www.wischik.com/scr/howtoscr.html#CommandLineArguments
Die HWND* wird übergeben und wir könnten uns jetzt mit der Windows API das Rectangle ermitteln wo wir hinsollten… Ich brauch keine Preview
Deployment (the dirty part)
Nun folgt eigentlich der Part für den ich keine optimale Lösung gefunden und umgesetzt habe. Stattdessen suchte ich nach einer Kompromisslösung.
Dirty Premissions:
Logisch: Sicherheit! Aber nervt ![]()
Wir müssen eine EXE-Datei zu einer SCR-Datei kopieren. Dies wird im appicationDirectory gemacht. Tja und dass ist das eigentlich “dreckige” an der Sache. Andere Plattformen erlauben normalerweise keine Modifikation des Programmverzeichnisses während der Laufzeit. Z.b. wird auf anderen Plattformen die Applikation mit Nutzerrechten ausgeführt. Da die Nutzer aber normalerweise keine Adminrechte haben, dürften hier keine Dateien modifiziert werden.
Das liebe Windows ist hier nicht so strikt, vorallem weil die Installation mit Adminrechten durchgeführt wird. Also tricksten wir. Beim ersten mal Starten (gleich nach der Installtion) führen wir ein Script aus, das uns die Datei kopiert und den Screensaver aktiviert. Das Script wird hier mit Adminrechten ausgeführt und kann das Projektverzeichniss modifizieren.
Eine alternative Lösung wäre, pro User separat im userData Space die Applikation zu speichern, was wiederum Probleme mit der AIR Runtime geben würde. Auch ein funktionierender Ansatz wäre, eine zweite Applikation in die erste hineinzukompilieren, ich wollte allerdings einen schlankeren Ansatz.
Native Process
In Windows kann man einen Screensaver per RunDLL oder per Registry setzten. Interessant ist: Unter Windows XP geht das nur mit der RunDLL und bei Win7 nur per Registery, wenn die SCR nicht im Windows Verzeichnis liegt. Unsere AIR Applikation wird aber im Programm Verzeichnis liegen.
“Native Process” in AIR erlaubt uns lokale Dateien auszuführen (exe). Wir benötigen aber zusätzliche Berechtigungen für die Applikation in der applikation.xml:
<supportedProfiles>extendedDesktop</supportedProfiles>
Diese Anweisung zwingt uns jetzt aber auch das Packing Script umzustellen. Wir brauchen ab jetzt einen Native Installer. Dazu ändern wir nur die set AIR_FILE Zeile im PackageApplikation.bat.
set AIR_FILE=-target native sunriseimagescr.exe
Wir haben nun die Möglichkeit die Exe in eine SCR (Screensaver) umzubenennen und dann in Windows zu registrieren. Hierzu verwende ich ein zusätzliches Script (install_saver.bat). Dieses Script könnte jetzt plattformspezifisch anders aussehen.
@echo off set SCRFILENAME=%~dp0imagescr.scr copy imagescr.exe imagescr.scr reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t REG_SZ /d "%SCRFILENAME%" /f rundll32.exe desk.cpl,InstallScreenSaver "%SCRFILENAME%"
Hier muss noch eine IF rein um abzuprüfen welches System wir haben (winxp,win7).
Nach Installation des Screensavers wir dieser automatisch ausgeführt (Standardaktion bei AIR Installation). Wir nutzen dieses Feature nun aus und fragen, ob die SCR Datei bereits besteht. Wenn ja, führen wir den Screensaver mit entsprechenden Parametern aus. Wenn nein, führen wir das Script aus. (Wir hören auf den Invoke)
var file:File = File.applicationDirectory.resolvePath("screensaver.scr"); if (file.exists) { NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvokeEvent); } else { if (NativeProcess.isSupported) { //we have to execute the bat with with cmd.exe as commandinterpreter var bat:File = File.applicationDirectory.resolvePath("install_saver.bat"); var cmd:File = new File("C:\\WINDOWS\\system32\\cmd.exe"); var npi:NativeProcessStartupInfo = new NativeProcessStartupInfo(); npi.executable = cmd; npi.workingDirectory = File.applicationDirectory; var args:Vector.<String> = new Vector.<String>(); args[0] = "/c"; args[1] = bat.nativePath; npi.arguments=args; proc = new NativeProcess(); proc.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onOutputData); proc.start(npi); // //finally we exit the application and wait for the real screensaver call NativeApplication.nativeApplication.exit(); } else { throw new Error("no native process support"); } }
Wiederum könnte der Code plattformabhängig modifiziert werden.
Seperater Installer für AIR
Wir brauchen die Runtime von Adobe AIR auf dem Zielsystem: http://get.adobe.com/de/air/
Es ist möglich, beim Installer Adobe AIR mitzuliefern. Dazu muss man aber die direkte Erlaubnis von Adobe haben: http://www.adobe.com/de/products/air/runtime_distribution1.html
Ich hab den Adobe Weg noch nicht versucht. Hat hier jemand Erfahrung damit?
Deinstallieren…
…Ist auch ein Problem für sich. Die Deinstallation funktioniert zwar einwandfrei mit dem Uninstaller von AIR, leider bleibt aber so die Referenz in der Registry. Hierfür benötigt man eine separate BAT-Datei. Die auch noch die SCR entfernt.
Eine Lösung wäre übrigens auch, den Adobe Installer in einen separaten Installer zu packen und darüber den Installations- und Deinstallationsprozess zu managen.
http://www.actionscript.org/forums/showthread.php3?t=171190
Projektdateien
Referenzen
- http://blog.empiregpservices.com/post.cfm/adobe-air-screensaver-how-to-make-use-of-windows-settings-button
- http://www.video-flash.de/index/flash-bildschirmschoner-mit-adobe-air-erstellen/
- http://www.adobe.com/devnet/air/flex/quickstart/articles/interacting_with_native_process.html
- http://www.tburke.net/info/rundll.htm
- http://www.flashdevelop.org
- http://www.adobe.com/de/products/air/runtime_distribution1.html
* Die HWND-Eigenschaft (auch: Handle) gibt eine Zugriffsnummer für ein Formular oder Steuerelement zurück, d. h. ein eindeutiger ganzzahliger Wert, der von der Betriebsumgebung definiert wird und von einem Programm verwendet wird, um ein Objekt zu kennzeichnen und zu einem Objekt zu wechseln.













