Archiv

Archiv für März, 2011

Fehlercode 8004402F beim Installation von Sp1 auf Windows 7

23. März 2011 5 Kommentare

Seit einigen Tagen versuche ich das Servicepack 1 (KB976932) von Windows 7 zu installieren. Immer ohne Erfolg. Der Vorgang startet ganz normal, aber beim Neustart des Rechners läuft die Konfiguration zügig auf 99% hoch, bevor ein Fehler auftritt und alles wieder rückgängig gemacht wird.

Da das ganze ca. eine Stunde dauert, ist jeder Test schwierig und einfach aufwändig. Im Ereignisprotokoll oder WindowsUpdate.log waren leider keine sinnvollen Hinweise zu finden, lediglich kurz nach dem Hochfahren wird der Fehlercode 8004402F angezeigt. Ein ähnliches Problem brachte dann auch noch die Installation vom Internet-Explorer 9.

Glücklicherweise habe ich heute einen recht alten Blog-Beitrag für Windows Vista gefunden, der dann auch half. Mein %TEMP% Ordner war auf Laufwerk D umgestellt. Dieses Laufwerk ist aber ein verschlüsseltes TrueCrypt-Laufwerk, was beim Neustart nicht zur Verfügung steht. Ich habe diesen Ordner wieder auf eine unverschlüsselte Festplatte umgelenkt, und die Installation war erfolgreich.

Schade, dass hier nirgends ein entsprechender Fehler ausgegeben wird. Beim Starten der Installation hätte mir der Hinweis auf einen nicht verfügbaren Temp-Ordner viele Stunden der Suche erspart.

Erweiterung von INotifyPropertyChanged (PostSharp)

17. März 2011 4 Kommentare

Mit PostSharp bekommt man eine mächtige Möglichkeit, Code mittels Attributen aufzupeppen. So wird man auch in die Lage versetzt, wiederkehrenden Code zu vermeiden. Üblicherweise sieht nämlich beispielsweise eine Implementation von System.ComponentModel.INotifyPropertyChanged wie folgt aus:

public class Test: System.ComponentModel.INotifyPropertyChanged
{
    private string _myProp;
    public string MyProp
    {
        get { return _myProp; }
        set
        {
            if (_myProp == value) return;
            _myProp = value;
            OnPropertyChanged("MyProp");
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    public void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Verwendet man jedoch PostSharp als Referenz in seinem Projekt und die Klasse NotifyPropertyChangedAttribute aus

{ProgramFiles}\PostSharp 2.0\Samples\.NET Framework 3.5\CSharp\NotifyPropertyChanged

kann man seinen Code merklich verkürzen:

[NotifyPropertyChanged]
public class TestBase
{
    public string MyProp { get; set; }
}

Problem
Leider ergibt letztere Implementation das Problem, dass ich die Kontrolle über das Auslösen von Events vollständig an das Attribut NotifyPropertyChanged abgebe. Da der Code für das Event nachträglich in das Compilat injiziert wird, ergibt sich keine Möglichkeit, das Event PropertyChanged manuell auszulösen, da .NET das Auslösen von Events nur innerhalb der implementierenden Klasse erlaubt. Versuche, Zugriff auf das Event durch Vorimplementierung des Interfaces zu erhalten, helfen leider auch nicht, da der durchs Attribut erzeugte Code in einer Property der Klasse zusätzlich angelegt wird. Dies kann man leicht mit dem Reflektor prüfen:

public string MyProp
{
    [CompilerGenerated]
    get
    {
        return this.<get_MyProp>();
    }
    [CompilerGenerated]
    set
    {
        LocationInterceptionArgsImpl<string> CS$0$1 = new LocationInterceptionArgsImpl<string>(this, Arguments.Empty);
        CS$0$1.Location = <>z__Aspects.l3;
        CS$0$1.TypedBinding = <MyProp>c__Binding.singleton;
        CS$0$1.TypedValue = value;
        this.<>z__aspect0.OnPropertySet(CS$0$1);
    }
}

Das Setzen der per Attribut erweiterten Property wird beispielsweise komplett auf z__apect0 umgeleitet. Und an genau dieses z__apect0 ist ja zur Entwurfszeit noch nicht verfügbar (das ist ja der Sinn des Attributes).

Umgehen konnte ich das Problem mit einer kleiner Erweiterung des NotifyPropertyChangedAttribute:

[ImportMember("ManualPropertyChanged", IsRequired = false,
		Order = ImportMemberOrder.AfterIntroductions)]
public Event<PropertyChangedEventHandler> ManualPropertyChanged;
 
public override void RuntimeInitializeInstance()
{
	base.RuntimeInitializeInstance();
	if (ManualPropertyChanged != null)
		ManualPropertyChanged.Add((sender, args) => 
		{ if (PropertyChanged != null) PropertyChanged(Instance, args); });
}

Bietet meine Klasse, welche das NotifyPropertyChangedAttribute ausweist, folgendes Ereignis an:

public event PropertyChangedEventHandler ManualPropertyChanged;

so abonniert das Attribut dieses Ereignis und sorgt beim Auslösen von ManualPropertyChanged automatisch für eine Weiterleitung an das Ereignis PropertyChanged.
kick it on dotnet-kicks.de

KategorienMicrosoft .NET Tags: ,