Thomas Wölfers Baustatik-Blog

Thomas Wölfers Baustatik Blog

Launch != Verfügbar


Microsoft plant ja für Februar 2008 ein gross angelegtes Launch Event für Visual Studio 2008, Windows Server 2008 und SQL Server 2008. Das ganze dauert gleich 3 Tage - für meinen Geschmack ein bisschen zu heftig.

Wie dem auch sein mag, und was viele vielleicht nicht wissen: Nur weil der Launch-Event im Februar ist, bedeutet das nicht, das es die Produkte dann auch gibt. Das Visual Studio 2008 kann man ja heute bereits herunterladen - den SQL Server wird es hingegen im Februar noch gar nicht geben: Dessen "offizieller" Verfügbarkeitstermin liegt dann noch in der Zukunft, und zwar im 2. Quartal 2008. Nicht im Februar.


Automatische Builds mit Visual Studio und Source Safe


Warum überhaupt automatische Builds? Kurze Antwort: Weil man sonst nicht weiss, ob man sein Projekt überhaupt bauen kann. Der Grund dafür ist der, das das Visual Studio einige "magische" Dinge tut die dazu führen können, das man ein Projekt bauen kann, obwohl - wenn alles "ordnungsgemäß" ablaufen würde - der Build fehlschlagen müsste.

Ich habe dafür ein paar Beispiel, die in unserer aktuelle Solution tatsächlich aufgetreten sind. Die Solution umfasst zur Zeit 65 Projekte. 2 davon sind Setup-Projekte, die anderen sind C# sowie Native und Manged C++ Projekte. Ein Projekt enthält überhaupt keine Code, sondern ausschliesslich Dokumentation in Form von HTML, CSS, JavaScript und Bitmaps.

Problemfälle die aufgetreten sind:

  • Ein (C#) Projekt konnte (innerhalb von VS) gebaut werden, obwohl es einen Typ benutzte der aus einer Assembly stammte, die nicht referenziert wurde. (Der Build auf der Kommandozeile schlug fehl.)
  • Ein (Managed C++) Projekt konnte gebaut werden, obwohl im Code ein Typ aus einer nicht referenzierten Assembly verwendet wurde. (Der Build auf der Kommandozeile schlug fehl.)
  • Einige C++ Projekte konntn gebaut werden, obwohl die Projekt-Abhängigkeiten (und damit die Build-Reihenfolge) nicht korrekt war.

Der eigentliche Grund warum wir regelmäßige "nächtliche" Builds auf einem Buildserver durchführen wollten war aber ein anderer: Wir haben einen mitlerweile recht großen Satz an Testcases, bei denen es aufgrund des Umfangs langsam aber sicher unhandlich wird, sie interaktiv durchlaufen zu lassen. Statt dessen werden dieses Testläufe nun einfach automatisch nachts durchgeführt - schlägt ein Test fehl, werden die Entwickler per eMail informiert. Praktische Sache.

Nun sollte man annehmen, das automatische Builds eine einfach Sache sein sollten - schließlich ist das Projektsystem seit Visual Studio 2005 ja auf MSBuild aufgebaut: Zumindest hiess es das immer. In der Theorie sollte es also reichen

MSBuild NameDerSolution

einzugeben, und MSBuild sollte dann genau das gleiche Produzieren, was auch innerhalb der IDE stattfindet. Nun - das ist leider nicht so, wie ich feststellen musste. Doch eins nach dem anderen: Das erste Problem war nämlich, das vor jedem Build zunächst einmal ein aktueller Satz an Quellcode-Dateien aus dem Revision Control System besorgt werden muss. Wir verwenden als RCS Visual Source Safe (*1), und also machte ich mich auf die Suche in der zugehörigen Dokumentation.

Die ist, um es höflich zu sagen, etwas mager. Um per Kommandozeile ein Get-Latest-Version zu machen, muss man folgendes tun:

  • Die Environment-Variable "ssuser" auf einen gültigen Source Safe Usernamen setzen.
  • Die Environment-Variable "sspwd" auf das zugehörige Passwort setzen.
  • Die Environment-Variable "SSDIR" auf das Source-Safe Verzeichnis der Solution setzen.
  • Per "cd" in das Verzeichnis wechseln, in das Source Safe die lokale Kopie des Codes platzieren soll. (Es gibt eine Option mit der man dieses Verzeichnis angeben kann, die habe ich aber nicht ans laufen gebracht.)
  • Dann per "ss" Kommando die neueste Version holen: ss get $/PfadZurSolutionInderSSDatenbank -R
  • Dann bekommt man das Problem, das Source Safe als erstes einen Prompt ausgibt und fragt, ob das aktelle Verzeichnis das permanente Default-Verzeichnis für die Solution werden soll. Mit dieser Frage hatte ich zwei Probleme: 1) Ich verstehe sie nicht und 2) Für ein automatisches Build ist sie hinderlich. Nun gibt es eine Option "-Y", mit der man angeblich alle interaktiven Prompts abschalten kann - aber leider weiss ich nicht, ob die Antwort auf die Frage dann "Ja" oder "Nein" lautet - und außerdem habe ich die Option ausprobiert: Die Frage wurde aber trotzdem nicht unterdrückt. Daher Rückgriff auf MS-DOS Zeiten:
  • Anlegen einer Datei "N.dat", die ausschließlich den Buchstaben N enthält und abändern des SS-Aufrufs auf:
  • ss $/PfadZumProjekt -R <n.dat

Damit hat man zumindest schon mal den aktuellen Quellcode. Nun gehts ans bauen. Nichts einfacher als das, dachte ich:

msbuild NameDerSolution.sln /t:Rebuild /p:Configuration=Release

In der Theorie ist das auch richtig - aber in der Praxis ging das bei mir nicht.

  • msbuild kann keine Setup-Projekte bauen
  • msbuild kann auch keine C++ Projekte bauen, und delegiert die Arbeit dazu an ein anderes Tool. Das übersetzt dann in der Theorie auch richtig - nur leider klappte das auch nicht.

Unabhängig von den fehlenden Setup-Projekten (damit könnte ich leben), habe ich zwei Probleme gefunden:

1) Wenn man in einem Managed C++ Projekt eine Referenz auf ein anderes Projekt mit Managed Code hat, dann wird das von MSBuild völlig ignoriert. Die Referenz müsste eigentlich in die Compiler-Option "/FU PfadZurAssemblyDerReferenz" umgesetzt werden. Das passiert aber nicht. Resultat: Der Compiler kennt die aus der referenz stammenden Typen (und Namespaces) nicht, und der Build schlägt fehl. Das kann man allerdings umgehen, indem man nicht das Projekt referenziert, sondern die Assembly per "#using <Pfad zur Assembly>" einbettet: Nicht schön, funktioniert aber.

2) Ich hatte einen Fall (den ich auch immer wieder reproduzieren kann, aber leider nur mit genau diesem Projekt), bei dem im Build auf der Kommandozeile eines C# Projektes eine gesetzte Referenz ebenfalls einfach ignoriert wurde. Warum das in diesem Fall passierte konnte ich nicht herausfinden, und einen Workaround dafür habe ich auch nicht. (In allen anderen Fällen funktionierte das ja auch, nur in einem einzelnen Fall eben nicht. Das ist aber genauso gut, als wenn es nie gehen würde: Der Build schlägt fehl.)

Also kam MSBuild leider nicht in Frage. Netterweise gibt es aber eine Alternative: Visual Studio hat auch einen Kommandozeilen-Modus, mit dem man Builds durchführen kann. Der Aufruf dazu geht wie folgt:

devenv PfadZumSolutionFile.sln /Rebuild "Debug" /out PfadZuEinemLogFile.log

Ruft man das aber so auf, dann passiert folgendes: C++ Build schlagen fehl. Grund: Include- und Lib-Dateien werden nicht gefunden. In der Theorie ist es so, das man über die VC++ Projektoptionen in der IDE die richtigen Pfade für Header und Libraries einstellt, und das die Kommandozeilen-Variante dann diese Einstellungen verwendet. Für Header hat das bei mir auch geklappt, für Libraries aber nicht.

Workaround: Vor dem Aufruf von "devenv" die Environment-Variablen "INCLUDE" und "LIB" mit den Pfaden zun den Headern und Libraries setzen, und "devenv" dann mit der zusätzlichen Option "/UseEnv" aufrufen.

--

(*1) Mir ist bewusst das Source Safe keinen besonders guten Ruf geniesst, und ich bin auch mit einigen Dingen darin eher unzufrieden. Unabhängig davon kann ich aber die Meldungen über "verlorerne" Daten, die immer wieder gern angebracht werden, absolut nicht bestätigen.


Visual Studio 2008 ab sofort verfügbar


Mit einem MSDN Abo kann man das ganze seit gestern Abend runterladen. Es gibt eine ganze Menge Neuerungen und Veränderungen - das hier sind die meiner Ansicht nach wichtigsten:

  • VS 2008 kann parallel zu VS 2005 installiert werden
  • Visual Studio Tools for Office ist nun integriert
  • Unit Testing jetzt auch in der "Professional" Edition (Danke !)
  • Quellcode zum .NET Framework (dazu gibts Source Server, die aber gerade erst angeworfen werden: Wie man tatsächlich in den Quellcode zum .NET Framework stept soll nächste Woche veröffentlicht werden.)
  • LINQ, Anonymous Types, Lambda Expressions, Extension Methods, Automatic Properties (in C# und VB)
  • Der HTML/CSS Designer ist nun der gleiche wie in Expression Web.
  • AJAX fest integriert
  • Javascript deutlich besser integriert: Mit Intellisense und Debugger-Support

Das Download der Pro-Edition hat etwa 3.3 GB, das Download für die MSDN Library etwa 2 GB. Wer außerdem noch SourceSafe Support will, der braucht das Update CTP von Source Safe und sollte außerdem diesen KB Artikel lesen, denn es braucht einen manuellen Installationsschritt, der im KB Artikel erklärt wird. (Die fertige Version vom neuen Source Safe wird dieses Problem nicht haben.)

Achja: Die kostenlosen Express Versionen gibts auch wieder. VS Express Developer Center


Gestern: Visual C++ 2008 and beyond


Ich sags nicht gern, aber ich war nicht besonders beeindruckt. Im Kern läuft die Sache für mich darauf hinaus: VC++ 6.0 war die letzte wirklich hervorragende C++ IDE von Microsoft. Danach ist bist VS 2005 nicht viel passiert in Sachen C++. Auf Basis der Veranstaltung von gestern kann ich sagen: Von VS 2005 bis VS 2008 ist eigentlich auch nichts passiert. Die VC Jungs versprechen aber, das sich das mit der nächsten Version (VC 10, zu erwarten in 2010) bessern soll. _Dann_ soll Intellisense funktionieren, es bessere Libraries geben etc. pp.

Dummerweise ist das erst in 2 Jahren (wenn der Zeitplan klappt, und wir wissen alle, das das nie der Fall ist.).

Achso: MFC-Freunde wird das freuen. Die VC++ Version in 2008 wird _kein_ relevantes Update von MFC erhalten. Es soll aber, ein paar Monate nach dem Release von VS 2008, ein Download geben, das die MFC aus Ihrem 1990er-Zustand erlöst, zumindest was das UI angeht.

Den Abend hätte ich mir echt sparen können. Er hat mich allerdings darin bestätigt, das es eine gute Wahl war, sich von VC++ zu verabschieden und möglichst viel mit C# zu unternehmen.

Nachdem ich etwa 5 (?) jahre lang VC++ MVP war tut mit das in der Seele weh - aber vor 2010 wird offenbar nichts relevantes passieren. Zumindest nichts, mit dem die Jungs mich gestern begeistert hätten.


Rechtschreibprüfung für HTML im Visual Studio


Danach schaue ich schon seit längerer Zeit immer wieder mal: Ein AddOn fürs Visual Studio mit dem man die Rechtschreibung von Texten in HTML-Dokumenten innerhalb des Visual Studios überprüfen kann. Jetzt habe ich eines gefunden das

a) funktioniert und zwar

b) auch für deutsch und obendrein

c) auch noch kostenlos ist.

Michail Arkhipov: Spell Checker for HTML and ASP.Net pages.

Beim Installieren (Windows Vista X64 Premium) gab es ein Problem: Nach der Installation wollte der Eintrag für die Rechtschreibprüfung im Tools-Menu nicht auftauchen. Auch der Troubleshooter half nicht weiter.

Was dann geklappt hat war folgendes:

  • Regedit "Als Administrator starten".
  • HKEY_CURRENT_USER\Software\Microsoft\Visual Studio\8.0\Addins exportieren.
  • Regedit beenden und mit dem normalen Account starten.
  • Das exportierte .reg-File wieder importieren.

 


SQL Server anyone?


Ich habe damit noch nie besonders viel gemacht, und verzweifle gerade ein bisschen an der SQL Server Dokumentation... und finde auch nichts in Google oder Live.

Kann mir irgend jemand sagen, wie man im WHERE Bereich des SQL Statements zwei DateTime Werte vergleicht? Ich hätte gerne nur die Records...

WHERE ( dateTimeColumnInTable <= " + DateTime.Now.ToString( CulturInfo.InvariantCulture ))

Nur - so wie ichs hingeschrieben habe gehts nicht. Ich kann mich erinnern, das man bei mySQL auch irgendwas merkwürdiges machen musste ( Konvertieren in Ticks seit 1970 und die vergleichen..?) - weiss aber auch nicht mehr, was das war.

Bin für jeden Hinweis danbar.

 

 


ZipFiles mit der PowerShell bestücken


Ich hatte vor kurzem ein kurzes Fragment eines PowerShell Skripts gepostet, mit dem man "ganz einfach" eine Zip-Datei anlegen kann. Damit will man natürlich auch was tun - in meinem Fall will ich da Dateien reintun, weil die dann später in gezippter Form per eMail versendet werden sollen. Dazu braucht man zunächst ein Folder-Objekt. Das bekommt man relativ einfach per new-Object:

function CreateZip( $path )
{
   set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
   $zipFile = (new-object -com shell.application).NameSpace( $path )
   return $zipFile
}

Das Folder Objekt (das ist, was man tatsächlich bekommt) hat dazu eine passende Methode: CopyHere(). Wenn man danach sucht, dann findet man auch schnell Beispiele, wie man damit Dateien in die Zip-Datei bekommt. Angenommen, man hat eine Liste von vollständigen Pfaden zu Dateien in $files, dann geht das laut den Beispielen so:

$files | foreach {
   $zipFile.CopyHere( $_.fullname )
}
 

Das Problem dabei: Das klappt nicht richtig. Manchmal sind dann nämlich alle Dateien drin, manchmal nur die erste oder die letzte, und manchmal bekommt man eine Fehlermeldung, das die Zip-Datei defekt sei.

Ich habe ein bisschen nachgewühlt und die Symptome untersucht, und meiner Ansicht nach ist der Grund dafür der, das (im Gegensatz zum normalen Verhalten von Methoden in COM-Objekten) die Methode CopyHere() asynchron ist. Das bedeutet, der Aufruf von CopyHere() kommt sofort zurück, startet aber vorher einen asynchronen Vorgang der das eigentliche kopieren und komprimieren besorgt.

Macht man das also in einer Schleife für mehrere Dateien, laufen mehrere dieser asynchronen Vorgänge gleichzeitig - und kommen sich natürlich beim schreiben in die Zip-Datei in die Quere, da es offenbar keine Instanz gibt, die sich dann wieder um synchronisieren kümmert. Man muss das also selbst machen - zumindest habe ich keinen anderen Weg gefunden.

Man kann es aber dankbarerweise selbst machen, indem man überprüft, was das Zipfile über seinen eigenen Inhalt denkt: Das Folder-Objekt das das Zipfile abbildet, hat nämlich eine Methode Items(), und die hat ein Property Count. Man kann also nachsehen, ob bereits die Anzahl an Files im Zip sind, von denen man denkt das sie drin sein sollten. Sind sie es nicht, dann muss man noch ein bisschen warten. Eine funktionierende Method sieht also so aus:

$filesCopied = 1
$files | foreach { 
   $zipFile.CopyHere( $_.fullname )
   do {
      start-sleep -milliseconds 500
   } 
   while ( $zipFile.Items().count -lt $filesCopied )
   $filesCopied++;
}


ZIP-Datei mit PowerShell erzeugen


Einige Dinge sind noch immer so einfach wie vor 20 Jahren. Ein Beispiel dafür ist das Erzeugen einer ZIP-Datei mit der PowerShell. (Kleiner Aufsatz für den Einstieg in die Powershell von mir hier.)

Von Haus aus gibt es kein Kommando mit dem man unter Windows "einfach so" eine neue Zip-Datei per Kommandozeile anlegen kann - zumindest kenne ich keins. Mit der PowerShell ist das aber leicht nachgerüstet, denn (leere) Zip-Dateien sind nicht besonders kompliziert. Sie bestehen im wesentlichen aus einem konstanten Header. Der beginnt immer mit PK (Phil Katz), gefolgt von ein paar konstanten Byte. Wenn man die kennt, kann man mit dem folgenden PowerShell Skript "einfach so" eine passende Zip-Datei anlegen:

set-content $args[0] ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))

Der Name der Datei muss dem Script als erster Parameter übergeben werden: Fertig.

 


.Net Framework Quellcode wird verfügbar


Shawn hatte sich das bereits 2005 als Ziel gesetzt - und nun passiert es tatsächlich: Mit dem VS 2008 wird man direkt in den Quellcode des .Net Frameworks steppen können. (Wer mag, kann sich den Code auch einfach herunterladen und mit einem beliebigen Editor ansehen.) Scotts Ankündigung dazu hier.