Was nicht alles mit WordPress möglich ist…

Ich bin jedesmal über die Vielfalt der Plugins von WordPress erstaunt.
Ich habe gerade WP-Syntax installiert und es ist stark was das aus den Code-Snipplets macht, die man so in seinem Blog platziert kann.

// TestConsole.cpp : Defines the entry point for the console application. 
//            

#include "stdafx.h" 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
   _tprintf(_T("Hello World!\n")); 
   return 0; 
}

Und so sah es vorher aus:

// TestConsole.cpp : Defines the entry point for the console application.
//
  
#include „stdafx.h“
int _tmain(int argc, _TCHAR* argv[])
{
   _tprintf(_T(„Hello World!\n“));
   return 0;
}

Genial schön mit WP-Syntax! 😎

AfxBeginThread versus _beginthreadex

Es hat sich ja mittlerweile schon herumgesprochen, dass man _beginthread(ex) anstatt CreateThread verwenden sollte, wenn man die CRT verwendet. Die Frage ist wie steht es nun mit _beginthread(ex)  und AfxBeginThread wenn man die MFC verwendet?

Es ist ähnlich wie bei der CRT, es gibt auch für die MFC einen Thread State, der im Thread Local Storage abgelegt wird.  Zu diesem Thread Local Storage gehören z.B. die temporären Maps für die Fensterverwaltung und Maps für GDI-Objekt Verwaltung. Auch für Tooltips und diverse OLE Funktionen werden in diesem Module Thread State Daten abgelegt.

Weiterhin werden einige Hooks gesetzt, die notwendig werden, wenn GUI verwendet wird. Dito Aufräumarbeiten, falls COM verwendet wird… (AfxOleInit)
Dieser Thread Local Storage wird normalerweise beim Zerstören des assoziierten CWinThread wieder freigegeben. Wird die Threadfunktion verlassen oder AfxEndThread aufgerufen, dann wird der Thread Module State mit dem entsprechenden Speicher freigegeben.

Was passiert, wenn man in einem MFC Programm einen Thread mit _beginthreadex startet und anschließend MFC Funktionen verwendet und dann mit _endthread den Thread terminiert?
Was passiert, wenn man mit AfxBeginThread einen Thread startet und ihn mit _endthread terminiert ❓

❗ Dann entsteht ein Leak, und je nach verwendeten Komponenten kein kleines ❗

Sollte die MFC Applikation also dynamisch Threads erzeugen, weil damit zum Beispiel Sockets überwacht werden oder andere nette Workerthreads bedient werden, dann kann man relativ  schnell unerfreuliches erleben.

Es gilt also 2 Dinge zu beachten:

  1. In einem MFC Programm sollte man immer AfxBeginThread verwenden! Man geht sonst das Risiko ein, dass bei der Verwendung der ersten MFC Funktion (AfxGetResourceHandle o.ä.) ein entsprechender Speicherblock angelegt wird und eben sonst nicht mehr freigegeben wird..
  2. Und beim Verlassen einer Threadfunktion kümmert man sich am Besten gar nicht darum, wie der Thread gestartet wurde :mrgreen: . Man muss explizit AfxEndThread gar nicht aufrufen. Man sollte einfach alle Threadfunktionen einfach durch return verlassen. Der Thread wird dann entsprechend der Funktion, die man beim Start gewählt hat auch terminiert. Dann bleibt – auch bei einer Änderung der Umgebung , ob nun mit oder ohne MFC. 

Anmerkung:
Warum werden diese Leaks nicht in der Debugausgabe angezeigt? Ganz einfach, weil diese Allokationen durch die MFC nicht getrackt werden. Das Speichertracking der Debugversion wird explizit für diese Allokationen ausgeschaltet.

Warum man manchmal AFX_MANAGE_STATE auch in seiner eigenen EXE aufrufen muss

AFX_MANAGE_STATE ist jedem bekannt, der mit DLLs hantiert. Es garantiert bei Verwendung der MFC DLLs, dass die entsprechenden Ressourcen bei den verschiedenen Ladeoperationen, wie z.B. CString::LoadString gefunden werden.

Warum ❓
AfxSetResourceHandle und AfxGetResourceHandle bedienen, eine globale Variable, die in der MFCn.DLL liegt.
Genau genommen ist es keine prozessglobale Variable, dies wird klar wenn man an Threads denkt. Die Variable wird threadlokal gespeichert.  Die HINSTANCE für AfxGetResourceHandle liegt in einer Struktur, die AFX_MODULE_STATE heißt. In dieser Struktur werden noch einige andere wichtige threadlokale Daten gespeichert. Das sind z.B. für die Interaktion mit der Managed-World, der Activation Context. Einen Blick auf den Inhalt dieser Struktur zu werfen lohnt sich.
Durch diese Struktur AFX_MOUDLE_STATE hat das Makro AFX_MANAGE_STATE seinen Namen.

Gesetzt den Fall wir haben EXE und DLLs (egal ob Standard oder Extensions DLLs), die alle die MFC DLLs dynamisch binden, dann wird AFX_MANAGE_STATE wichtig. Ruft eine EXE also eine Funktion aus einer DLL auf, hat natürlich die EXE das entsprechende Handle an AfxSetResourceHandle übergeben. Damit nun seinerseits die DLL eigene Ressourcen laden kann, wird durch AFX_MANAGE_STATE die alte AFX_MODULE_STATE Struktur gesichert (genau genommen der Zeiger darauf), und ein Zeiger auf die neue aktuelle AFX_MODULE_STATE Struktur gesetzt. CString::LoadString und CDialog::DoModal finden nun die richtigen Ressourcen in der DLL.
Der Destruktor sorgt nun am Ende der Funktion, dass der alte Zeiger der ursprünglichen AFX_MODULE_STATE Struktur zurückgesetzt wird, auf den Wert vor dem Aufruf.

Soweit mal die Theorie 🙂
Was passiert aber nun unter den folgenden Gegebenheiten:

  • Eine DLL ruft einen Dialog oder eine MessageBox auf. In der EXE existieren Fenster, die einen Timer gesetzt haben?
  • Oder eine DLL ruft einen Dialog auf, und die EXE hat einige COM-Objekte veröffentlicht, die nun von extern angesprochen werden können.
  • Die DLL ruft über einen Mechanismus eine Callback Funktion in der EXE auf.

Das Alles ist kein Problem, solange nicht ihrerseits die Funktionen aus der EXE auf die Idee kommen eine Ressource zu laden. Was würde dann passieren?

Klar, die DLL hat mit AFX_MANAGE_STATE den AFX_MODULE_STATE umgesetzt. Würde die EXE in der Callback-Funktion oder Timer-Funktion nun selbst auf die Idee kommen einen Dialog zu laden oder nur einfach CString::LoadString auszuführen, dann wird evtl. ein String oder Dialog geladen, aber vermutlich nicht der, den man erwartet.
Verwendet man nun Formatierungsfunktionen, wie z.B. Format, wird man manchmal böse Wunder erleben. Oder man lädt einen Dialog mit DoModal. Wenn man Glück hat ist der Dialog mit dieser ID nicht da und DoModal schlägt fehl. Wenn man Pech hat wird der Dialog geladen, aber die entsprechenden Controls die gebunden werden oder mit GetDlgItem gesucht werden sind nicht vorhanden. Und da die meisten Entwickler keine Prüfung auf NULL durchführen (z.B. hier bei GetDlgItem(IDC_MYITEM)->EnableWindow(FALSE)) kracht es an den absonderlichsten Stellen.
Auch in der EXE ist man gut beraten in OnTimer Handlern AFX_MANAGE_STATE zu verwenden, wenn der Timer auch Ressourcen verwendet. Gleiches gilt in COM Interfaces oder IDispatch Interfaces. Glücklicherweise sorgen hier die Wizards für korrektes Verhalten.

Mehr noch: Unglücklicherweise kann theoretisch jeder Windows Handler zu diesem Problem führen, wenn diese Fensterfunktion direkt über die modale Nachrichtenschleife aus einer DLL aufgerufen wird.
Und auch bei mancher Funktion, die als Callback aus einer DLL verwendet wird, kann ein zusätzliches AFX_MANAGE_STATE nicht schaden.

VS-Tipps & Tricks: Benötigt man eigentlich noch DEF Dateien?

Das was eine DEF Datei tut, benötigt man oft genug noch. Stellen wir die Frage mal etwas anders:
Kann man den Inhalt einer DEF Datei auch wo anders unterbringen?

Ja man kann sich eine DEF Datei sparen. Auch der Linker kennt entsprechende Optionen auf der Befehlszeile, die das gleiche tun, was eben eine DEF Datei macht.

Wer schon mal ATL Support zu einem DLL Projekt hinzugefügt hat, oder eine ATL DLL mit VS-2005/2008 angelegt hat, der wird feststellen, dass es gar keine DEF Datei mehr gibt, aber dennoch Funktionen wie DllCanUnloadNow exportiert werden.

Schaut man sich den Code an, der erzeugt wird, dann sieht man einen netten Block von pragmas.

#pragma comment(linker, 
        "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow@0,PRIVATE") 
#pragma comment(linker, 
        "/EXPORT:DllGetClassObject=_DllGetClassObject@12,PRIVATE") 
#pragma comment(linker, 
        "/EXPORT:DllRegisterServer=_DllRegisterServer@0,PRIVATE") 
#pragma comment(linker, 
        "/EXPORT:DllUnregisterServer=_DllUnregisterServer@0,PRIVATE")

Die Ähnlichkeit zur DEF Datei ist frappierend, was aber auch wieder nicht wundert.
Nett ist auch, dass man sich die declspec(dllexport) Spielereien sparen kann. Alles macht hier einfach der Linker ❗

Das eigentliche Problem an dieser Syntax ist, dass man auch den intern gemangelten Namen kennen muss. Es enthebt den Programmierer nicht die Funktion auch entsprechend korrekt zu deklarieren.

#pragma comment(linker, 
        "/EXPORT:ExportedFunction=_ExportedFunction@0") 
extern "C" BOOL __stdcall ExportedFunction() 
...

Der einzige kleine Trick steckt hinter der Frage: Wie kommt man an den gemangelten Namen der Funktion?
Aber auch das ist nicht schwer. Funktion gewünscht deklarieren und definieren, z.B.:

__declspec(dllexport) BOOL __stdcall ExportedFunction2(const char *) 
{ 
 return FALSE; 
}

Dann mit Depends, den exportierten Namen abgreifen (rechte Maustaste Copy Function Name).
Dann einfach die Funktion final übernehmen.

#pragma comment(linker, 
        "/EXPORT:ExportedFunction2=?ExportedFunction2@@YGHPBD@Z") 
BOOL __stdcall ExportedFunction2(const char *) 
{ 
 return FALSE; 
}

Netter Effekt: Auf diesem Weg kann man auch eine Funktion leicht unter zwei Namen exportieren…

Debugging und ASSERTs in Services

Ich habe in der letzten Zeit einige COM-PlugIns  und Service Komponenten entwickelt. Alles Teile von anderen Diensten und TSPs (Tapi Service Provider). D.h. alles ohne UI. Die ganze Maschinerie, die ich hierzu verwendete befand sich auf einem Windows 2003 R2 Server. Aufgrund bestimmter Hardware war ein virtueller Server zum Testen nicht drin.
Macht ja nix. Man kann ja auch mit Remote Desktop auf dem Server vom eigenen Platz aus arbeiten, ohne deshalb im klimatisierten und immer zu kaltem und außerdem viel zu lautem Serverraum zu arbeiten…

Ziemlich schnell nervte mich gleich ein bestimmtes Problem. Ein Service mit einer meiner Komponenten stand auf einmal. Ich habe mich mit dem Debugger remote attached und merkte mehr oder weniger schnell, dass ein bestimmter Thread (von 67) auf einen ASSERT gelaufen war. Dämlicher Weise hatte der nun kein DebugBreak ausgelöst. Genaugenommen stand der Thread in einer MessageBox mit dem ASSERT Fenster, dass jeder kennt.
Da ich aber per Remote Session mit dem Server verbunden war sah ich diese nicht. Wäre ich am primären Monitor angemeldet gewesen, hätte mich die MessageBox erreicht, dafür trifft die CRT Vorsorge.
Dämlich! Mir wäre sogar ein Crash (mit Minidump natürlich) lieber gewesen. So stand der Service blockierte noch drei andere Sachen und es dauerte doch einige Zeit bis ich diesen stehenden Service als Ursache ausmachen konnte. Wäre der Service gecrasht hätte ich es in Sekunden mitbekommen.

OK! Wie gestalte ich das System nun um, dass ein ASSERT immer einen DebugBreak auslöst und keine MessageBox, die sowieso keiner zu sehen bekommt?
Das würde einen Minidump schreiben und wenn ich mit dem Debugger verbunden wäre, würde es sofort das System an der entsprechenden Stelle stoppen. Die MessageBox mit dem ASSERT brauche ich nicht.

Ein wenig Lesen in der CRT Doku schadet nicht. Also hier die Lösung:

Schritt 1: Wir verhindern, dass die entsprechende MessageBox erscheint und stellen entsprechend ein, dass der ASSERT in der Debug Ausgabe mit protokolliert wird. Und wenn man es hat auch noch will, zusätzlich in einer Protokolldatei.

_CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_DEBUG/*|_CRTDBG_MODE_FILE*/);

Schritt 2: Nun brauchen wir noch einen DebugBreak, der immer ausgelöst wird. Auch das ist kein Problem. Wir benutzen den Debug Report Hook:

_CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, MyDebugHook);

MyDebugHook ist nun nichts weiter als eine kleine Funktion die nur eins enthält: den Aufruf der Funktion DebugBreak();.

So ausgestattet lassen sich Services im Debugmode weitaus besser entwickeln. Jetzt sorgen Sie wenigstens für einen anständigen Crash (natürlich mit Dump), wenn es ASSERTet… :mrgreen:

Late Binding und schwache Performance durch GetIDsOfNames

Immer wieder sehe ich Entwickler, die über Late Binding COM Komponenten ansprechen. Das ist an sich nur zu unterstützen, denn DISPIDs können sich schnell mal ändern, wenn sich ein Interface ändert. Gerade bei den rasant an Verbreitung zunehmenden .NET Komponenten, die man mal schnell in die eigene Anwendung per COM einbindet, kann das Binding über die Interfaces und DISPIDs schnell zum Frust werden. Gleiches gilt für Office Komponenten, bei denen man sich nicht zwingend an ein Interface binden will. Zudem ist es der von Microsoft empfohlene Weg die Office-Automation zu benutzen (siehe auch hier).

OK! Also man nimmt Late Binding und verwendet z.B. die aktuellen Wrapper, die netterweise von der ATL zur Verfügung gestellt werden,  z.B. die netten Funktionen aus der CComDispatchDriver Klasse. GetPropertyByName, PutPropertyByName und auch die Funktionen Invoke0, Invoke1 und InvokeN haben entsprechende Überladungen, die die Verwendung von Funktions-/Eigenschaftsnamen direkt erlauben.

Der Nachteil liegt nicht gleich auf der Hand. Immer wenn solch eine Funktion aufgerufen wird, wird nicht durch der IDispatch::Involke ausgeführt, sondern auch ein Aufruf von IDispatch::GetIDsOfNames. Bei einem Out-Of-Process-Server kann dieser Roundtrip einiges an Performance kosten. Dabei ist es so einfach es besser zu machen.

Die Doku von IDispatch::GetIDsOfNames sagt folgendes:  

The member and parameter DISPIDs must remain constant for the lifetime of the object. This allows a client to obtain the DISPIDs once, and cache them for later use.

Und wer den oben genannten KB-Artikel aufmerksam gelesen hat, der hat auch was von DISPID-Caching mitbekommen.

Ich benutze gerne die die Wrapper, die in der MFC automatisch erzeugt werden, wenn man einen Type-Library über den Class View importiert. Hier werden die Funktionen auch in eine nette kleine COleDispatchDriver-Klasse verpackt und man bekommt netterweise ein gutes Exception Handling den Fehlerfall geliefert. Leider werden hier aber auch wieder nur DISPIDs verwendet.
Aber mit einem kleinen Trick, kann man diese Klassen genial einfach für Late Binding nutzen. Ich gehe wie folgt vor:

  • Ich importiere die Type-Library (tlb) mit dem Visual Studio Class View.
  • D.h. ich habe jetzt alle Wrapper mit DISPIDs, Was ich eigentlich für Late Binding vermeiden will.
  • Jetzt passe ich einfach die einzelnen Wrapper Funktionen in der folgenden Art und Weise an, ich ersetze die DISPID durch eine statische Variable:
void CMyWrapper::DoSomething(){
  static CDispIdHolder dispid(m_lpDispatch,L"DoSomething");
  InvokeHelper(dispid, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}
  • Die kleine Klasse die ich hier verwende macht nun den Rest und besorgt die DISPID und cached sie damit weil die Variable statisch definiert ist:
class CDispIdHolder
{
public:
 CDispIdHolder(IDispatch *pDispatch,LPCOLESTR pName)
  : m_dispid(DISPID_UNKNOWN)
  {
   HRESULT hr = pDispatch->GetIDsOfNames(
         IID_NULL,
         &const_cast<LPOLESTR>(pName),
         1,
         LOCALE_SYSTEM_DEFAULT,
         &m_dispid);
   if (FAILED(hr))
    AfxThrowOleException(hr);
  }
  operator DISPID() { return m_dispid; }
private:
 DISPID m_dispid;
};

Die Exception, die man verwendet ist natürlich Implementierungsfrage.

❗ Der Performance Gain ist zum Teil beträchtlich, besonders wnen bestimmte Funktionen sehr oft aufgerufen werden müssen!

Anmerkung (für alle die es ganz genau nehmen):
Wenn man die Doku genau liest, heißt es natürlich hier, dass die Implementierung nur für die Lebenszeit des Objektes konstante DISPIDs garantiert. Wenn man allerdings bei Early Binding schon DISPIDs als konstant annimmt, ist meine Methode für Late Binding sicherlich vertretbar.

Vista: Wie man den Kontextmenübefehl „Eingabeaufforderung hier öffnen“ auf die Powershell umbiegen kann

Torsten Schröder hat mir einen netten Kommentar in meinem letzten Blog-Artikel Vista: Wie man den Kontextmenübefehl “Eingabeaufforderung hier öffnen” umbiegen kann gegeben. Er meinte (Zitat):
„noch einen Tick besser fänd ich es, wenn man es Richtung Powershell umbiegt!“

Nun das gefällt mir auch und es ist auch nicht schwer. Mit dem folgenden kleinen Hack in der Registry kann man auch diesen erweiterten Kontextmenübefehl auch die Powershell umbiegen.

Einfach in der Registry unter HKEY_CLASSES_ROOT\Directory\shell\cmd\command
den Eintrag: cmd.exe /s /k pushd „%V“
z.B. in „C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe“ -noexit -command „set-location ‚%V'“ tauschen.

Damit lässt sich nun auch für mich das erweiterte Kontextmenü unter Vista perfekt nutzen:

  • 4NT integriert sich mit eigenen Kontextmenü-Befehlen.
  • und die Powershell ist nun über das erweiterte Kontextmenü des Vista-Explorers durch das Drücken der Umschalt-Taste extrem einfach zu erreichen.

Anmerkung: Wer den Faden verloren hat, alles beginnt mit diesem Tipp:
Zusätzliche Befehle im Explorer-Kontextmenü von Vista  😉

Vista: Wie man den Kontextmenübefehl „Eingabeaufforderung hier öffnen“ umbiegen kann

In meinem Artikel Zusätzliche Befehle im Explorer-Kontextmenü von Vista habe ich ja erwähnt, dass der Menüpunkt Eingabeaufforderung hier öffnen immer CMD.EXE verwendet und nicht den Befehlszeileninterpreter, der durch COMSPEC definiert ist.
Aber mit einem kleinen Hack in der Registry kann man auch diesen Befehl auf den eigenen Befehlszeileninterpreter umbiegen.

Einfach in der Registry unter HKEY_CLASSES_ROOT\Directory\shell\cmd\command
den Eintrag: cmd.exe /s /k pushd „%V“
z.B. in „C:\Program Files\4NT\4NT.EXE“ /s /k pushd „%V“ tauschen.

Anmerkung: Da 4NT normalerweise auch seine eigenen Einträge in den Kontextmenüs des Explorers macht, kann man es natürlich auch als Vorteil ansehen, wenn man bei Bedarf den originalen Befehlszeileninterpreter starten kann. 🙂

Alle reden von Sichertheit in der IT-Branche… Alle?

Bei einem Kunden muss ich aktuell einem Problem auf den Grund gehen, das irgendwie mit Locks in den tiefsten Tiefen des SQL-Server 2005 zu tun hat. Aus diesem Grund habe ich Einblick in den originalen – doch etwas größeren – Datenbestand erhalten. Besagter Kunde ist in seiner Branche ziemlich populär. Es werden in dieser Datenbank 750.000 Kunden verwaltet. Alles aktive Kunden eines bestimmten Produkts einer kleinen geographischen Zone in Deutschland. Qualitativ wirklich aktuelles Material, denn alle diese Datensätze sind wirklich aktive Kunden, d.h. bekommen mindestens einmal im Jahr eine Rechnung.

Um sich nun mit unserer Anwendung als Benutzer Administrator anzumelden benötigte ich noch ein Kennwort. Das hatte mir keiner mitgeteilt (bis jetzt). Aber was soll’s, probieren wir doch mal 😉

  1. Versuch: Der Firmenname
  2. Versuch: Der Produktname
  3. Versuch: admin… Bingo 😮

Ich will nicht davon reden, wieviele Aktivität betrieben wird,  die Datenbanken nach außen abzuschirmen. Auch will ich nicht über die interne Panik klagen, die uns gegenüber immer geschoben wird, dass alles hoch sicher und geheim zu behandeln ist.

Jeder Angestellte, mit etwas Spielwitz kann in etwa 20 Sekunden als Admin an alle Daten…

Nur als Anmerkung: Dieses Sicherheits-Problem ist natürlich mittlerweile behoben… :mrgreen:

Verhindern des Flackerns von Controls wenn ein Fenster-Resize erfolgt

Immer wieder taucht in Foren die Frage aus, wie man das Flackern von Controls verhindern kann. Die Allgemeine Antwort heißt Doublebuffering, d.h. die Ausgabe wird zuerst auf einem nicht sichtbaren Memory DC durchgeführt und anschließend in einem Schlag auf den eigentlichen DC kopiert. Wichtig ist hier, dass auch der Hintergrund im eigentlichen WM_PAINT Handler mit gezeichnet wird und WM_ERASEBKGND gar nichts mehr macht. Der Code-Klassiker hierzu findet sich in Code-Project http://www.codeproject.com/KB/GDI/flickerfree.aspx

Anders liegt die Sache wenn es beim Resize eines Fensters flackert. Hier ist selten Doublebuffering eine Lösung. Meistens liegt hier das Problem darin, dass das Parent Fenster seinen Hintergrund neu zeichnet und anschließend alle Child-Windows auch neu gezeichnet werden müssen.

Aber auch hier ist Abhilfe einfach. Im Parent-Fenster wird einfach der Stil WS_CLIPCHILDREN gesetzt. Das sorgt dafür, dass das Parent Fenster einen DC bekommt bei dem die einzelnen Child-Windows ausgeclippt sind, und somit weder durch WM_ERASEBKGND noch durch den WM_PAINT Handler des Parents überschrieben werden.

Sollten sich die Child-Fenster überlappen müsste man zusätzlich an WS_CLIPSIBLINGS bei allen Kindfenstern als Stil denken (nicht beim Parent).