Zwei Tools, die die interne Kommunikation über den TFS noch einfacher machen…

Die Dokumentation, gehört bei uns zu dem Bereich, der nicht direkt mit der Entwicklung verbunden ist.
Ein Teil der Doku wird vorab von den Entwicklern entworfen, aber erhalten letzten Endes den Feinschliff von Anderen. Auch die weitere Pflege und auch die Übersetzungen werden nicht von der Entwicklungsmannschaft durchgeführt.

Eigentlich haben wir nur „everlasting“ Projekte haben, dass heißt unsere Projekte werden immer weiter gepflegt. Das ändert sich oft erst nach so nach 6-10 Jahren wenn sie in eine neues Produkt mit einem kompletten Redesign übergehen.
Das bedeutet auch für die Dokumentation eine immer wiederkehrende Überarbeitung. In der Vergangenheit, haben oft genug Verbesserungen nicht den Weg in die Doku gefunden, weil einfach vergessen wurde eine entsprechende Notiz zu schreiben.
Großes Erstaunen herrschte dann oft, wenn der Vertrieb ein Feature anmahnte, dass die Entwicklung schon längst implementiert hatte.

Mit der Einführung des Team Foundation Server (TFS) und Visual Studio Team Systems 2008 wollte ich auch den Informationsfluss an andere Firmengruppen verbessern, insbesondere zu den Personen, die die Doku schreiben und für die Publikationen der Updates zuständig sind.

Erreicht haben wir das durch zwei ganz einfache Schritte:

  1. Haben wir Visual Studio Team System Web Access 2008 SP1 Power Tool installiert, das als CTP vorliegt. Dadurch kann jeder einfach und simpel von jedem Rechner auf den TFS und die Workitems zugreifen ohne VS installiert zu haben.
    Die entsprechenden User wurden mit „Reader“-Rechten im TFS ausgestattet, sofern sie nicht sowieso schon zum Teil die Rolle eines Testers hatten.
  2. Habe ich das Team Foundation Server Event Subscription Tool installiert.
    Die Events die man über die Menüs in VS-2008 einrichten kann sind doch etwas dürftig.
  3. Mit dem Team Foundation Server Event Subscription Tool  habe ich dann zwei WorkItemChangedEvents eingerichtet, die bei einem Status „Closed“ (für Tasks) oder „Resolved“ (für Bugs), sofort eine Email mit dem entsprechenden Infos des Workitems an eine Emailverteilergruppe sendet.

Jetzt wird jeder „Close“ eines Tasks, bzw. jedes „Resolved“ eines Bugs sofort weiter gemeldet.
Die Mitarbeiter können sich über die entsprechenden Links, die Informationen aus dem Task oder Bug holen und die Dokumentation, Readme’s, Hilfedateien und Übersetzungen anpassen.

PS: Ja man hätte dies auch noch mit eigenen Projekt-Tasks und spezielen Statis regeln können, aber der Weg, so erschien mir einfach, simpel und praktikabel.

PPS: Im dem Team Foundation Server Event Subscription Tool  kann man übrigends noch andere sehr nützliche Benachrichtigungen erzeugen…

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.