Tja, so war es, das Leben ohne SSD

Auf einem Rechner stelle ich immer wieder fest, dass der VCR.NET Recording Service nach dem Booten nicht läuft – das kann sehr ärgerlich werden, wenn man auf Aufnahmen wartet. Im Ereignisprotokoll von Windows steht, dass der Dienst in 30 Sekunden nicht gestartet werden konnte und deswegen beendet wurde. Tatsächlich macht der VCR.NET Recording Service kaum etwas beim Starten so dass die Ursache schnell erkannt war: dieser eine Rechner hat noch keine SSD, da dauert das halt alles etwas länger beim Starten.

Ich habe den Startmodus des Dienstes auf den verzögerten Start gestellt und damit gibt es dann keine Probleme mehr. Damit die Einstellung nicht bei jeder Updateinstallation verloren geht, macht das die Installation nun automatisch so (ab 4.3.45, das ich gerade hochgeladen habe).

Einen schönen Feiertag

Jochen

Und immer wieder die Zeitumstellung…

Leider gab es noch einen kleinen (glücklicherweise nur optischen) Bug im VCR.NET Recording Service: bei der Auswahl der Wochentage bei der Vorschauanzeige im Aufzeichnungsplan wurde in der Winterzeit (i.e. ab dem 25.10.2015) ein Tag zu früh angezeigt. So wäre es richtig:

plan

Die fehlerhafte Version zeigt allerdings zum Beispiel statt Di 27.10 Mo 26.10 an, beim Anklicken werden dann aber tatsächlich die Aufzeichnungen vom 27.10 gezeigt – sehr verwirrend, aber es ist wirklich nur die Beschriftung falsch.

Ich habe alle Downloads (bei mir und Heise) aktualisiert.

Jochen

VCR.NET Kontrollzentrum und Windows 10

Ich habe ein kleines Fehlverhalten im Zusammenspiel mit Windows 10 korrigiert (die Downloads des VCR.NET Recording Service wurden mit Version 4.3.40 aktualisiert): nach dem Aufwachen aus dem Schlafzustand konnte es vorkommen, dass in der Taskleiste ein aktives Fenster (im Allgemeinen ohne Icon) angezeigt wurde, das man (durch das Kontextmenü über die rechte Maustaste) leicht als das VCR.NET Kontrollzentrum identifizieren konnte.

Ich habe zwar nicht ganz verstanden, warum das unter Windows 10 so ist, aber der Fix läuft bei mir nun schon 10 Tage problemlos, so dass ich Euch das nicht weiter vorenthalten will.

Bye

Jochen

Windows 10 mag Visual Studio 2015 nicht – nanu!

Naja, ich muss das ein wenig relativieren. Nach einigen erfolgreichen Migrationen auf Windows 10 war nun gestern mein Arbeitsplatzrechner an der Reihe. Eine ziemlich alte Windows 7 32 Bit (wg. einer Nexus DVB-S TV Karte) Installation, auf der sich SEHR viel Krams im Lauf der Jahre angesammelt hat (e.g. mehrere Versionen Visual Studio, dazu SQL Server, Office, …). Der Upgrade auf Windows 10 Home dauert daher auch recht lange (klar, er muss ja die Features aus der Windows Installer Datenbank übernehmen) und dann, so nach ca. 100 Minuten bei 70% Gesamtfortschritt (90% Features & Treiber) stehe ich plötzlich am rien ne va plus…

Über dem großen Kreis mit dem Gesamtforschritt erscheint ein Windows Befehlszeilenfenster (!), ohne Inhalt mit dem Titel “Microsoft Visual C++ Runtime …” – leider ohne Versionsnummer. Es handelt sich offenbar (?) um den Versuch, irgendeine Visual C++ Runtime zu installieren. Jeder Versuch, das Fenster zu schliessen (Klick mit der Maus, ENTER im Fenster, Alt-F4) führt dazu, dass Windows 10 auf die Vorinstallation zurückfällt. Mist!

Nun habe ich leider eine ganze Reihe von C++ Runtime Versionen auf meinem Altsystem: 2005, 2008, 2010, 2012, 2013 und 2015. Ich hatte erst einmal die wirklich alten (2005 und 2008) im Verdacht und diese zusammen mit ähnlich alten Komponenten (e.g. SQL Compact 2005, 3.5 und 4.0) entfernt. Leider ohne Erfolg.

Im Windows 10 Setup Protokoll (setupact.log) gehörte der letzte Eintrag zum Visual Studio 2015, das ich kurz vorher (RTM wohlgemerkt) installiert und ausprobiert hatte. Also schweren Herzens (das hat fast 2 Stunden gedauert – Löschen von einer SSD, echt heftig) Visual Studio 2015 samt C++ 2015 Runtime deinstalliert und siehe da: die Windows 10 Installation läuft durch. Ich gehe davon aus, dass ich darauf auch wieder Visual Studio 2015 mit allem installieren kann, aber im Moment reicht es mir erst einmal – die Nerven 🙂

Ich hoffe, dass der Tipp dem einen oder anderen dabei hilft, Windows 7 etwas schneller als ich zu modernisieren!

Viel Spaß dabei

Jochen

JavaScript und Schutz vor unerwünschtem Zugriff auf Objekte

Der genaue Hintergrund meiner Fragestellung führt jetzt zu weit, aber letztlich bin ich auf diesen Artikel gestoßen. Nehmen wir einmal an, dass ich eine JavaScript Klasse aus einer Bibliothek in meinem Programm unverändert verwenden möchte. Im Beispiel könnte das etwa so aussehen:

var SomeClass = function () {
    function SomeClass(value) {
        this.value = value;
    };

    SomeClass.prototype.getValue = function () {
        return this.value;
    };

    SomeClass.prototype.setValue = function (newValue) {
        this.value = newValue;
    };

    return SomeClass;
}();

Das Programm selbst bietet eine Erweiterungsschnittstelle an, über die ein Anwender sich in bestimmte Abläufe einklinken kann. Allerdings soll er im Beispiel nur lesend auf den in einer Instanz gespeicherten Klasse zugreifen können (getValue), Änderungen (setValue, value) sind alleine meinem Programm erlaubt – gerade ein direkter Zugriff auf Eigenschaften kann natürlich einiges durcheinanderwerfen.

Der oben erwähnte Artikel erklärt sehr schön, welche Alternativen man hat, um tatsächlich das gewünschte Ergebnis zu erreichen. Am mächtigsten scheint der Einsatz von Closures (JavaScript Scopes) pro Objektinstanz zu sein. Allerdings erwähnt der Autor des Artikels dabei auch, dass es zu Geschwindigkeitseinbußen kommen wird – zudem der Artikel davon ausgeht, dass man die verwendete Bibliothek verändern kann. Hier einmal ein Alternativvorschlag respektive eine Ergänzung.

Im Endeffekt soll das Programm in der Lage sein, eine Kapselung (hier als Proxy bezeichnet) zu erzeugen, die auf keinem Weg einen Zugriff auf die Objektinstanz der Bibliothek zulässt. Die Erstellung der Kapselung könnte man sich so vorstellen – Details gleich:

// Einmalig ganz am Anfang
var someClassProxy = Context.registerProxyType(SomeClass, "getValue");

// Das wäre unser Bibliotheksobjekt, vielleicht auch nur einmalig erzeugt
var lib = new SomeClass(42);

// Hier brauchen wir irgendwo tief im Code die Kapselung
var proxy = Context.createProxy(test, someClassProxy);
try {
    extensionMethod(proxy);
} finally {
    proxy.destroy();
}

Ziel ist es, dass über die Kapselung nur die Methode getValue angeboten wird und zudem die Eigenschaften des JavaScript Objektes keine Rückschlüsse auf das Bibliotheksobjekt zulassen. Das wäre dann eine mögliche Lösung:

var Context = function () {
    function Context() {
    };

    var index = 0;
    var map = {};

    Context.createProxy = function (instance, factory) {
        if (instance === null)
            return null;
        if (instance === undefined)
            return undefined;

        var proxy = factory(index++);

        map[proxy.index] = instance;

        return proxy;
    };

    Context.registerProxyType = function () {
        var args = arguments;
        var type = args[0];

        var Proxy = function () {
            function Proxy(index) {
                this.index = index;
            };

            Proxy.prototype.destroy = function () {
                delete map[this.index];
            };

            for (var i = 1; i < args.length; i++) {
                var name = args[i];
                var fn = type.prototype[name];
                if (fn === undefined)
                    throw "no method " + name;

                Proxy.prototype[name] = function (fn) {
                    return function () {
                        var instance = map[this.index];
                        if (instance === undefined)
                            throw "proxy already disconnected";

                        return fn.apply(instance, arguments);
                    };
                }(fn);
            }

            return Proxy;
        }();

        return function (index) {
            return new Proxy(index);
        };
    };

    return Context;
}();

Mit der statischen registerProxyType Methode kann ich zu einer beliebigen Klasse einen Kapselungserzeuger (Factory) erstellen, der in der Kapselung nur die gewünschten Methoden offenlegt. In der Kapselung wird auch keine Referenz auf das Bibliotheksobjekt gespeichert, sondern nur eine laufende Nummer einer aktiven Kapselung - da könnte der Anwender in seiner Erweiterung dran herumspielen, erreicht dadurch aber maximal andere aktive Kapselungen. Durch das Closure (den Scope) ist vor allem map für den Anwender unerreichbar. createProxy erzeugt zu einem beliebigen Bibliotheksobjekt eine neue Kapselung - alternative Kapselungen ein und der selben Klasse für unterschiedliche Erweiterungsszenarien sind denkbar. Durch einen laufenden Index (ebenfalls im Closure) wird die Kapselung aktiviert, ein destroy Aufruf auf der Kapselung hebt die Aktivierung wieder auf - auch hier kann die Erweiterung pfuschen aber letztlich nur ihre eigene Aufgabe erschweren, niemals aber die Infrastruktur der Bibliotheksobjekte antasten.

Ok, das ist als Studie nur ein erster Gedanke. Sollte ich es denn wirklich einmal brauchen, kann man sicher noch vieles verfeinern - e.g. muss destroy wirklich eine Methode der Kapselung sein? Aber ich hoffe, dass auch in diesem groben Ansatz zumindest die Idee insbesondere als Erweiterung des eingangs erwähnten Artikels verständlich wird.

Happy Coding

Jochen