Der X-mas 2007 Relaunch

Wie Weihnachten 2006 im Internet gezeigt hat, heißt das Weihnachten 2007 nicht mehr Weihnachten, sondern X-mas, also muss der Weihnachtsmann auch X-man sein! Da X-mas 2007 quasi schon vor der Tür steht, war es spätestens ab März höchste Zeit, mit der Weihnachtsvorbereitung zu beginnen – Verzeihung: das diesjährige Weihnachts-Roll-Out zu starten und die Christmas-Mailing-Aktion just in Time vorzubereiten. Hinweis: Die Kick-Off-Veranstaltung (früher 1. Advent) für die diesjährige SANCROS (SANta Claus Road Show) findet bereits am 29. November statt. Daher wurde das offizielle Come-Together des Organizing Committees unter Vorsitz des CIO (Christmas Illumination Officer) schon am 6. Januar 2007 abgehalten.

Erstmals haben wir ein Projektstatus-Meeting vorgeschaltet, bei dem eine in Workshops entwickelte „To-Do-Liste“ und einheitliche Job Descriptions erstellt wurden. Dadurch sollen klare Verantwortungsbereiche, eine powervolle Performance des Kundenevents und optimierte Geschenk-Allokation geschaffen werden, was wiederum den Service Level erhöht und außerdem hilft, „X-mas“ als Brandname global zu implementieren. Dieses Meeting diente zugleich dazu, mit dem Co-Head Global Christmas Markets (Knecht Ruprecht) die Ablauf-Organisation abzustimmen, die Geschenk-Distribution an die zuständigen Private-Schenking-Centers sicherzustellen und die Zielgruppen klar zu definieren. Erstmals sollen auch so genannte Geschenk-Units über das Internet angeboten werden.

Die Service-Provider (Engel, Elfen und Rentiere) wurden bereits via Conference Call virtuell informiert und die Core-Competences vergeben. Ein Bündel von Incentives und ein separater Team-Building-Event an geeigneter Location sollen den Motivationslevel erhöhen und gleichzeitig helfen, eine einheitliche Corporate Culture samt Identity zu entwickeln. Der Vorschlag, jedem Engel einen Coach zur Seite zu stellen, wurde aus Budgetgründen zunächst gecancelt. Stattdessen wurde auf einer zusätzlichen Client Management Conference beschlossen, in einem Testbezirk als Pilotprojekt eine Hotline (0,35 Ct/Minute) für kurzfristige Weihnachtswünsche einzurichten, um den Added Value für die Beschenkten zu erhöhen.

Durch ein ausgeklügeltes Management Information System (MISt) ist auch Benchmark-orientiertes Controlling für jedes Private-Schenking-Center möglich. Nachdem ein neues Literatur-Konzept und das Layout-Format von externen Consultants definiert wurde, konnte auch schon das diesjährige Goldene Buch (Golden Book Release 00.1) erstellt werden. Es erscheint als Flyer, ergänzt um ein Leaflet und einen Newsletter für das laufende Updating. Hochauflagige Low-cost-Giveaways dienen zudem als Teaser und flankierende Marketingmaßnahme. Ferner wurde durch intensives Brainstorming ein Konsens über das Mission Statement gefunden. Es lautet: „Lets Keep the Candles Burning“ und ersetzt das bisherige „Frohe Weihnachten“. Santa Claus hatte zwar anfangs Bedenken angesichts des Corporate-Redesigns, akzeptierte aber letztlich den progressiven Consulting-Ansatz und würdigte das Know-how seiner Investor-Relations-Manager.

In diesem Sinne noch erfolgreiche X-mas Preparation für das Jahr 2007.

– Quelle unbekannt –

Die Unsitte in WM_CONTEXTMENU keine Tastaturnutzer zu berücksichtigen

Das viele Programmierer nur an die Maus denken, wenn Sie Kontextmenü hören ist schon an meinem letzten Blog Artikel klar geworden. 

Dennoch überraschen mich immer wieder Programm, die zwar korrekt auf die Kontextmenü-Taste (bzw. Umschalt+F10) reagieren, aber dann ein Kontextmenü links oben in der Ecke meines Monitors aufklappen.

OK! Es wurde verstanden, dass es eine WM_CONTEXTMENU Nachricht gibt, dass aber intelligentes Handling für Tastaturbenutzer anders aussieht, als für einen Mausbenutzer wird sehr selten verstanden oder berücksichtigt.

❗ Nehmen wir mal ein Beispiel:
Gegeben sei ein List View Control. Der Benutzer hat den Fokus auf diesem Control und drückt nun die Kontextmenütaste bzw. die Tasten Umschalt+F10.

❓ Frage: Was währe nun ein angemessenes Verhalten?

Wer die Doku gelesen hat wird wissen, dass in diesem Fall als Koordinaten (-1,-1) mit der WM_CONTEXTMENU Nachricht übermittelt werden. Dies ist nun der Grund dafür, dass viele Kontextmenüs nun in der linken oberen Ecke aufklappen, weil viele Entwickler eben nicht lesen (können), oder sich keine Gedanken machen, dass es einen Unterschied macht Mausbenutzer zu sein oder Tastaturbenutzer.

(-1,-1) ist keine geeignete Position für das Kontextmenü!

Nun die Mausposition zu bestimmen, wäre meiner Meinung nach, auch nicht angemessen. Denn der User benutzt diese ja gar nicht, und hat sie evtl. sogar einfach an den Bildschirmrand geschoben. Das Kontextmenü dort aufpoppen zu lassen wäre genauso falsch.

Einzig richtig wäre es den aktuell selektierten Eintrag mit dem Fokus im List View zu bestimmen und das Popupmenü knapp darunter und leicht rechts versetzt davon anzuzeigen. Dem Benutzer wäre der Kontextbezug sofort klar und auch seine Augen müssten nicht erst an eine andere Bildschirmposition wandern um zu erfassen, was nun möglich ist

Im Klartext heißt das für den Entwickler: selektiertes Item suchen (LVM_GETNEXTITEM), dessen Bildschirmposition Position zu bestimmen (LVM_GETITEMRECT) und sich eine gute alternative zu überlegen, wenn das Item außerhalb des sichtbaren Bereiches ist (z.B. Mitte des Controls).

Fazit: Um Kontextmenüs auch mit der Tastatur bedienbar zu machen gehört etwas mehr Grips und Aufwand dazu, als nur eine Popupmenü an einer bestimmten Koordinate anzuzeigen.

Die Unsitte WM_RBUTTONDOWN statt WM_CONTEXTMENU zu verwenden

Ich freue mich jedesmal, wenn ich ein Programm benutze und ein Kontextmenü öffnen will und es öffnet sich nicht.

„Ja da hast Du wohl nicht mit der rechten Maustaste geklickt, sonst würde es sich öffnen!“

werden jetzt einige sagen.
Und ja es stimmt, ich habe nicht mit der rechten Maustaste irgendwohin geklickt sondern die Kontextmenü-Taste rechts unten auf meiner Tastatur benutzt. Und wer es noch nicht wusste Umschalt+F10 löst die selbe Funktion aus.

Falls es also noch jemand nicht bemerkt haben sollte. Microsoft hat in der Windows API direkt eine Nachricht nur für die Behandlung von Kontextmenüs reserviert und die heißt: WM_CONTEXTMENU! Und es sollte jedem Entwickler bereits in Fleisch und Blut übergegangen sein, diese Nachricht und nichts anderes für Kontextmenüs zu verwenden.

Der nette Nebenbonus dieser Nachricht, ist, dass man sich nicht um jedes Fenster alleine kümmern muss. WM_CONTEXTMENU wird an das Elternfenster weitergereicht, wenn ein Kindfenster diese Nachricht nicht behandelt. Das macht es auch einfach für Dialoge einen zentralen Handler zu bauen.

Hexeditoren

Seit Jahren habe ich Frhed als Hexeditor verwendet und man ist ja oft relativ unflexibel und schaut sich nichts Neues an, wenn man zufrieden ist mit dem was man hat. Zudem ja auch Visual Studio und auch mein TextPad Funktionen für das Arbeiten im binären Modus haben.

Jetzt bin ich doch auf etwas Neues gestoßen in Sachen Hexeditor und das ist HxD.
Er ist wirklich einen Blick Wert.

  • Schön ist gerade die Export-/Copy-Funktion, mit der man schnell mal binäre Daten in C Syntax erhält, oder auch HTLM für eine Doku.
  • Man kann einfach mal so in andere Prozesse reinsehen,
  • oder mal kurz die Festplatte „demolieren“.

Zum Rumschnüffeln und auch professionelles Arbeiten ein wirklich nettes Tool.

Die Unsitte immer GetModuleHandle(NULL) für hInstance in CreateWindow und RegisterClass zu verwenden

Carsten hat mich dazu inspiriert noch ein wenig mehr Don Quichotte zu spielen und gegen Windmühlen zu kämpfen: Damit hier mein zweiter Beitrag zum Thema Unsitten.

Der hInstance Parameter in CreateWindow(Ex) und RegisterClass (WNDCLASS) wird oft genug nicht verstanden. Man braucht für diese Funktionen einen HINSTANCE Wert. Den hat aber niemand in der Tasche, wenn man mit der Win32 API pur mal eben so ein Programm schreibt. Die wenigsten kommen auf die Idee den hInstance Wert aus WinMain und DllMain irgendwo global zu speichern und zu verwenden. Globals sind ja irgendwie „böse“, und nicht OOP-like… 😉

Was also tun? Irgendein Unwissender empfiehlt einfach GetModuleHandle(NULL) zu verwenden und seit dem dieser Unwissende diesen Tipp in die Welt gesetzt hat kursiert er durch die Foren… unaufhaltsam…

❗ Das Problem: Es geht… manchmal… aber portabel ist der Code damit nicht und man erlebt eigentümliche Sachen damit an anderer Stelle unter annderen (DLL-)Umständen. Aber warum?

Das Geheimnis steckt darin, dass Fensterklassen nicht einfach so unter ihrem Namen abgelegt werden, sondern unter einem Namen und der hInstance, die bei RegisterClass mit angegeben wird. So hat jeder Prozess seine Liste der Fensterklassen die aus hInstance und dem Namen der Klasse bestehen. Auch die Standard Fensterklassen wie Edit, Button, Static etc. werden mit der hInstance der User32.dll gespeichert.

Wird nun ein Fenster erzeugt mit CreateWindow(Ex), dann benutzt der Windowsmanager die Kombination aus hInstance Wert, der bei CreateWindow(Ex) angegeben wird und dem Namen der Klasse um den entsprechenden Klassen Eintrag zu finden.

Es ist also vollkommen OK wenn DLLs selber Klassen registrieren mit ein und unterschiedliche Module den selben Namen verwenden. Da gibt es keinen Konflikt, denn durch die hInstance Werte bleiben die Klassen eineindeutig. Und auch jede DLL kann damit, dass von Ihr gewünschte Fenster mit der entsprechenden Klasse erzeugen, denn jede DLL hat eine unterschiedliche hInstance.

Einzige Ausnahme ist eine Klasse, die mit dem Klassenstil CS_GLOBALCLASS registriert wird. Bei solch einer Klasse wird der Windowsmanager nur auf den Namen und nicht auf den Wert der hInstance achten. Jedem wird klar sein, dass die Standardfensterklassen der USER32.DLL und auch die Klassen der COMCTL32.DLL mit diesem Stil registriert wurden.
Und klar ist auch, dass man seine eigenen Klassen, die in DLLs liegen mit diesem Flag CS_GLOBALCLASS registrieren muss, wenn man diese Klassen applikationsweit verwenden will. Würde man also ein Dialogtemplate mit einer eigenen Klasse anlegen, die in einer DLL liegt, so kann der Dialogmanager, der wieder hInstance der Applikation verwendet, die entsprechende Klasse nicht finden, wenn diese nicht mit CS_GLOBALCLASS registriert wurde.

Es ist und bleibt eine Unsitte GetModuleHandle(NULL) beim Registrieren der Windowsklasse zu verwenden, denn dieses hInstance, das man erhält ist natürlich das hInstance der Applikation, und nicht das des Modules, welches die Klasse enthält, z.B. eben eine DLL. Es wundert nicht wenn man etwas später seine Klassen in eine DLL auslagert erstaunt feststellt, dass auf einmal die Sachen nicht mehr funktionieren wie sie sollen.

Um solchen Problemen aus dem Weg zu gehen sollte man immer das hInstance verwenden, das zu dem entsprechenden Modul gehört. Diesen Wert erhält man durch WinMain oder DllMain. Am Besten man speichert diesen in einer globalen Variablen. Die MFC hat hierzu eine spezielle Funktion AfxGetInstanceHandle, die dies für das entsprechende Modul erledigt. Aber ein MFC Programmierer würde ja auch AfxRegisterClass verwenden und nicht in diese Probleme laufen, wiederum vorausgesetzt er verwendet auch brav AFX_MANAGE_STATE 🙂

❗ Anmerkung: Es gibt auch Code, der einem erlaubt das hInstance Handle zu einem Code Abschnitt zu bestimmen.
http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx (sofern man einen MS-Linker verwendet)

Auch der folgende etwas trickreichere Code ist einen Blick wert:

HINSTANCE Get_hInstance()
{
 MEMORY_BASIC_INFORMATION mbi; 
 VirtualQuery(Get_hInstance, &mbi, sizeof(mbi)); 
 return reinterpret_cast<HINSTANCE>(mbi.AllocationBase); 
}

Aber bitte diesen Code nicht in eine DLL auslagern :mrgreen:

Die Unsitte PostQuitMessage zum Beenden eines Programmes zu verwenden!

Immer wieder lese ich Postings in http://www.c-plusplus.de/forum die es anpreisen ein Programm mit PostQuitMessage zu beenden, genau so unsinnig wie WM_QUIT zu versenden. 

Das ist natürlich Unfug! Sicherlich wird ein Programm durch PostQuitMessage beendet, aber warum?
Weil die Nachrichtenschleife verlassen wird und letzten Endes WinMain verlassen wird. Dies führt dazu, dass die darunter liegenden CRT Routinen irgendwann ExitProcess ausführen. BTW: Würde hier nur ein der CRT einfacher return erfolgen, dann würde der Prozess weiterleben, wenn noch ein einziger anderer Thread aktiv wäre.

Das brutale Verlassen führt aber letzten Endes auch dazu, dass erst ExitProcess brutal alle Fenster aufräumt. D.h. kein Fenster wird normal zerstört, kein WM_DESTROY bzw. WM_NCDESTROY wird empfangen. D.h. alle normalen Prozesse, die dem Aufräumen und Freigeben von Ressourcen dienen, werden außer Kraft gesetzt.
Ja und sicherlich gibt ExitProcess Speicher frei, die der Prozess alloziert hat, auch einige Handles können freigegeben werden, aber nicht alle (z.B. benamte Mutexe und Semaphoren).

Bei einem Mikey Mouse Win32 API Programm mag dies kein Problem sein, denn hier gibt es keine Ressourcen, die Prozessübergreifend ein Leak verursachen würden, oder eine Ressource blockieren würden.
Aber grundsätzlich würde ich es unterlassen. Jede andere Library, die man verwendet, jedes externe Control, dass man einbindet könnte genau auf dieses entscheiden WM_DESTROY angewiesen sein um Ressourcen freizugeben, die ein System blockieren könnten. Solange man nicht 100%ig weiß wie die benutzen Bibliotheken arbeiten, ja nicht einmal detailliert weiß wie COM und die CRT Handles behandeln würde ich grundsätzlich abraten ein Programm einfach mit ExitProcess zu verlassen, genau so wie ich abrate TerminateProcess zu verwenden.

Der richtige Weg ist und bleibt es das/alle Main Window(s) zu zerstören und entsprechend dann (im WM_DESTROY Handler) PostQuitMessage (AfxPostQuitMessage) auszuführen. Durch das Zerstören des Hauptfensters werden natürlich alle enthaltenen Child-Windows mit zerstört. Alle Fenster bekommen damit die Chance hinter sich aufzuräumen und Ressourcen frei zu geben.

PS: Aber solche Unsitten lassen sich kaum ausmerzen. Genauso wenig wie die Unsitte einen HINSTANCE Wert einfach durch Aufruf von GetModuleHandle(NULL) zu bestimmen… Auch eine Unsitte, die wohl niemand mehr ausmerzen wird.

Bios Update per Boot CD

Wer hätte gedacht, dass es so einfach geht 🙂
http://www.biosflash.de/bios-boot-cd2.htm

Einfach Nero genommen, das Image angegeben. Die paar Dateien mit auf die CD gepackt und gebrannt. Neu booten. 

Ich habe jedoch zwei DVD-Laufwerke. Es erscheint dann beim Booten  von der CD eine Fehlermeldung, dass nicht genügend Laufwerkbuchstaben verfügbar sind. Logisch, denn als erster Buchstabe wurde mit Z in dem Image angegeben und nach Z ist kein zweiter Buchstabe mehr verfügbar für mein zweites DVD-Laufwerk.

Kein Problem! Einfach nochmal den Befehl:

MSCDEX /D:MSCD001 /L:X

ausführen und man kann auf die Laufwerke X und Y direkt von der DOS Ebene zugreifen.
Nun kann das BIOS Update lufen…

Crash in Online Hilfe des Exchange System Manager

Nun habe ich auch die Ursache für das Versagen der Onlinehilfe in der MMC des Exchange System Manager gefunden:
Es ist die IE7 Installation.

Nachzulesen hier: http://support.microsoft.com/kb/932513

Allerdings ist das nur die halbe Wahrheit. Die IE7 Installation ist mit Sicherheit nicht schuld, sondern nur der Auslöser. Wenn man sich diesen Fix ansieht, dann wird dort eine psapi.dll umbenannt. Mehr nicht!
Der Fix besteht also darin eine System-DLL, die lokal durch Exchange installiert wurde, außer Kraft zu setzen und die neueste DLL, die natürlich längst im Windows\System32 Verzeichnis liegt zu verwenden.

Bleibt die Frage: Warum hat das Exchange Team überhaupt eine lokale psapi.dll installiert und nicht die Datei verwendet, die mit dem OS von Windows 2003 ausgeliefert wird? Fakt ist, dass diese psapi.dll eine Uralt-Version für Windows 2000 mit Version 5.0 ist; Windows 2003 wurde mit einer Version 5.2 ausgeliefert.

Hilfe und Support kann nicht geöffnet werden… Starten Sie „Hilfe und Support“, um dieses Problem zu beheben.

Auf einem meiner Windows 2003 R2 Server bekam ich permanent Abstürze sobald ich die Online-Hilfe im Exchange System-Manager aufrief.
Also dachte ich mir: „Schaust Du doch mal in die Online Hilfe“.

😯 Es springt mich die folgende Fehlermeldung an:

Hilfe und Support kann nicht geöffnet werden, da ein Systemdienst nicht ausgeführt wird.
Starten Sie „Hilfe und Support“, um dieses Problem zu beheben.

Eine dämlichere Fehlermeldung kann es wohl nicht geben! OK, Nach ein wenig googlen kam ich zu der Erkenntnis:
Der Dienst „Hilfe und Support“ fehlte bei mir in der Liste aller Dienste. Das mit dem Satz „Starten Sie „Hilfe und Support“, um dieses Problem zu beheben“ ein Dienst gemeint ist, kann hier wirklich nicht riechen.

Etwas mehr googeln ergab folgenden Fix:

  1. Wechseln in das Verzeichnis c:\windows\pchealth\helpctr
  2. Das gesamte Verzeichnis packagestore löschen
  3. Wechseln in das Verzeichnis c:\windows\pchealth\helpctr\binaries
    und dort den folgenden Befehl aus der Console starten:
    start /w helpsvc /svchost netsvcs /regserver /install

Sollte  helpsvc.exe nicht mehr vorhanden sein, oder der letzte Befehl fehlschlagen, muss man wohl diesen Teil neu installieren:

  1. Explorer starten und wechseln nach c:\windows\inf
  2. Rechtsklick auf die Datei pchealth.inf und Installieren auswählen
  3. Dienst wie oben unter 3. neu installieren.

Das Problem scheinen mehrere Leute sowohl mit XP, als auch Windows 2003 Server zu haben, nachdem Servicepacks installiert wurden. Wundert mich allerdings, weil in der letzten Zeit kein Servicepack installiert wurde.  Wahrscheinlich habe ich nur längere Zeit die Hilfe nicht verwendet 😉 und mirist es nicht aufgefallen.

Damit kann man zumindest mal wieder die Hilfe aufrufen. Warum aber mein Exchange System-Manager jegliche Online-Hilfe mit einem Absturz quittiert bleibt mir noch ein Rätsel…

Mein Favorit bei den Backup und Imaging Programmen

Es gibt ja Leute, die legen keinen Wert auf Backups Ihrer Rechner. Ich habe bereits zu viele negative Erfahrungen gemacht und NTBackup funktioniert zwar, ist aber für das komplette Wiederherstellen eines Rechners bestimmt nicht erste Wahl.

In den letzten zwei Jahren hat sich bei mir ein klarer Favorit heraus gebildet:
Acronis in Verbindung mit meiner externen 500GB Festplatte.
In der Firma setzt ich Acronis True Image Echo Workstation ein. Zu Hause auf meinem Desktop und Laptop Acronis True Image Home Version 11. Beide Versionen unterstützen natürlich Vista.

Speziell die Home Version bekommt von mir die Note 1+. Die knappen Euro 50,– die das Programm kostet sind wirklich gut angelegt.

Es ist extrem einfach komplette Backups zu ziehen sind und die auch wirklich einfach zu verwenden sind wenn mal was zu restaurieren ist, man öffnet sie einfach im Explorer als Pseudo-Laufwerk. Differenzielle Backups (die ich bevorzuge) und inkrementelle Backups sind auf DiskImage Ebene möglich. D.h. man kann jederzeit auch seinen ganzen Rechner sofort wieder auf einen zuvor gesicherten Stand bringen. Zum Glück habe ich das noch nicht benötigt.
Durch eine versteckte Partition (Secure Zone), kann man auch das entsprechende Recovery-Modul direkt installieren. Oder aber man erzeugt sich ein bootbares Medium (CD). USB Laufwerke werden in diesem Recovery Modus erkannt und bedient. Für mich sind das die elementar wichtigen Dinge die ich von einem Backup Programm erwarte.
Darüber hinaus bietet die Acronis Software noch einiges mehr. Besonders Try&Decide hat es mir hier angetan. Einfach erstmal Software im Probiermodus testen, bevor Änderungen tatsächlich am System durchgeführt werden.

Einziger Wermutstropfen ist mein Rechner in der Firma mit einem Intel SATA-Raid Controller. Bei diesem funktioniert das entsprechende Recovery Modul nicht.