Eigentlich hat sich seit 1869 nichts geändert in dieser Welt…

Gerade habe ich eine Passage in Der Idiot von F.M. Dostojewski gelesen und konnte mir ein Schmunzeln nicht verkneifen:

Freilich, heißt es, freilich stehen bei uns alle im Staatsdienst oder wenn sie nicht im Augenblick darin stehen, dann haben sie darin gestanden oder werden sie darin stehen, und das geht bei uns schon so seit zweihundert Jahren nach dem schönsten deutschen Vorbild von den Urgroßvätern bis zu den Ururenkeln; aber gerade die Beamten, gerade die sind ja die unpraktischsten Leute der Welt, und es ist doch bei uns schon so weit gekommen, daß noch vor kurzem abstraktes Wissen bei völligem Mangel an praktischem Wissen unter den Staatsdienern selbst fast als größte Tugend und beste Empfehlung betrachtet wurde!

Der Idiot, F.M. Dostojewski
Teil III, Kapitel 1 (direkt in der Anfangspassage)

Hat sich irgend etwas geändert?
Es mag zwar nicht mehr jeder im Staatsdienst stehen, aber was den Praxisbezug unserer Beamten und Politiker betrifft und die Abwesenheit jedes Realitätsbezuges und Praxis, hat sich irgendwie wirklich nichts geändert.

Auch wenn diese Zeilen auf das Russland der Zarenzeit um 1860 gemünzt sind. Irgendwie scheinen sich bestimmte Dinge in Bezug auf Politiker und Beamte auch 150 Jahre später in Deutschland nicht zu ändern :mrgreen:

Abgespecktes 4NT als TCC/LE von JP-Software als Freeware

Ich bin seit Jahren ein begeisterter Fan von 4NT (kennengelernt habe ich es noch als 4DOS unter DOS 4.0).
Was man so alles vermisst wenn man mal mit CMD.EXE arbeitet merke ich immer sofort, wenn ich ein DIR oder COPY ausführe und die komplexen Ranges, die 4NT bietet , sofort vermisse.
Ganz zu schweigen von netten Befehlen wie LIST, SELECT und anderem.

Auf den großen Bruder Take Command habe ich bisher immer verzichtet.
Ich verwende 4NT gerade auch da, wo ich komplexe Batchfiles für den gesamten Weg vom Build bis zum Setup benötige. All‘ das Kopieren von Dateien und Tools anwerfen, die dann irgendwann ein fertiges SETUP Paket erzeugen. Es ist einfach unschlagbar von den internen Funktionen, die hier geboten werden.

Jetzt hat mich JP-Software überrascht:

  1. Negativ: 4NT als Produkt alleine gibt es nicht mehr. Man kann den gesamten Funktionsumfang nur noch als Take Command erhalten.
  2. Positiv: Es gibt 4NT in etwas abgespeckter Form nun als TCC/LE (Take Command Console LE) kostenlos ❗

Soweit ich das sehe fehlt nur der Batch-Debugger und der Batch-Compiler, die ich sowieso kaum nutze, sonst sind alle meine gliebten Befehlszeilenfunktionen vorhanden.
In den internen Funktionen wird man evtl. die Datums- und Zeitfunktionen vermissen, die komplett herausgenommen wurden. Gleichfalls wie einige andere Funktionen.
Selbst mit den eingeschränkten Funktionen: TCC/LE ist ein Muss ❗

Download hier: http://www.jpsoft.com/tccledes.htm

Rätselhafte Auswahl bei Microsoft…

Immer wieder staune ich über die rätselhafte Auswahl von Funktionen, die es als Wrapper in die MFC geschafft haben. Warum werden nicht alle Funktionen in die MFC Wrapper aufgenommen?

CImageList::GetIconSize sucht man vergeblich, man muss die API Funktion ImageList_GetIconSize verwenden… OK, wenn diese Funktion nicht in allen Windows Versionen verfügbar wäre. Aber gerade diese Funktion existiert schon seit der aller ersten COMCTL32 Version!

Man könnte meinen, dass mit der Zeit fehlende Funktionen irgendwann mal in neueren Funktionen nachgerüstet werden, aber da hofft man scheinbar vergebens.
Immer wieder verwirrt mich das. 😕

Kann man GDI Objekte aus anderen Prozessen verwenden und auslesen?

Frage eines Regulars neulich in microsoft.public.de.vc

Habe einen HRGN Handle von einem anderen Process.
Deshalb liefert GetRegionData wahrscheinlich Size 0 zurück.
int iSize = ::GetRegionData((HRGN)hHandle, 0, NULL); 
Wie kann ich GetRegionData eines anderen Processes auslesen ?

Die Antwort ist klar und eindeutig ein Nein!

Zitat Feng Yuan in einem fast 7 Jahre alten Thread, den ich mir damals hinter die Löffel geschrieben habe:

On Windows NT/2000/XP, GDI does have a system-wide GDI object table. But certain data is stored in per-process user mode area, and the process ID of the creating process is stored in GDI object table.
For every operation with a GDI object, GDI32.DLL always checks for matching  process ID. So cross-process usage of GDI object is not allowed by design, at least for NT/2000/XP.

Wem das aber nicht langt, der kann diese Info auch in der MSDN nachlesen unter GDI Objects (gleich der erste Satz):

GDI objects support only one handle per object. Handles to GDI objects are private to a process. That is, only the process that created the GDI object can use the object handle.

Wer also Informationen zu GDI Objekten aus anderen Prozessen benötigt, der muss wohl oder übel zu DLL-Injection greifen.

Die Unsitte GetAsyncKeyState statt GeyKeyState zu verwenden…

Immer wieder wird in Foren gefragt, wie man  feststellen kann, ob z.B. die Umschalt- oder Strg-Taste gedrückt ist.
Nur zu oft liest man als Antwort: Nimm GetAsyncKeyState ❗

Zwei Dinge stören mich an dieser Antwort:

  1. Dem Frager ist meistens gar nicht bewusst, dass es für die entsprechenden Tasteneingaben immer auch eine entsprechende Nachricht WM_KEY… Nachricht gibt.
    Hier wäre ein Grundstudium der Windows API angesagt!
  2. Ist den meisten Fragern (und Antwortenden) nicht klar, das Nachrichten chronologisch einlaufen aber GetAsyncKeyState den aktuellen Zustand der Taste zurückgibt, eben asynchron, wie der Name es schon andeutet.

In den meisten Fällen ist diese Antwort also falsch!

Im Detail will ich das auch erklären:
GetAsyncKeyState liefert den Zustand der Umschalt-Taste zu dem Zeitpunkt an dem die Funktion aufgerufen wird. Im Gegensatz dazu liefert GetKeyState den Zustand der Taste zu der Zeit, als die Nachricht die aktuell bearbeitet wird einlief, bzw. erzeugt wurde. (Genau genommen geht es hier um die letzte Windows-Nachricht)
Das Problem wird offensichtlich, wenn das OS durch hohe Prozessorauslastung Nachrichten etwas verzögert abarbeitet. Es ist klar, dass GetAsyncKeyState zu falschen Ergebnissen führen muss, bzw. ein evtl. gedrückte Strg-Taste evtl. nicht beachtet wird. Die Folge könnte sein, dass aus einer Kopieraktion, ein Verschieben wird. Fatal für den Benutzer.

Eigentlich fällt mir gar kein vernünftiger Grund ein GetAsyncKeyState zu verwenden! Außer man pollt, und pollen ist das Letzte was ich in eine Windows Applikation machen wollte.

Vermutlich hat irgendwann irgendein etwas unterbemittelter Programmierer angefangen einen Tipp mit GetAsyncKeyState zu geben und dieser Unsinn kursiert nun auf ewig durch die Netze…

In welcher Reihenfolge werden Ressourcen in unterschiedlichen Sprachen gefunden?

Immer wieder taucht die Frage auf, wie die Funktionen zum Laden von Ressourcen (LoadImage, LoadCursor, LoadMenu etc.) eigentlich arbeiten und entscheiden aus welcher LANGID-Sektion die Ressource geladen wird.

Die Dokumentation von FindResource – auf der alle diese Funktionen basieren – gibt leider keine Auskunft.

Wenn man jedoch etwas sucht wird man in der Dokumentation von Developing International Software fündig. Dort findet sich der folgende Abschnitt mit dem Titel Multiple Language Resources, in dem auch beschrieben wird wie FindResource arbeitet und wie eine Ressource gesucht wird:

If the FindResource and FindResourceEx functions do not find any resources that match the language ID’s primary language, they search for resources tagged as „language-neutral.“ This language ID is useful for resource elements such as icons or cursors that are identical for all languages. If a bitmap or an icon will differ for some languages, you can define one language-neutral bitmap as the default and specify language IDs for as many other customized bitmaps as required. For example, bidirectional applications might require bitmaps with right-to-left directionality. Because the FindResource and FindResourceEx functions always search for specific language IDs first, they will always find a bitmap tagged with that language ID before they find one tagged as language-neutral. The search algorithm they follow is summarized in the following list:

1. Primary language/sublanguage
2. Primary language
3. Language-neutral
4. English (skipped if primary language is English)
5. Any

SQL-Fehlermeldung: Der Abfrageprozessor hatte während der Abfrageoptimierung zu wenig Stapelspeicherplatz. Vereinfachen Sie die Abfrage.

Auf einer Datenbank in einem MS-SQL 2005 Server (32bit) verursachte ein simpler DETETE FROM tbl… in einem meiner Programme die folgende Fehlemeldung:

Der Abfrageprozessor hatte während der Abfrageoptimierung zu wenig Stapelspeicherplatz. Vereinfachen Sie die Abfrage.

Das Ganze war etwas mysteriös, und auch in den Newsgroups und im Netz gab es keine vernünftige Antwort. Also habe ich kurzerhand eine Supportanfrage an Microsoft gestellt.

Hier in Kurzform die Problematik:

  • Wir haben eine sehr komplexe Datenstruktur, die der Anwender mit der Hilfe eines Tabellen-Generators selbst manipulieren und definieren kann. Die Folge in einem Fall:
    Es gab zu einer Tabelle über 400 Fremdschlüssel.
  • Besagte Fremdschlüssel sollten garantieren, dass aus dieser Tabelle, die für Datensatz Klassifikationen verwendet wurde, keine verwendeten Datensätze gelöscht werden können. 
  • An dem Statement selbst gab es nichts zu optimieren, das war wirklich nur ein einfaches Statement im Stile von DELETE FROM tbl WHERE Id=4711

In Kurzform die Antwort von Microsoft:

  • Das Problem ist nachvollziehbar.
  • Das Problem ist hausgemacht und liegt an der Anzahl der Fremdschlüssel.
  • Einen Fix bzw. eine Änderung oder Parameter mit denen man das Verhalten ändern, oder erweitern kann, gibt es nicht und ist nicht geplant.
  • Der Speicherblock, der hier zu klein wird, ist bei einem MS SQL-2005 Server in der 32bit Version 512KB groß, auf einer 64bit Installation ist besagter Speicherblock viermal so groß, d.h. 2MB!
    Der Fehler tritt auf einem 64bit Server und der gleichen DB-Struktur nicht auf, dafür aber später 😉 , wenn noch mehr Schlüssel verwendet werden.

Einen kleinen bissigen Kommentar kann ich mir hierzu aber nicht verkneifen, denn ganz blind bin ich in dieses Problem nicht hinein gelaufen 😈

Hier der entsprechende Link zu Spezifikationen der maximalen Kapazität für SQL Server 2005, und dort lesen wir folgendes:

Verweise auf Fremdschlüsseltabellen pro Tabelle 253

– und in der-

Fußnote 4:
Auch wenn eine Tabelle eine unbeschränkte Anzahl von FOREIGN KEY-Beschränkungen enthalten kann, beträgt das empfohlene Maximum 253. In Abhängigkeit von der Hardwarekonfiguration, die SQL Server hostet, kann das Angeben weiterer Fremdschlüssel den Abfrageoptimierer bei der Verarbeitung stark beanspruchen.

Diese Information deckt sich mit der englischen Dokumentation.

Meine Interpretation dazu ist die folgende:
Es kann den Abfrageoptimierer stark beanspruchen wenn man so einen Konstrukt baut, allerdings war und ist mir das egal. Von mir aus kann die Ausführung Minuten dauern. Der Fall des Löschens in dieser Tabelle ist die seltene Ausnahme. Das Problem ist hier, dass die Ausführung gar nicht möglich ist. Hier steht nicht, dass ich nicht mehr als 253 Schlüssel verwenden darf! Wenn dem so ist, müsste dieser Satz klar umformuliert werden, oder es müsste bereits beim Anlegen eines weiteren Fremdschlüsselverweises eine Fehlermeldung kommen.
De facto steht hier: „Auch wenn eine Tabelle eine unbeschränkte Anzahl…“
Die Operation sollte fehlerfrei durchgeführt werden können, was aber nicht so ist.

Besagte Supportanfrage wurde geschlossen ❗

Bleibt noch Abschließendes hinzuzufügen:

  • Auch der MS-SQL Server 2008 zeigt das gleiche Verhalten.
  • Man erhält den selben Fehler auch im MS-SQL 2000, dort heißt er dann
    Interner Fehler des Abfrageprozessors: Im Abfrageprozessor wurde bei der Ausführung ein unerwarteter Fehler festgestellt.

VS Tipps & Tricks: Verstecke Optionen in DEVENV.EXE: /AssociateFiles

Wer kennt das nicht: Man probiert einem neuen netten kleinen Editor aus, oder ein anderes Programm und wundert sich hinterher, dass bestimmte Dateiendungen nicht mehr mit den gewohnten Programmen verbunden sind…

Für Visual Studio gibt es hier einen netten undokumentierten Befehl, der es einem ganz einfach erlaubt, die Dateiverknüpfungen für Visual Studio wieder herzustellen ohne eine Reparaturinstallation fahren zu müssen.

Einfach DEVENV.EXE /AssociateFiles aufrufen.

Anmerkungen:

  • Dieser Befehl funktioniert sowohl in VS-2005 als auch VS-2008.
  • Es versteht sich von selbst, dass unter Vista dieser Befehl nur elevated (also als Administrator) ausgeführt werden kann. Also am Besten einen Visual Studio Command Prompt als Admin ausführen.
  • Dieser Befehl ist nicht direkt dokumentiert aber indirekt über eine Fehlermeldung in der Msdn und einige Change-Logs für VS-2005 SP1. So bin ich auf ihn gestoßen.

Tipps & Tricks:TFS Undo Checkout für einen anderen Anwender/Workspace erzwingen…

Für VSS hatte ich das entsprechende Vorgehen ja bereits unter diesem Artikel beschrieben: VSS Undo Checkout für einen Anwender den es nicht mehr gibt….

Während es im VSS nur eine Reaktionmöglichkeit hatte gibt es beim Arbietenmit dem Team Foundation Server gleich mehrere Szenarien und Möglichkeiten der Reaktion:

  • Ein Checkout muss rückgängig gemacht werden, weil ein anderer Benutzer einen exklusiven Checkout durchgeführt hat, dieser aber selbst nicht erreichbar ist.
  • oder man möchte nur den Checkout Lock zurücksetzen oder lockern und nicht den gesamten Checkout rückgängig machen
  • oder ein Mitarbeiter hat die Firma verlassen und alle entsprechenden Checkouts müssen zurückgerollt werden.

Zu jedem dieser Vorgänge gibt es eine spezielle Operation im TFS. Alle Operationen setzen voraus, dass man in dem entsprechenden Projekt administrative Rechte hat und alle Befehle müssen von der Befehlszeile aus eingegeben werden über TF.EXE.

Das mit diesen Befehlen nicht leichtfertig umgegangen werden sollte versteht sich hoffentlich von selber ❗

  1. Der Undo des Checkouts kann durch den folgenden Befehl erreicht werden:
    tf undo /workspace:BenutzerWorkspace;Benutzer $/Projekt/DateiName.cpp
    http://msdn.microsoft.com/de-de/library/c72skhw4
  2. Als Administrator hat man aber auch die Möglichkeit jede Form von Locks eines anderen Anwenders zu ändern. Das geschieht über die Befehlszeile mit:
    tf lock /lock:none $/Projekt/Dateiname.cpp
    http://msdn.microsoft.com/library/47b0c7w9
  3. Als letzter Holzhammer steht es einem Administrator offen einen Workspace eines Anwenders zu löschen. Dies löscht natürlich nicht die lokalen Dateien des Workspaces, führt aber dazu, dass alle Checkouts und alle Locks rückgängig gemacht werden. Diese letzte Methode eignet sich besonders dafür, die Daten ausgeschiedener Mitarbeiter aus dem TFS zu entfernen.
    tf workspace /delete WorkspaceName;DOMAIN\Benutzer
    http://msdn.microsoft.com/library/y901w7se

Evtl. muss noch mit der Option /s der Servername angegeben werden. Im Allgemeinen ist dies aber nicht notwendig. Für keinen der oben genannten Befehle ist muss man an den entsprechenden Rechner mit dem  betreffenden Workspace gehen um diese Befehle durchzuführen. Gerade das ist ja oft nicht möglich.

Videos für das C++ Community Event vom 17.04 in Bad Homburg statt

Wie schon angekündigt sind nun die Videos des Community Events in Bad Homburg veröffentlicht worden.
Boris Jabes aus Redmond hatte uns Einblicke aus dem VC++ Featurepack in die MFCNext, die neuen Marshalling Features und TR1 gegeben und nicht zu vergessen einige Ausblicke auf VC++ 10.

Alles findet sich auf dem Blog von Christian Binder, der das Ganze mit Dariusz Parys gefilmt hat:

http://blogs.msdn.com/cbinder/archive/2008/05/27/videos-das-neue-c-feature-pack-und-vsts-f-r-native-c-developer.aspx