Author Archives: jkalmbach

LowLevel Hooks sind böse

Es gibt ja viele, die stehen auf Hooks. Es gibt auch sog. LowLevel Hooks, welche keine DLL benötigen, sondern im Kontext des Prozesses (Threads) laufen, welche das SetWindowsHookEx aufgerufen hat.
Das Problem ist nun bei solchen Hooks, das diese in der Vergangenheit sehr oft zu Verzögerungen im ganzen Windows System geführt haben, wenn ein Hook in der Callback etwas länger gebraucht hat oder sonstwie Fehler gehabt hat.

Dies hat MS nun versucht zu in Windows 7 (RTM) beheben. Die Lösung ist einfach:
Der Hook wird einfach entfernt, wenn er 11 Mal länger als 300 ms gebraucht hat 😉 (wobei ich 300 ms immer noch sehr lang finde…)

Siehe auch: Global hooks getting lost on Windows 7

C++/CLI Programme auf einem anderen Rechner ausführen (VC2010)

In Foren kommt oft die Frage: Mein C++/CLI Programm läuft nicht auf anderen Rechner! Was brauche ich damit es läuft?

Die Frage ist einfach zu beantworten, wenn wir davon ausgehen, dass das Programm mit VS2010 (Beitrag für VS2008 gibt es hier) erstellt wurde:

  1. Zuerst wird das .NET Framework benötigt (da C++/CLI ja die CLR verwendet). Aktuell ist dies für VC2010 die Version 4.0:
    .NET 4.0 (Full download)

  2. Und da Du C++/CLI (also C++) verwendet hast, benötigst Du noch die C-Runtime DLLs, da C++/CLI (CLR) nur mit der DLL-Version der C-Runtime (CRT) verwendet werden kann:
    VC2010 (x86)
    In dem seltenen Fall, dass man die Application als x64 übersetzt hat benötigt man diese CRT-Version: VC2010 Runtime x64

PS: Falls man kein CLI (CLR / .NET) verwendet hat, so ist es meistens einfacher, wenn man statisch gegen die CRT linkt!

PPS: Auch sollte man beachten, dass es oft keinen Sinn macht C++/CLI zu verwenden. Das ist wirklich nur für InterOp gedacht!

Letztes PSDK für VC6

Es soll ja immer noch Leute geben, die VC6 verwenden. Die Gründe sind in den meisten Fällen Altprojekte, welche man eigentlich nie wieder anfassen wollte… und irgendwann muss man dann doch noch was anpassen.
Dazu werden dann oft neuere Methoden benötigt, die im mitgelieferten PSDK von VC6 nicht dabei sind. Das letzte PSDK, welches noch VC6 unterstützt ist von Februar 2003. Bei den darauf folgenden PSDKs hat sich teilweise das Format geändert und es lässt sich nicht mehr korrekt linken. Deshalb rate ich auch niemandem in VC6 ein anderes PSDK zu verwenden, als max. Februar 2003.

Bis vor einiger Zeit gab es auch noch eine offizielle Seite um das PSDK runterzuladen:
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm

Diese wurde aber wohl jetzt abgeschaltet…
Glücklicherweise sind die Dateien für den Download aber immer noch da:

PSDK-FULL.1.cab
PSDK-FULL.2.cab
PSDK-FULL.3.cab
PSDK-FULL.4.cab
PSDK-FULL.5.cab
PSDK-FULL.6.cab
PSDK-FULL.7.cab
PSDK-FULL.8.cab
PSDK-FULL.9.cab
PSDK-FULL.10.cab
PSDK-FULL.11.cab
PSDK-FULL.12.cab
PSDK-FULL.13.cab
PSDK-FULL.bat
extract.exe

Man muss die Dateien in ein Verzeichnis downloaden und dann die Batch-Datei ausführen. Dann erhält man das Setup 😉

SQL Server 2008 R2 Express jetzt mit 10 GB Database limit

Ab sofort gibt es den aktualisierten SQL Server 2008 R2 Express zum konstenlos runterladen.
Eines der wichtigesten neuerung der Express Edition dürfte wohl die erhöhung des Datenabnk-Größe-Limits von 4 GB auf 10 GB sein 😉
Hier der Link zur SQL 2008 R2 Express Startseite
http://www.microsoft.com/express/Database/

Download x86 Edition (235 MB)
Download x64 Edition (247 MB)

Sharepoint Foundation 2010 verfügbar

Ich bin schon länger ein Fan von Sharepoint und verwendet dies auch für mehrere interne Projekte.
Seit einigen Tagen ist jetzt auch der Nachfolger der “Sharepoint Services 3.0” verfügbar (natürlich immer noch kostenlos). Aber natürlich mit einem neuen Namen:
Sharepoint Foundation 2010

Der einzige Nachteil des Nachfolgers ist, dass es nur noch auf einem x64 System installiert werden kann.
Wenn man es auch auf einem Entwicklungsrechner installieren will, so kann man es auf Vista (SP1-x64) oder Win7 (x64) installieren. Produktiv wird dies aber nicht unterstützt.
Hier wird dann schon mehr verlangt:

  • x64 – 4 cores
  • 8 GB RAM
  • 80 GB HD

Zusätzliche Include-Pfad in VC++ 2010

Bis VS2008 konnte man zusätzliche Include-Pfad für den aktuellen Benutzer einfach hinzufügen, indem man einfach die nötigen Verzeichnisse unter “Tools|Options|Projects and Solutions|VC++ Directories” eingetragen hat. Dies sieht per Default so aus:
VS2008 Include Verzeichnisse

Ab VS2010 sieht man an dieser Stelle nur noch:
VS2010 Include Verzeichnisse

Der Grund hinter der Änderung liegt daran, dass ab VS2010 die IDE das “Multi-Targeting” unterstützt. D.h. man kann mit der gleichen IDE z.B. für VS2010 und auch für VS2008 compilieren! Deshalb kann man natürlich die C++ Pfade nicht mehr der IDE zuordnen, sondern diese müssen dem jeweiligen Projekt zugeordnet sein.

Man kann aber auch weiterhin Pfad Benutzerspezifisch hinzufügen. Dies wird dann über Property-Sheets realisiert. Dies zu finden, ist aber etwas komplizierter, deshlab hier eine kurze Erklärung:

  1. Öffne irgendein VC++ Projekt
  2. Zeige den Property-Manager an (View|Other Windows|Property Manager)
  3. Expandiere die Knoten dort (i.d.R. Debug/Release)
  4. Wähle dort alle Einträge mit “Microsoft.cpp..user” aus (Multi-Select)
  5. Dann ein rechter Mausklick auf eine der Selektionen und “Properties” auswählen
  6. In dem Dialog kannst Du nun “Common Properties|VC++ Directories” auswählen und dort die entsprechenden Einträge hinzufügen.
    VS2010 Include Verzeichnisse - Neu

  7. Ich persönlich würde links die Dropdown-Liste auswählen und dort dann Edit drücken und die Pfade in dem dann Folgenden Dialog eingeben.

Noch mehr Infos zum Upgrade auf VS2010 gibt es hier:
Visual Studio 2010 C++ Project Upgrade Guide

Anmerkung: Es sei noch erwähnt, dass man zusätzliche Include-Pfad für ein Projekt immer noch in den Projekteinstellungen vornehmen kann! Dazu sind diese Anpassungen NICHT nötig!

Anmerkung2: Um bei der Express Version den Property-Manager zu sehen, muss man erst die Expertenansicht aktivieren:

Tools | Setting | Expert settings

Wünsche/Anregungen für VC++???

Jetzt kommt ja bald VS2010 heraus…. und wie bei MS so üblich, verabschieded sich jetzt das Produkteam von der (dann) aktuellen Version und pplant schon die nächste Version (VS2012?).
Wer hierzu speziell im VC++ Bereich sein Feedback einfliessen lassen will, der kann dies mit einem Fragebogen vom Produkt-Team tun:
http://blogs.msdn.com/vcblog/archive/2010/03/22/vc-developer-survey.aspx

Ich kann es wirklich nur jemdem empfehlen daran teilzunehmen, der auch zukünftig noch VC++ einsetzen will!

RemoteFX

Mit Server 2008 R2 Service Pack 1 wird es endlich eine Erweiterung des RDP (Remote Desktop Protocols) geben: 3D!

Es ist also zukünftig möglich via RDP die schöne, neue 3D-Welt zu erfahren.
Dies bedeutet natürlich auch, dass ein Arbeiten mit VS2010, welches ja WPF verwendet, vermutlich flüssig über RDP möglich ist!

Also, ich bin mal gespannt und freue mich schon auf dieses Feature, da ich oft RDP verwende!

RemoteFX!

Edit 2010-03-27:
Hier gibt es auch noch eine ausführlichere Erklärng wie RemoteFX funktioniert:
http://blogs.msdn.com/rds/archive/2010/03/26/microsoft-remotefx-the-problem-we-are-solving.aspx

C++/CLI und WinForms macht keinen Sinn

Vielen Anfänger, welche C/C++ lernen wollen, suchen sich nach einer kostenlosen Entwicklungsumgebung und stossen dann früher oder später auf die Visual Studio 2008/2010 Express Edition.

Und ein Anfänger will natürlich gleich sichtbare Erfolge sehen und beginnt logischerweise gleich mit einer Fenster-Anwendung.

Leider enthält die VC2008/2010EE nur WinForms als graphische Oberfläche. Deshalb entwicklen die meisten dann nicht mit C/C++, sondern mit C++/CLI, was eine komplett andere Sprache ist und für die meisten nur zu Verwirrung führt.

Ich Rate jedem Anfänger davon ab VC 2008/2010 Express Edition für graphische Oberflächen zu verwenden, aus folgenden Gründen:

  • Der WinForms-Designer ist miserabel, da er die Implementierung von Methoden in der h-Datei vornimmt, was spätestens zu Problemen führt, wenn man mehr als ein Form hat und auf Methoden/Properties des anderen Forms zugreifen will (da man dann zyklische Abhängigkeiten in den h-Dateien hat, die man nur lösen kann, wenn man die Implementierung in die cpp-Datei verlegt)
  • Wenn man die Anwendung verteilen will, so muss man neben dem .NET-Framework auch die C-Runtime installieren; das muss man bei einer reinen .NET-Anwendung (z.B. C#) nicht
  • C++/CLI ist primär als InterOp Sprache zwischen .NET und native Code gedacht; das sieht man auch schon daran, dass seit VC2008 auch der Data-Wizward für C++/CLI entfernt wurde. Daraus ergibt sich gleich der nächste Punkt:
  • Der Data-Wizard wurde in VC 2008 entfernt um auch deutlich zu machen, dass der Focus auf native-managed InterOp liegt
  • Ca. 99% aller Beispiele im Internet sind mit C#; man findet fast keine Beispiele in C++/CLI
  • C++/CLI ist eine eigene Sprache und hat mit (ISO) C/C++ nichts zu tun; und das ganze zu mischen ist meistens noch viel sinnfreier, es sei denn, man weiss was man tut (was zu 99% nicht der Fall ist; zumindest in den Fragen, die ich aus den Foren entnehme)
  • C++/CLI wird oft als “Erweiterung” von C/C++ gesehen. Diese Sicht ist aber komplett falsch! Ganz einfacher Beweis: Versuch in einen STL-Vector ein CLR Objekt reinzustopfen (z.B. std::vector). Wenn es gehen würde, dann könnte man C++/CLI als Erweiterung sehen. Es geht aber nicht. Deshalb sind es zwei komplett getrennte Welten!
  • In VS 2010 wird es für C++/CLI Projekte kein Intellisense geben; das deutet auch stark darauf hin, dass es nicht als primäre Sprache für .NET geeignet ist
  • VC 2012 enthält keine Projekt-Templates mehr für WinForms!!!! Siehe: http://blog.kalmbach-software.de/de/2012/08/23/breaking-changes-in-vc2012/

Meine Empfehlung für Anfäger:
Wenn Ihr unbedingt graphische Oberflächen machen wollt, dann nehmt lieber C# (gibt es auch als Express Edition).

Meine Empfehlung für Microsoft:
Wenn Ihr auch mit VC++ Anfänger erreichen wollt, dann liefert bitte die MFC in der Express-Edition mit; oder bindet von mir aus wxWidgets ein 😉

C++/CLI Programme auf einem anderen Rechner ausführen

In Foren kommt oft die Frage: Mein C++/CLI Programm läuft nicht auf anderen Rechner! Was brauche ich damit es läuft?

Die Frage ist einfach zu beantworten, wenn wir davon ausgehen, dass das Programm mit VS2008 erstellt wurde:

  1. Zuerst wird das .NET Framework benötigt (da C++/CLI ja die CLR verwendet). Aktuell ist dies die Version 3.5SP1:
    .NET 3.5 SP1 (Full download)
    Damit es aber auch Problemlos läuft wird min. noch dieser Hotfix anschliessend benötigt:
    An update for the .NET Framework 3.5 Service Pack 1 is available

  2. Und da Du C++/CLI (also C++) verwendet hast, benötigst Du noch die C-Runtime DLLs, da C++/CLI (CLR) nur mit der DLL-Version der C-Runtime (CRT) verwendet werden kann:
    Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package MFC Security Update

PS: Falls man kein CLI (CLR / .NET) verwendet hat, so ist es meistens einfacher, wenn man statisch gegen die CRT linkt!

Source-Indexing (TFS) und Symbol-Store

Wer von Euch kennt das Problem: Der Kunde hat ein Absturz oder einen Hänger Deines Programmes. Das einzige was Du bekommst ist ein Dump-File (z.B. entweder via WER oder durch eigenes schreiben von MiniDumpWriteDump).
Jetzt beginnt für Dich das Problem:

  1. Welche Version hat der Kunde?
  2. Welche Source-Files brauche ich für diese Version?
  3. Wo zum teu.. sind nochmals die passenden PDBs und EXEn für diese Version?

Mit diesem Fragen braucht man sich nicht beschäftigen, wenn man bei seinem Build Prozess noch zusätzlich zwei Dinge einbaut

  1. Source-Indexing
  2. Symbols-Store

Source-Indexing (mit dem TFS)

Source-Indexing sorgt dafür, dass in die Debug-Symole (PDB-Dateien) auch zusätzlich noch ein verweis auf die richtige TFS-Version eingefügt wird. Dadurch kann der Debugger (z.B. VS) man mit der PDB-Datei genau den passenden Source aus dem TFS holen, mit dem die DLL/EXE gebuildet wurde.
Um dies zu machen braucht man zwei Dinge: “Debugging Tools For Windows” und “ActivePerl“). Das Source-Indexing findet sich bei den Debugging Tools im Unterverzeichnis “srcsrv” (also z.B. C:\Program Files\Debugging Tools for Windows\srcsrv). Da die “Skripts” (leider) in Perl geschrieben sind, ist auch noch ActivePerl notwendig. Es reicht aber, wenn man die ZIP-Datei runterlädt und vor dem Aufruf einfach den Pfad auch noch auf das entpackte ActivePerl setzt.

Damit beim Source-Indexing auch der korrekte TFS-Server verwendet wird, muss man in der Datei “srcsrv.ini” die Zeile mit “MYSERVER” auf den richtigen TSF zeigen lassen.
MYSERVER=http://my-tfs-machine:8080

Jetzt muss man nach einen Build nur noch das Source-Indexing aufrufen und angeben, wo denn der Workstore und die PDBs liegen. Ich gebe der Einfachheithalber immer den Root aller Projekte an, welche ich gebuildet habe. Die Natchdatei sieht dann z.B. so aus (es kann auch direkt als eigenes Task in msbuild laufen):

rem Merke mit mal den aktuellen Pfad, was die Root meiner Projekte und Ausgabe ist
set srvOrgDir=%CD%

rem Setze den pfad auch zu dem Perl Zeugs...
path=%path%;"%CD%\Tools\srcsrv\ActivePerl-5.10.1.1006-MSWin32-x86-291086\perl\bin"

rem Wechsle in das Verzeichnis wo die Source-Indexing Tools liegen (liegt bei mir auch im TFS)
cd .\Tools\srcsrv

rem Rufe das Source-Indexing auf
call tfsindex.cmd -ALLROOT="%srvOrgDir%"

rem Setze wieder den ursprünglichen Pfad
cd /D %srvOrgDir%

Alternativ kann man natürlich auch das srcsrv-Verzeichnis im TFS ablegen (so hab ich es gemacht), dann muss man nicht sicherstellen, dass man auf dem Build-Rechner auch die Debugging-Tools installiert hat.

Jetzt sollten nach einem Build alle PDB-Dateien mit der korrekten TFS-Version indiziert worden sein (dies erkennt man daran, dass ziemlich weit hinten in der PDB-Datei Einträge mit “MYSERVER” kommen…; kann man z.B. in Notepad anschauen).

Symbol-Store

Oben haben wir jetzt die PDB-Dateien mit dem passenden Verweis auf den TFS ausgestattet. Jetzt müssen wir nur noch sicherstellen, dass wir zu einem beliebigen späteren Zeitpunkt nicht mehr nach dieser PDB-Datei (und den dazugehörigen EXEn) suchen müssen. Dies geschieht am einfachsten mit dem “symstore” aus den Debugging Tools for Windows. Dies speichert einfach alle PDBs/EXEn in ein Verzeichnis (am besten ein Netzwerkverzeichnis, wenn es später mehrere Verwenden wollen).
Das ablegen erfolgt dann ganz Simple durch:

.\Tools\SymStore\Symstore.exe add /r /f .\*.* /s G:\MyProject\SymbolStore\Files /t "Project Name"

Das war alles 😉

Einstellungen in VS

Ok, fast… denn man will das ganze ja auch noch verwenden… dazu muss man in VS noch ein paar Einstellungen machen, da per default der “Source-Server” deaktiviert ist. Dies muss aktiviert werden:

Jetzt muss man noch den Pfad zu den zuvor abgelegten Dateien eintragen:

Bekommt man jetzt ein Dump oder will in dieser EXE/DLL debuggen, so werden die Sourcen direkt vom TFS geholt (und in einem temporären Verzeichnis gespeichert) und man kann dies dann direkt debuggen.

Ich hoffe, dass hilft dem ein oder anderen.

PS: Beide Verfahren werden übrigens auch intern von Microsoft schon sehr lange eingesetzt (deswegen auch das Source-Indexing in Perl; PowerShell gab es damals noch nicht). Die gesamten Windows Sourcen sind so indiziert und (der wer darf 😉 ) können dann via CCP die passenden indizierten PDB-Dateien abgefragt werden, welche dann z.B: in VS/WinDbg die passenden Source runterlädt.

PPS: Wer das ganze noch für SubVersion haben will, kann es bei Stefan nachlesen:
Source Server und Symbol Server Setup mit Subversion

ListBoxItem Template…

Wir haben hier für die ListBox ein eigenes Template gemacht, dass eben alle ListBoxen bei uns in der Anwendung gleich aussehen… dabei haben wir einfach das Beispiel aus der MSDN verwendet: ListBoxItem ControlTemplate Example

Eigentlich sollte man ja meinen, dass dies Beispiel zumindest einigermaßen funktioniert… leider weit gefehlt…

Das Problem ist: Sobald wir ein eigenes DataTemplate für spezielle Daten gemacht haben, hat ein Klick auf ein Element nur dann reagiert, wenn entweder genau auf den Rahmen des Items geklickt wurde oder genau auf den Text:
ListBoxItem

Es ist also relativ schwer z.B. das “!” genau zu treffen…wir haben ewig gesucht, bis wir endlich den Grund gefunden haben… (dank Franks Unterstützung haben wir es mittels Snoop und der Event-Ansicht gefunden): Der Border in dem ControlTemplate hat keine Hintergundfarbe. Somit ist der Border “durchsichtig” (bzw. “x:Null”), was dazu führt, dass ein Klick auf den Border nicht vom Border verarbeitet wird, sondern vom darunterliegenden Scroll-Container… und der macht natürlich hier nichts damit…
Hier ist auch ein Beispielprojekt (VS2008), damit man es mal selber probieren kann.

Für uns jetzt mal die Lösung: Wir setzen einfach die Hintergrundfarbe des Borders des ControlTemplates auf “Transparent”, dann wirken sich jetzt überall die Klicks auf die ListBox aus… danke an Hendrik für diesen Hinweis!

VS2010 Beta 2 – jetzt öffentlich verfügbar!

Seit einigen Tagen konnte ja schon MSDN Abonenten die Beta von Visual Studio 2010 runterladen. Ab sofort ist es auch als öffentlichen Download verfügbar:
Microsoft Visual Studio 2010 Ultimate Beta 2 – ISO

Und wer sich gleich noch über die Neuerungen in der MFC informieren will (ja die gibt es!), kann sich hier ein Video anschauen:
Pat Brenner: Visual Studio 2010 – MFC and Windows 7

vcredist für VS2008 – ATL security update

Wer unbedingt gegen die DLL-Version der CRT/MFC linken will/muss, der steht seit dem ATL-Security-Update vor dem Problem, dass neu übersetze Projekte jetzt zwangsläufig die neue CRT-Version im Manifest eingetragen hat. Dieses verhalten wurde von MS einfach so eingeführt, ohne dies zu kommunizieren. Dies hat natürlich zu etwas Kritik geführt. Aber “Security” rechtfertigt ja alles.
Bisher wurde nach einem Update von VS2008 (also z.B. durch das Feature-Pack oder durch den SP1) im Manifest immer noch die Versionsnummer der RTM-Version eingetragen. Deshalb war es auch jetzt sehr verwirrend, dass plötzlich eine neue Version eingetragen wird, ohne dass man irgend etwas am Projekt geändert hat. Bisher war es nötig, dass man als Define ein “_BIND_TO_CURRENT_CRT_VERSION=1” setzt. Erst dann wurde die aktuelle auf dem Enticklungsrechner verwendete Version eingetragen.

Aber nun ist es nunmal anders und wir sind entweder gezwungen das Security-Update von VS2008 nicht einzuspielen (was ich aktuell als einzige Lösung hier im Automatisierungs-Bereich habe, wenn man auch alte Systeme updaten muss) oder auf neuen Systemen das passende vcredist zu installieren.

Update (2011-04-13): Es gibt schon wieder ein Hotfix:
Siehe: MS11-025: Description of the security update for Visual C++ 2008 SP1 Redistributable Package: April 12, 2011
Update (2011-06-11): Es gibt schon wieder ein Hotfix:
Siehe: MS11-025: Description of the security update for Visual C++ 2008 SP1 Redistributable Package: June 14, 2011

Nur jetzt ist wieder die Frage: Welches ist denn nun die “richtige” vcredist…
Hier die Auflistung der aktuell verfügbaren Versionen:

Wer ganz sicher gehen will, der sollte ab sofort nur noch das oberste installieren!

CurrentItem einer ObservableCollection ermitteln/ändern

In letzter Zeit mach ich mehr mit WPF rum. Hierbei spielt ja das MVVM-Pattern eine große Rolle. Darin werden für änderbare Listen oft eine “ObservableCollection” verwendet. Diese informiert alle beteiligten darüber, wenn ein Element gelöscht oder hinzugefügt wurde. Auch unterstützt es dabei das Feature eines “CurrentItems”. Nur konnte ich dieses bisher nie über irgendwelche Methoden aus dem View-Model heraus ansprechen… immer nur durch WPF-Elemente war dies möglich. So hat z.B. eine ListBox das Property “IsSyncronizedWithCurrentItem“. Damit werden Änderungen am “CurrentItem” durch andere Controls (z.B. durch andere ListBoxen) automatisch auch in alle “angeschlossenen” übernommen.
Nur aus meinem ViewModel war es mir noch nicht gelungen das “CurrentItem” zu setzen (z.B. nach Button-Klick), da ich keine Methode oder Property finden könnte.
Jetzt hab ich es endlich gefunden wie man auf das “CurrentItem” zugreift: Man muss sich zuerst die “DefaultView” der Collection holen. Dann kann man auch die Position des aktuelle Items ändern.
z.B. um das “CurrentItem” zu setzen:

var dv = CollectionViewSource.GetDefaultView(viewModel.MeineCollection);
dv.MoveCurrentTo(viewModel.MeineCollection[1]);

oder um das CurrentItem auszulesen:

var dv = CollectionViewSource.GetDefaultView(this.List);
MessageBox.Show(dv.CurrentItem.ToString());

Hier gibt es auch ein kleines Beispielprojekt: WPF_CurrentItem.zip

Windows 7 installiert…

Nachdem ich auf meinen Wohnzimmer-Rechner schon vor einigen Wochen von Mac OSX auf Windows 7 Ultimate umgestiegen bin, hab ich das ganze vor zwei Tagen auf mit meinem Hauptrechner gemacht. Hier hatte ich vorher Vista 64 Ultimate drauf. Da ich mit der Partitionierung nicht ganz zufrieden war, hab ich mich entschieden alles neu zu installieren und das Ding ganz Platt zu machen.
Zuerst habe ich mit Acronis TrueImage Home 2010 eine Sicherung gemacht und dann die Windows 7 Ultimate x64 installation gestartet. Ich muss sagen: Die Installation hat ca. 25 min. gedauert und er hat alle Hardware in meinem Rechner erkannt (RAID, Soundekarte (die kannte Vista nicht), usw.).

Alles im allem muss ich sagen, dass ich sehr zufrieden bin. Leider musste ich dann natürlich wieder alles installieren, was man so braucht… und die Daten wieder rüberkopieren.

Also, ich kann es nur empfehlen auf Windows 7 umzusteigen. Es macht einen schönen und performanten Eindruck.

Jetzt dürft ihr auch gerne zu meiner Windows 7 HouseParty kommen 😉

GetWindowText und WM_GETTEXT

Es soll ja tatsächlich Leute geben, die den Unterschied der beiden Funktionsweisen noch nicht kennen. Liest man die MSDN-Dokumentation, so kann man erkennen, dass GetWindowText nur zuverlässig für den eigenen Prozess funktioniert. Die Begründung findet man dann bei “The Old New Thing“.

Und damit es jeder auch selber nachvollziehen kann, dass GetWindowText wirklicht nicht zuverlässig für andere Prozesse geht, hab ich hier ein kleines Beispielprogramm:
http://blog.kalmbachnet.de/files/GetWindowText.zip

Wie man aus dem verwiesenen Blog-Eintrag erkennen kann, verwendet intern “GetWindowText” nur WM_GETTEXT, wenn es ein Fenster im eigenen Prozess ist. Sonst wird ein “secret-buffer” verwendet. Ein WM_GETTEXT wird nicht gesendet!

Die ZIP-Datei besteht aus zwei Projekten (Release-EXEn liegen auch drin, damit man es nicht mal mehr selber übersetzen muss).
1. TargetApp: Dieses Wizard erzeugte Fenster-Programm verarbeitet selber die WM_GETTEXT Message und gibt als String “Booga!” zurück. Durch Aufruf von “Help|About…” kann man nachweisen, dass “GetWindowText” hier den String “Booga!” zurück gibt. Es verwendet also WM_GETTEXT um den Text zu erhalten.

2. SpyApp: Dieses Wizard erzeugte Fenster-Programm mach nach Aufruf von “Help|About…”: Es ermittelt das Fenster-Handle des TargetApp durch den Klassennamen (TARGETAPP). Dann kommt der eigentlich Aufruf zu “GetWindowText”. Der zurückgegebene Text wird dann in einer MessageBox angezeigt.

Und dreimal dürft Ihr Raten, was das für ein Text ist 😉 (nein, es ist nicht “Booga!”).

PS: Auch durch den Aufruf von diversen anderen Funktionen wie AttachThreadInput und GetFocus ändert sich an dem verhalten nichts, dass GetWindowText nicht WM_GETTEXT verwendet.

PPS: Wer sich für den Auslöser dieses Posting interessiert, der kann es hier nachlesen:
aktives Control ermitteln
Dort behauptet der Poster, dass “GetWindowText” intern WM_GETTEXT sendet. Und das stimmt natürlich nur für den eigenen Prozess, nicht aber für externe (in diesem Thread geht es nur um externe Prozesse).

[ADD: 2009-10-11]
PPPS: Wer sich wundert, warum im Source-Code der SpyApp sowas komisches wie “AttachThreadInput” aufgerufen wird, der sollte einfach nur den obigen Thread lesen… dieser Aufruf ist einfach sinnlos und kann getrost entfernt werden; ein anderer behauptet in dem Thread, dass es “unbedingt notwendig” ist, damit das “GetWindowText” intern ein WM_GETTEXT verwendet (was es ja für externe Prozesse nicht tut, wie das Beispiel ja schön zeigt).