Klonen einer defekten Festplatte mit Acronis Home ohne Probleme

Ich selbst benutze Acronis als Datensicherungs Programm schon sehr lange. Zu Hause sind Acronis Home und meine Vista Rechner (Desktop + Laptop) ein gut eingespieltes Team.

Folgendes Erlebnis hat mich noch mehr von Acronis Home überzeugt:

  • Neulich beim Kaffeetrinken bei Freunden (absolute Computer-Laien) wird berichtet, dass ihr Rechner so langsam geworden wäre.
  • Nach einem Blick auf den XP SP2 Rechner und Analyse des Ereignisprotokolls stellt sich heraus, dass die Festplatte schon massenweise Fehler meldet. CHKDSK.EXE meldet eine sehr hohe Anzahl defekter Sektoren und läuft ewig.
  • OK! Neue Festplatte für einen Appel&Ei bei Ebay geordert.
  • Nach ein paar Tagen nachdem die Festplatte angekommen ist, von zu Hause Acronis Home als bootbare CD mitgenommen.
  • Neue Harddisk als Master an den zweiten IDE Channel angeschlossen.
  • Von CD Acronis gebootet.
  • Clonen der Festplatte angeschmissen.
  • Logisch: Nach ein paar Minuten die ersten Meldungen über Lesefehler. Alle ignorieren…
  • Acronis benötigt 4 Stunden für die Kopie, aufgrund der vielen defekten Sektoren (zwischendrin war die Prognose mal bei 17 Stunden)
  • Nach einem gemütlichen Ausflug und Kaffeetrinken ist der Clone-Vorgang fertig.
  • Alte Festplatte abgeklemmt, neue an IDE Channel 1 als Master.
  • Nichts sonst gemacht, Rechner bootet, alles toll und prima und der Rechner ist wieder so schnell wie dazumals.
  • Freund und Ehefrau wieder glücklich(er)… 🙂

Einfach genial. So einfach und simpel hatte ich mir das ehrlich gar nicht vorgestellt. Ich war absolut positiv überrascht, da ich mich auch nicht für den genialen Hardware Bastler halte.

Wenn ich solche Festplattenwechsel gemacht habe, hatte ich bisher immer eine Neuinstallation vorgenommen, was sich bei mir auch meistens gelohnt hat. Bei meinen Freunden, wäre es unnötig gewesen, für das bisschen Word, Excel, Vokabeltrainer der Kiddys und Onlinebanking.

Für das Geld was dieses Acronis Home kostet ist es ein absolut geniales Rundum-Sorglos-Programm…

CLIP.EXE der nette kleine Helfer unter Vista

Wer wollte nicht schon mal ganz schnell die Ausgabe eines Befehlszeilen Tools in der Zwischenablage haben. OK man kann einen Bereich mit dr Maus im Konsolenfenster markieren, aber was macht man wenn es um eine 2000 Zeilen Ausgabe geht?

Unter Vista ist das ganz einfach, man benützt einfach eine Pipe und CLIP.EXE!

DIR | CLIP

Siehe da. Man hat den gesamten Text in die Zwischenablage gepipet.
Was CLIP macht verrät es wenn man einfach mal CLIP /? ausführt.

CLIP

Beschreibung:
    Leitet die Ausgabe von Befehlszeilenprgrammen in die
    Windows-Zwischenablage um.
    Diese Textausgabe kann in andere Programme eingefügt werden.

Parameterliste:
    /?                  Zeigt diese Hilfe an.

Beispiele:
    DIR | CLIP     Erstellt eine Kopie des aktuellen Verzeichnis-
                         inhalts in der Windows-Zwischenablage.

    CLIP < README.TXT   Erstellt eine Textkopie von readme.txt
                         in der Windows-Zwischenablage.

BTW: Jeder 4NT bzw. TCC/LE Nutzer kennt natürlich schon längst den CLIP: Device! Diejenigen mussten auf solch ein Helferlein auch nicht bis Vista warten. Damit kann man das ganze auch einfach so

DIR > CLIP:

machen.

Die Return-Taste in Dialogen, eine unendliche Geschichte

Wer sich in Windows-Programmierer-Foren tummelt, dem wird die folgende Frage mindestens einmal in der Woche über den Weg laufen:

Ich möchte in einem Dialog die Eingabetaste abfangen, so dass sich der Dialog nicht schließt.
Wie geht das?

Vom Sinn und Unsinn dieses Wunsches wollen wir mal hier nicht reden. Also schauen wir mal auf dieses Problem etwas genauer.

Die Lösung WM_COMMAND mit IDOK abfangen, lasse ich nicht gelten , denn evtl. hat der Dialog ja einen OK Button. (In der MFC käme das mit dem Überschreiben von CDialog::OnOK gleich)

Die Standardantwort von MFC Entwicklern lautet immer:

Überschreibe PreTranslateMessage und fange WM_KEYDOWN mit VK_RETURN dort ab und behandle die Nachricht dort.

OK. Aber was macht ein Win32-API Entwickler. Der hat keinen Einfluss auf die Message-Loop. Muss der nun zu der Hook-Kanone greifen?

Wo liegt eigentlich das Problem?
Die Funktion, die VK_RETURN in ein WM_COMMAND mit IDOK umwandelt ist die API Funktion IsDialogMessage. Diese Funktion wird in der Messageloop von modalen Dialogen verwendet. In der MFC direkt in CDialog::PreTranslateMessage und in Win32 Dialogen wird sie in der Messageloop die DialogBox ausführt.

Diese Funktion geht aber mit solchen Tastatureingaben nicht einfach wahllos um. Sie macht das sehr intelligent. Das sieht man schon daran, dass man in einer aufgeklappten ComboBox die Eingabetaste drücken kann und es schließt die ComboBox und nicht der Dialog.
Ebenfalls kennt man den Effekt, dass ein mehrzeiliges Eingabefeld (Edit Control) sehr wohl die Eingabetaste als Zeilenschaltung nutzen kann und auch hier schließt der Dialog nicht.
Kennt also IsDialogMessage seine Pappenheimer von Controls?

Woher weiß IsDialogMessage also wann VK_RETURN mal so und mal so behandelt werden muss?
Die Antwort ist einfach: IsDialogMessage fragt seine Controls ab was sie gerne hätten!
Und das wird erreicht mit einer einfachen Windows-Nachricht, die in diesem Zusammenhang fast nie genannt wird: WM_GETDLGCODE.

Bevor IsDialogMessage eine Tastatureingabe selbst behandelt, fragt die Funktion das Zielfenster mit WM_GETDLGCODE ab, ob das Fenster evtl. selbst Verwendung für diese Tastatureingabe hat.
WM_GETDLGCODE kann hier sehr flexibel reagieren, denn in wParam erhält die Nachricht den virtuellen Tastencode und das Control weiß nun sehr genau um was es hier geht.

Kann man also in jedem Control (das natürlich den Fokus hat) die Eingabetaste selbst behandeln?
Antwort: Ja!

Das Control muss nur einfach WM_GETDLGCODE behandeln für die Taste VK_RETURN. In diesem Fall gibt es DLGC_WANTMESSAGE zurück (ist übrigends identisch zu DLGC_WANTALLKEYS). IsDIalogMessage wird in diesem Fall die Eingabetaste an das Control weitergeben und nicht selbst behandeln. So macht es übrigens auch eine ComboBox die aufgeklappt ist wenn die Eingabetaste gedrückt wird.

Ich habe einfach mal hier eine Win32 Lösung aufgebaut. Es wird einfach das entsprechende Control mit einer eigenen WndProc gesubclassed und das sieht etwa so aus:

LRESULT CALLBACK SpecialWndProc(HWND hWnd,
                        UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_GETDLGCODE:
        if (wParam==VK_RETURN)
            return DLGC_WANTMESSAGE;
        break;
    case WM_KEYDOWN:
        if (wParam==VK_RETURN)
        {
            MessageBox(hWnd,_T("VK_RETURN received!"),NULL,MB_OK);
            return 0;
        }
        break;
    }
    WNDPROC pWndProc = reinterpret_cast(GetWindowLongPtr(hWnd,GWL_USERDATA));
    return CallWindowProc(pWndProc,hWnd,message,wParam,lParam);
}

...
// Subclass the control
HWND hWndEdit = GetDlgItem(hDlg,IDC_EDIT1);
LONG_PTR pOldWndProc = SetWindowLongPtr(hWndEdit,GWL_WNDPROC,
                        reinterpret_cast(SpecialWndProc));
SetWindowLongPtr(hWndEdit,GWL_USERDATA,pOldWndProc);

Effekt: Jedes Control, dass man mit dieser WndProc subclassed wird die Messagebox anzeigen und der Dialog wird nicht geschlossen! Subclassed man also alle Controls eines Dialoges, die den Fokus bekommen können, dann kann man sofort ohne Hook, auch die Eingabetaste selbst behandeln.
Sinnvollerweise sendet man bei Erhalt von VK_RETURN dann einfach eine entsprechende Nachricht an das Parent, dass die gewünschte Aktion dann ausführt, sofern nicht das Control selbst die Eingabetaste direkt behandelt.

Man kommt also auch in reinen Win32 API Programmen ganz ohne Hooks aus, um VK_RETURN in Dialogen so zu behandeln wie man es selbst gerne möchte!

Bookmark on MSDN auch auf meiner Seite

Social Bookmarking V1 wurde ja gerade veröffentlicht, wie Kay Giza berichtete.

In meinem Blog auf der rechten Seite unter dem Blog-Info habe ich mal gleich mal das neue MSDN Bookmark Widget eingebaut. Ich bin mal gespannt wer es benutzen wird.

Der Einbau ist einfach. Man fügt nur den nachfolgenden Skript Code auf seiner HTML Seiten ein.

<script src="http://Services.social.microsoft.com/widgets/bookmark.jss?
type=1&brand=Msdn&locale=1031" type="text/javascript"></script>

So ist das ganze auch auf dieser Tools Seite beschrieben.
Was leider nicht dokumentiert ist und ich nur durch herumprobieren hinbekommen habe ist die Bedeutung des Type Parameters. Der Type Parameter hat folgenden Einfluss auf die Darstellung des Links.

  • Mit Type=0 erhält man nur ein Icon
  • Mit Type=1 erhält man das Link Icon inkl. dem Text Bookmark on MSDN

Wie man sieht habe ich mich für Type=1 entschieden.

Über was es nicht alles RFCs gibt

Durch Zufall bin auf diesen uralten RFC aus dem Jahre 1996 gestoßen.
Man beachte das Datum der Veröffentlichung!
http://www.apps.ietf.org/rfc/rfc1925.html

Besonders stark finde ich Abschnitt (3) bzgl. der fliegenden Schweine 🙂

BTW: Eine Liste aller 1. April RFCs gibt es hier
http://www.apps.ietf.org/rfc/apr1list.html

Dialog basierende MFC-Anwendungen einmal anders

Ich habe mich zwar gerade erst darüber ausgelassen, dass man dialog basierende Anwendungen gar nicht braucht (sieh hier), aber ganz und gar unsinnig sind sie ja nicht.

Bei mir ist der häufigste Anwendungsfall eine simpler Dialog, der nur zum Steuern eines Programmes dient, das ein Icon in der Taskleiste abablegt.

Ärgerlich ist dann nur, dass man nicht vermeiden kann, dass beim Start der Anwendung der Dialog kurz aufflackert, bevor man ihn mit einem Timer oder mit PostMessage und einer benutzerdefinierten Nachricht wieder versteckt.

Aber es geht viel einfacher und dazu noch in einer Form, die der MFC-Konstruktion besser entspricht, als das Gerüst, das der Applikations-Wizard erzeugt.
Ich möchte das hier einfach kurz erläutern:

1. Erzeuge ich eine normale dialog basierende Anwendung mit dem Wizard.

2. Dann lege ich ein Objekt der Dialog Klasse mit dem Namen m_dlg in der CWinApp Klasse an. Ich möchte damit erreichen, dass die Dialogklasse so lange existiert wie die Applikation und nicht mehr nur als lokale Variable in InitInstance auftaucht.

3. Der gesamte Code, den der Wizard erzeugt hat:

CTestDLGDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
    // TODO: Place code here to handle when the dialog is
    // dismissed with OK
}
else if (nResponse == IDCANCEL)
{
    // TODO: Place code here to handle when the dialog is
    // dismissed with Cancel
}

wird ersetzt durch:

// Create the Dialog
if (m_dlg.Create(CMyDlg::IDD))
{
    m_pMainWnd = &m_dlg;
    return TRUE;
}
else
    return FALSE;

4. Kleine Schönheitskorrektur nun. Man verlagert das Laden des Applikations-Icons aus dem Konstruktor des Dialogs nach OnInitDialog.

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

Fertig ❗

Kurz erklärt: Aus dem modalen Dialog der durch DoModal gestartet wird wird nun ein modaler Dialog, der durch die Messageloop der CWinApp::Run gesteuert wird. Von der sonstigen Funktionsweise ändert sich nichts.
Dieser Konstrukt hält sich nach meiner Meinung weit mehr an das MFC Gerüst, als die Anwendung, die der Wizard erzeugt.
Die Vorteile sind schnell aufgezählt:

  1. InitInstance wird durchlaufen und CWinApp:Run wird verwendet.
    Dies hat z.B. zur Folge, dass auch CWinApp::OnIdle durchlaufen wird und temporäre Map Objekte entsorgt werden. (siehe Kommentar unten)
  2. Man kann die Applikation ohne Flackern zu dem Moment sichtbar machen an dem man es möchte. Dazu muss man nur das WS_VISIBLE Flag im Dialogtemplate entfernen und ShowWindow aufrufen, wenn es einem passt.

Vielleicht sehen ja andere Leser noch mehr Vorteile… die Diskussion ist eröffnet 😉

PS: Noch ein kleiner Nachtrag zu den oben erwähnten temporären Handle Maps in einer dialog basierenden Applikation. Diese temporären Handlemaps werden automatisch aufgeräumt und gelöscht wenn CWinApp::OnIdle ausgeührt wird. Das ist normalerweise der Fall wenn in CWinApp::Run keine Nachricht in der Messagequeue liegt, die abgearbeitet werden muss (PeekMessage gibt FALSE zurück). Im Gegensatz dazu werden Handlemaps nicht gelöscht wenn die Nachrichtenschleife mit CWnd::RunModalLoop für einen modalen Dialog ausgeführt wird. So also auch niemals in einer dialog basierenden Anwendung, oder wenn ein modaler Dialog in einer MFC-Applikation ausgeführt wird!
Das fast noch mal einen Artikel wert…

Manche ungenaue Dokumentation nervt einfach

Die MSDN ist eines der größten und besten Nachschlagewerke, die ich kenne, allerdings gehen mir auch seine Unzulänglichkeiten ab und zu auf die Nerven (und hier meine ich nicht die funktionellen Defizite, sondern die inhaltlichen)!

Das sind dann ganz besonders die kleinen Sachen, die einem das Leben leicht machen könnten, die dann nicht „vollständig“ dokumentiert sind.

Beispiel:
Die MFC List-Container (z.B. CObList). Wir lesen in der Doku zu InsertAfter:

position
A POSITION value returned by a previous GetNext, GetPrev, or Find member function call.

Gut! Aber da steht nichts zu NULL. 😕
Aber wenn ich genauer darüber nachdenken, kann GetNext und Find auch NULL zurückgeben…
Was passiert also wenn ich NULL als Argument für position?
Mein Verstand sagt mir: „Es wird ein Element am Ende eingeführt!“ und ein Blick in den Code bestätigt den Verdacht.

Warum steht in der Doku nicht gleich, dass InsertAfter mit NULL als position ein AddTail ausführt?
Wer weiß wieviele Entwicler solchen „unnützen“ Code aufgrund der mangelnden Doku geschrieben haben:

CStringList lst;
FillMyList(lst);
POSITION pos = lst.Find(_T("Anything"));
if (pos==NULL)
    lst.AddTail(_T("Something to insert"));
else
    lst.InsertAfter(pos,_T("Something to insert"));

Es würde ja genügen wie folgt zu schreiben:

CStringList lst;
FillMyList(lst);
POSITION pos = lst.Find(_T("Anything"));
lst.InsertAfter(pos,_T("Something to insert"));

Korrespondierend ist die Doku von CObjList::InsertBefore genauso unvollständig.
Wird NULL als Position verwendet wird hier ein AddHead ausgeführt.

PS: Mich ärgert auch jedesmal wenn einer meiner Kollegen solchen Code schreibt:

CSomeObject *p = NULL;
...
// Conditional create
if (SomeThing())
     p = new CSomeObject();
...
// Cleanup
if (p)		// Category meaningless
    delete p;
  1. Warum der Test auf !=NULL?
  2. Warum wird kein Autopointer verwendet, der das auch Exception-Save gemacht hätte?

Die Unsitte dialogbasierende Anwendungen zu bauen statt SDI mit CFormView zu verwenden

Es scheint mir meistens ein Anfängerfehler zu sein, dass viele MFC Entwickler (oder solche die es werden wollen) zuerst mal zu einer dialogbasierenden Anwendung greifen.
Ist ja auch nett. Man kümmert sich nur um die paar Dialogfelder und hat kein Doc/View zu verwalten.

Am Ende kommen aber dann noch weitere Wünsche:

  • Ich hätte gerne ein Menü
  • Ich hätte gernenoch einen Toolbar
  • Ich hätte gerne einen Status Bar
  • Schön wäre ein Accelerator

Triviales und nicht triviales schließt sich an:

  • Warum kann ich kein Command/Routing für meinen Toolbar und mein Menü verwenden?
  • Warum schließt mein Dialog bei Nutzung Eingabe-Taste?
  • Kann ich meinen Dialog auch resizen?
  • Die Daten sollen auch gespeichert werden, wie geht das?
  • Ich hätte gerne so einen schönen MFCNext Toolbar in meinem Dialog, oder ein Ribbon, geht das?
  • … (die Liste ist bestimmt nicht vollständig)

Gibt man dann die Antwort, dass man x Klimmzüge machen muss um so etwas in eine dialogbasierende Anwendung einzubauen (wenn es überhaupt geht), dann erntet man noch noch die stöhnende Klage: „Ohhh Mann! Ist das kompliziert!“

Und all das geht nur mit Mühe in einen CDialog einzubauen. Der Grund ist einfach: Das Commandrouting für all diese Elemente ist in CFrameWnd integriert. Aber ein CDialog leitet sich von CWnd ab und ist von Grunde auf für keine dieser Funktionen vorbereitet.

Dabei könnte alles so einfach sein!
Man muss nur einfach eine SDI Applikation mit einem CFormView erzeugen und alle die Wünsche die mancher später hat, kann man sofort erfüllen und wenn man es wirklich nicht will auch weglassen.

Die Frage stellt sich für mich also:
Warum nicht einfach immer gleich eine SDI/CFormView Anwendung bauen ❓
Das Potential dieser Anwendungsform ist einfach unerreichbar verglichen mit einer dialogbasierenden Anwendung.

Also sollte man sich mal die Liste der Wünsche, die ich hier aufgestellt habe ansehen und als Checkliste betrachten. Sollte einer dieser oben aufgeführten Punkte für die Applikation wichtig sein, würde ich dringend anraten zum SDI/CFormView zu greifen.
Das ist auch der Fall, wenn diese Anforderungen erst später integriert werden soll. Oft genug ist ja die dialogbasierende Anwendung schon fertig und es heißt dann: Ich möchte doch nur noch…

PS: Ich persönlich benutze nicht mal mehr zu Testzwecken dialogbasierende Anwendungen 😉

Aufflackern eines Konsolenfensters bei Nutzung system und _popen

Immer wieder kommt die Frage auf, warum sich ein Konsolenfenster kurz öffnet wenn man eine Windows Anwendung, wie z.B. Notepad mit den CRT Funktion system startet.

Die Antwort ist ganz einfach, dazu muss man einfach mal nicht einmal unbedingt einen Blick in die Sourcen werfen, denn es ist sogar richtig für system dokumentiert in der MSDN.

The system function passes command to the command interpreter, which executes the string as an operating-system command. system refers to the COMSPEC and PATH environment variables that locate the command-interpreter file (the file named CMD.EXE in Windows 2000 and later). If command is NULL, the function simply checks to see whether the command interpreter exists.

Also kurz und bündig: Es wird zwangsläufig immer ein Konsolenfenster geöffnet. Das verschwindet zwar sofort wieder, wenn man eine GUI Applikation startet, aber das kann man vermeiden indem man gleich ShellExecute verwendet.

Ganz anders sieht es mit der Doku bei _popen aus. _popen scheint sich anzubieten, um die Ausgaben eines Tools in eine Datei umzuleiten. Aber auch _popen nutzt wie system CMD.EXE /c (COMSPEC). Um das heraus zu bekommen muss man allerdings den Source Code der CRT zu Rate ziehen. Das bedeutet, dass auch bei Verwendung von _popen ein Flackern durch ein Konsolenfenster nicht ausbleibt.

Wie man es richtig macht, wenn man die stdin/stdout umleiten will findet man in den wohlbekannten Artikeln der MSDN http://support.microsoft.com/kb/190351 und http://msdn.microsoft.com/en-us/library/ms682499.aspx. Durch die Verwendung von CreateProcess lässt sich auch ganz vermeiden, dass der zweite Prozess angezeigt wird.

Dr. Watson starb unter Vista…

… und es war nicht etwa wieder Prof. Dr. Moriarty :mrgreen:

Wenn man unter Vista einen Crashdump benötigt dann sucht man DRWTSN32.EXE unter Vista vergeblich. Für die Qualitätssicherung sind mir Minidumps immer extrem wichtig.

Es stellt sich die nette Frage: Wie kommt man von einem Kunden dann an einen informativen Minidump, wenn man keinen WER-Account hat, oder das Programm nicht signiert war, oder gar der WER Server diese Dumps nicht anfordert?

Unter Vista ist alles noch einfacher und schwieriger geworden. Vista speichert leider nicht grundsätzlich Minidumps, aber es legt für Crashs unter Problemberichte und Lösungen einen eigenen Eintrag an. Zu Crashs von WER registrierten Programme werden hier evtl. direkt Lösungen oder Updates angeboten. Und auch Crashdumps werden hier mit abgelegt, wenn sie erzeugt werden..

So ist es unter Vista aus:

  1. Das WER System in Vista erzeugt normalerweise nur Minidumps für signierte Programme bzw. wenn der WER Server einen Crash abruft.
  2. Um immer einen Minidump zu erhalten muss in der Registry der folgende Wert gesetzt werden:
    HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\ (DWORD)  mit Namen ForceQueue  erzeugen und auf 1 setzen.
  3. Dumps werden im Benutzerverzeichnis unter C:\Users\TheUserName\AppData\Local\Temp und hier C:\ProgramData\Microsoft\Windows\WER\ReportQueue abgelegt und sind meistens gepackt. Sie erhalten die Endung *.mdmp.
  4. Der Zugriff kann ganz einfach erfolgen mit Systemsteuerung -> System und Wartung -> Problemberichte und Lösungen -> Probleme anzeigen und überprüfen
  5. Dort findet man das entsprechende Programm und die dazugehörigen entsprechenden Crashs.
  6. Weitere Infos einfach über Details anzeigen lassen.
  7. Wenn es einen Dump gibt, dann findet man hier wieder einen Eintrag Temporäre Kopie dieser Dateien anzeigen
  8. Damit lässt sich der Explorer öffnen und man erhält Zugriff auf die gespeicherten Daten.
  9. Diese kann man sich nun als Entwickler zusenden lassen.

Siehe auch: