AllocSysString

Hartnäckigkeit zahlt sich oft aus: Heute habe ich ein Speicherleck (englisch „Memory leak“) in Zeta Producer korrigiert, das seit Version 5 drin war:

Beim Aufruf der Microsoft Scripting Engine habe ich beim Aufruf der Funktion IActiveScriptParse::ParseScriptText irrtümlicherweise CStringT::AllocSysString aufgerufen und den so angeforderten Speicher selbst nicht mehr freigegeben. Dies hätte ich jedoch machen müssen, was ich in der korrigierten Version nun mache.

Das hätte ich aber machen sollen! „RTFM“ hat Mario mir da gleich geantwortet als ich es ihm erzählt habe.

Hiermit also nochmals der ultimative Artikel wann wer für die Freigabe von Zeichenfolgen die mittels AllocSysString reserviert wurden verantwortlich ist: „Allocating and Releasing Memory for a BSTR (Visual C++ Concepts)„.

Fehlermeldung CS0013 beim Kompilieren einer ASP.NET 1.1-Anwendung mit Microsoft Visual Studio .NET 2003

Beschreibung

Beim Kompilieren einer ASP.NET 1.1-Anwendung mit Microsoft Visual Studio .NET 2003 auf einem Windows 2000 Server via Terminal Services („Remote Desktop“, RDP) trat folgende Fehlermeldung auf:

CS0013: Unerwarteter Fehler beim Schreiben der Metadaten in die Datei ‚C:\…\obj\Release\MyDll.dll‘ — ‚Unbekannter Fehler‘.

In Englisch sollte das in etwa so lauten:

CS0013: Unexpected error writing metadata to file ‚C:\…\obj\Release\MyDll.dll‘ — ‚Unknown error‘.

Die Fehlermeldung trat bei einem Projekt auf, das bereits über ein Jahr erfolgreich kompilierte. Nach einer kleinen Codeänderung kam auf einmal diese Fehlermeldung.

Ursache

Die erwähnte „kleine Codeänderung“ war, daß ich eine Klasse erstellt hatte, die von einer anderen Klasse abgeleitet hat, welche in einer dritten Klasse als Unterklasse enthalten war.

Also so was wie das hier:

public class A
{
    ...
    
    public class B
    {
        ....
    }

    ...
}

...

public class C : A.B
{
    ...
}

Scheinbar „verhaspelt“ sich der C#-Compiler da irgendwo. In anderen Fällen hat das selbe Prinzip auch schon oft funktioniert. Nur in diesem Fall hier aus irgendeinem Grund nicht.

Lösung

Nachdem ich die Klasse B „global“ gemacht hatte, kompilierte alles wieder:

public class A
{
    ... 
}

...

public class B
{
    ....
}

...

public class C : B
{
    ...
}

Windows-Explorer zum Brechen langsam bei entferntem Netzwerkkabel

Beschreibung

Auf einem Laptop (oder heißt das Notebook?) hatte ich seit kurzem folgendes Phänomen:

Sobald das Netzwerkkabel entfernt war (und WLAN deaktiviert), war der Windows-Explorer (auch die Shell selbst) mangels Geschwindigkeit praktisch unbenutzbar.

Allein das Startmenü-Öffnen war nur sehr langsam (im Minutenbereich) möglich. Ebenso dauerte es sehr lange, im Windows-Explorer einen Ordner anzuzeigen und dann zu einem anderen Ordner zu wechseln.

Ursache

Mittels CommView habe ich herausgefunden, daß ständig Anfragen ins (nicht vorhandene) Netzwerk gesendet wurden.

Lösung

So sahen die Netzwerkverbindungen des Laptops aus:

Netzwerkverbindungen

(Die betreffende Netzwerkkarte habe ich violett markiert).

Wenn nun das „Erweiterte TCP/IP-Einstellungen“-Dialogfenster dieser LAN-Verbindung angezeigt wurden, war die Option „NetBIOS-Einstellung“ auf den Wert „Standard“ gesetzt.

Sobald ich die Option auf den Wert „NetBIOS über TCP/IP deaktivieren“ aktiviert hatte, lief der Explorer wieder:

Was genau diese Option bewirkt hat sich mir trotz Recherche nicht so ganz erschlossen. Jedoch arbeiten nun alle Windows-Komponenten sowohl mit als auch ohne Netzwerkkabel zu meiner vollen Zufriedenheit.

Mehrfache Datensätze in einer Tabelle mit SQL löschen

Tisch mit Buch, darin Tipps, wie mehrfache Datensätze aus einer SQL-Tabelle zu löschen sind

Gestern habe ich versehentlich in eine Tabelle im Microsoft SQL Server doppelte Datensätze importiert.

Habe den Mario gefragt wie ich die wieder rausbekomme, seine übliche Antwort war natürlich „…geht mit Standard-SQL nicht…„.

Ha! Von wegen! Der Rainer hat genau 30 Sekunden gebraucht um den Artikel „Mehrfache Datensätze anzeigen und mit Ausnahme einer Zeile löschen“ zu finden.

Sieschd, Mario, es gooht doch! 🙂

Im verlinkten Artikel ist für mich die fast ganz unten stehende Abfrage meistens am passenden:

DELETE FROM tbl_Personen

WHERE [Personen-Id] NOT IN
(
    SELECT MIN(X.[Personen-Id])
    FROM tbl_Personen AS X
    GROUP BY X.Nachname, X.Vorname, X.Geburtstag
)

Fehlermeldung „Fehler bei sqlmaint.exe“ bei einem geplanten Auftrag in SQL Server

Fehlerbeschreibung

Es kommt eine Meldung „Fehler bei sqlmaint.exe. [SQLSTATE 42000] (Fehler 22029). Fehler bei Schritt“ und der Auftrag ist mit einem roten X als fehlgeschlagen markiert.

Ursache

Der Aufruf der Anwendung „sqlmaint.exe“ schlug fehl.

Lösung

Zunächst den Auftrag anschauen und das T-SQL-Skripts des Auftrags analysieren. Dies kann z.B. wie folgt aussehen:

EXECUTE
    master.dbo.xp_sqlmaint
    N"-PlanID 99F45116-2803-46BB-A95D-058C5D8E72EC
    -WriteHistory
    -VrfyBackup
    -BkUpOnlyIfClean
    -CkDBRepair
    -BkUpMedia DISK
    -BkUpDB "c:mybackfolder"
    -DelBkUps 4DAYS
    -BkExt "BAK""

Der Aufruf „xp_sqlmaint“ ist eine Erweiterte Gespeicherte Prozedur die schlicht ein Wrapper für die Anwendung „sqlmaint.exe“ ist.

Wenn nun „sqlmaint.exe“ direkt von der Befehlszeile aus aufgerufen wird mit den Parametern die auch an „xp_sqlmaint“ übergeben wird, liefert „sqlmaint.exe“ eine sehr detaillierte Fehlermeldung warum der Aufruf tatsächlich fehlschlug.

Mit dieser Fehlermeldung dann die tatsächliche Ursache beseitigen.

Noch einfacher ist es, die Ausgabe von „sqlmaint.exe“ wenn es durch „xp_sqlmaint“ aufgerufen wird sich direkt ausgeben zu lassen. Dazu:

  1. Eigenschaften des T-SQL-Skripts des Auftrags anzeigen.
  2. Registerkarte „Erweitert“
  3. Im Feld Ausgabedatei einen Datei angeben, möglichst als UNC-Pfad, z. B. „\\myserver\myfolder\sqlmaint-output.txt“. Diese Ausgabe dann analysieren.

Tipps

  • „sqlmaint.exe“ ist normalerweise im Ordner „C:\Programme\Microsoft SQL Server\MSSQL\Binn“ gespeichert. (bzw. „C:\Programme\Microsoft SQL Server\MSSQL.1\MSSQL\Binn“ für SQL Server 2005)
  • Ein Fehler war „Error 21268: [SQL-DMO]Row or column specified is outside the range of the specified query result set„. Ein Autor schlug vor, die Begrenzung der Zeilenanzahl für Protokolle aufzuheben, ein anderer „dbcc checkdb“ auf der Datenbank auszuführen (im SQL Query Analyzer). Es wurden dann auch tatsächlich Fehler in der „msdb“ Datenbank gefunden. Um diese zu beseitigen:
    1. Den SQL-Server Dienst anhalten
    2. Den SQL-Server manuell starten „C:\Programme\Microsoft SQL Server\MSSQL\Binn>sqlservr.exe -m“
    3. „ISQL.exe“ starten
      „C:\Programme\Microsoft SQL Server\MSSQL\Binn>isql -U sa“ und den Reparieren-Befehl ausführen, z.B.:
      1> alter database msdb set SINGLE_USER
      2> DBCC CHECKDB („msdb“, REPAIR_ALLOW_DATA_LOSS)
      3> alter database msdb set MULTI_USER
      4> GO

    Für den SQL Server 2005 lauten die entsprechenden Befehle/Ordner:

    1. Den SQL-Server Dienst anhalten
    2. Den SQL-Server manuell starten „C:\Programme\Microsoft SQL Server\MSSQL.1\MSSQL\Binn>sqlservr.exe -m
    3. „OSQL.exe“ starten
      C:\Programme\Microsoft SQL Server\90\Tools\Binn>osql -U sa“ und den Reparieren-Befehl ausführen, z.B.:
      1> alter database msdb set SINGLE_USER
      2> DBCC CHECKDB („msdb“, REPAIR_ALLOW_DATA_LOSS)
      3> alter database msdb set MULTI_USER
      4> GO

(Stichwörter für Suchmaschinen: )

Beispielprojekt für ADO.NET 2.0 mit Windows Forms 2.0 unter Visual Studio.NET 2005

Um mal in die aller einfachsten Grundlagen von Visual Studio.NET 2005 (Beta 2 mit June CTP) im Zusammenspiel mit ADO.NET 2.0 und Windows Forms 2.0 reinzukommen, habe ich in 2 Stunden eine kleine Anwendung zusammengeklopft (Download siehe unten).

Folgende Stichworte/Rahmenbedingungen:

  • Möglichst ganz wenig Code selber schreiben, möglichst alles die diversen Assistenten machen lassen
  • Typed DataSets verwenden
  • DataBound Controls verwenden
  • Windows Forms 2.0 verwenden
  • DataGrid verwenden
  • Microsoft Access 2003 Datenbank verwenden

Folgendes kam dabei raus.

Hauptfenster

Das Hauptfenster stellt schlicht eine Liste der einzigen Tabelle dar und hat die üblichen Schaltflächen für „Neu“, „Bearbeiten“ und „Löschen“.

Bearbeitungsfenster

Das Bearbeitungsfenster wird angezeigt um einen neuen Datensatz zur Tabelle hinzuzufügen oder einen bestehenden Datensatz der Tabelle zu bearbeiten.

Download

Hier könnt Ihr die Anwendung samt Quelltexten herunterladen (150 kB)

Zusammenfassung

Alles recht einfach zu benutzen. Für größere Projekte habe ich bisher immer selbstgeschriebene Klassen verwendet, aber im 2005er Visual Studio scheinen die Microsoft-Jungs nochmals einiges verbessert zu haben. Schaut vielversprechend aus.

Von den gesamten 2 Stunden habe ich übrigens 90% der Zeit dafür benötigt, eine einzige Zeile Code zu recherchieren. Und zwar diese hier:

BindingContext[shipsBindingSource].EndCurrentEdit();

Vielleicht hilft es ja mal jemandem Zeit zu sparen, wenn ich das nun hiermit dokumentiert habe.

Test Informatik

In meiner Eigenschaft als Dozent (1 mal pro Woche) an der Fachhochschule unterrichte ich „Informatik 1“. Das sind C-Grundlagen. Meine Studenten müssen pro Semester einen Test/Klausur schreiben.

Eine der Aufgaben lautete:

Es soll eine Tabeller der Teiler der ganzen Zahlen von 17 bis 63 in exakt folgender Form gedruckt werden:

17 1, 17
18 1, 2, 3, 6, 9,18
: :
: :

Schreiben Sie das Programm in C.

Die offensichtlichste Lösung wären 2 verschachtelte Schleifen, eine äußere Schleife die von 17 bis 63 zählt und eine innere Schleife die jeweils hochzählt bis zum aktuellen Zählerwert der äußeren Schleife. Dann noch ein bisschen Modulo prüfen und ein bisschen Bildschirmausgabe und gut ist’s.

Ein, natürlich nicht namentlich genannter, Student hat das nun aber ganz anders gelöst:

Da fällt mir nur WTF dazu ein.