Zeichenketten in C# formatieren

Dieser Artikel hier soll im Laufe der Zeit für mich (und ggf. andere) eine schnell zu findende Kurzreferenz für Zeichenkettenformatierung in C# werden.

In C/C++ gibt es printf() und verwandte Funktionen um verschiedene Datentypen formatiert in Zeichenfolgen umzuwandeln. In .NET/C# sind es string.Format(), object.ToString() und verwandte Funktionen, die verwendet werden um dies zu erreichen.

Tipps

1.) Nachkommastellen festlegen

Um die Nachkommastellen beim Umwandeln von Fließkommazahlen (decimal, double, float) zu beeinflussen, einfach das Präfix „:F“ gefolgt von der Anzahl der Nachkommastellen angeben.

Beispiel:

decimal x = 0.00m;
double y = 1.38;

// Variablen x und y auf jeweils
// 2 Nachkommastellen formatieren.
string s1 = string.Format( "{0:F2}", x );
string s2 = string.Format( "{0:F2}", y );

2.) Vorkommastellen festlegen und mit Nullen auffüllen

Um die Vorkommastellen beim Umwandeln von Ganzzahlen (z.B. int, long) zu beeinflussen und auf eine feste Anzahl stellen zu bringen, einfach das Präfix „:“ gefolgt von der gewünschten Anzahl als Nullen („0“) verwenden.

Beispiel:

int i = 19;

// Variable i auf 5 Stellen formatieren,
// fehlende Stellen mit "0" auffüllen.
string s1 = string.Format( "{0:00000}", i );

3.) Integerzahlen hexadezimal mit führenden Nullen darstellen

Um ganze Zahlen hexadezimal mit einer festen Anzahl Stellen zu formatieren einfach ein „X“ gefolgt von der gewünschten Anzahl der Nullen (z.B. „4“) schreiben.

Beispiel:

int i = 234;

// Schreibt "00EA" in s1.
string s1 = i.ToString( "X4" );

Beispiel (alternativ zum vorherigen Beispiel, gleiches Ergebnis):

int i = 234;

// Schreibt "00EA" in s1.
string s1 = string.Format( "{0:X4}", i );

Internet-Ressourcen

Folgende Artikel/Seiten sind hilfreich:

System.Drawing.Color-Elemente

Weil mir die vielen Namen der Farben des Namensraums System.Drawing.Color des .NET Framework nichts sagen, habe ich mal flott via Reflection eine ASP.NET-Seite zusammengestupfelt die die Farbnamen visualisiert.

System.Drawing.Color

Vermutlich gibt’s da schon was Fertiges, ich habe aber leider nichts gefunden. Deshalb die Seite :-). Wenn Ihr den Quelltext haben wollt; einfach runterladen.

GDI+-Fehler 7 (Gdiplus::Win32Error) beim Speichern eines Bilds das aus der Zwischenablage gelesen wurde

Beschreibung

Gerade habe ich folgendes Phänomen erlebt:

Beim Speichern eines GDI+-Bilds (Image– bzw. Bitmap-Klasse) bekam ich einen Statuscode 7 zurückgeliefert, was die Fehlermeldung „Win32Error“ bedeutet.

Also wie bei den meisten GDI+-Fehlermeldungen völlig ungenau und völlig an der wahren Ursache vorbei.

Da ich das ganze im Debugger laufen ließ und dieser bei First-Chance-Exceptions anhält, sah ich die genaue Stelle wo zum ersten Mal ein Fehler auftritt. Nämlich eine Zugriffsverletzung („Access violation“, 0x00000005) innerhalb von GDI+ an der folgenden Stelle im Aufrufstapel:

Bzw. als Textversion:

GdiPlus.dll!GpJpegEncoder::PushPixelData() + 0xa5	
GdiPlus.dll!GpMemoryBitmap::PushIntoSink() + 0x14b	
GdiPlus.dll!GpMemoryBitmap::SaveToStream() + 0xa1	
GdiPlus.dll!GpMemoryBitmap::SaveToFile() + 0x39	
GdiPlus.dll!CopyOnWriteBitmap::DoSave() + 0x206	
GdiPlus.dll!CopyOnWriteBitmap::SaveToFile() + 0x15	
GdiPlus.dll!GpBitmap::SaveToFile() + 0x1f	
GdiPlus.dll!_GdipSaveImageToFile@16() + 0x5f	
zlzdiud.dll!Gdiplus::Image::Save() Zeile 140 + 0x18

Das Bild habe ich aus der Zwischenablage geholt (Zwischenablagenformat CF_DIB) und dann über die Funktion Bitmap::FromBITMAPINFO() ein Bitmap-Objekt daraus gemacht.

Ursache

Nach einigen Tests habe ich herausgefunden, woran es lag:

Sobald ich den Speicher freigegeben hatte, der die Daten aus der Zwischenablage gespeichert hat (ein Instanz der MFC-Klasse CByteArray), schlug der Aufruf von Image::Save() mit oben genannter Fehlermeldung fehl; habe ich den Speicher erst nach dem Aufruf von Image::Save() freigegeben, verlief das Speichern erfolgreich.

Die Ursache ist also (wiedermal) wie bei den meisten GDI+-Routinen: Ich muß selbst dafür sorgen, daß ich den Speicher, aus dem ein ein Bitmap-Objekt erstellt wurde, lange genug reserviere, weil GDI+ sich das nicht selbst in interne Puffer kopiert.

Ist für ehrlich gesagt teilweise ggf. verständlich (Performance, Flexibilität), aber sehr unintuitiv (Komfort)!

Lösung

Den Speicher für ein Bitmap-Objekt, das aus einem Aufruf via Bitmap::FromBITMAPINFO() (oder entsprechend anderer Funktionen) erstellt wurde, muß während der gesamten Lebensdauer des Bitmap-Objekts gültig sein und von der benutzenden Anwendung reserviert bleiben.

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: )

Fehlermeldung „Sie versuchen eine Funktion auszuführen, die Makrounterstützung erfordert…“ bei der Microsoft Office Word 2003-Automation

Beschreibung

Beim Automatisieren von Microsoft Office Word 2003 aus einer C#-Anwendung trat folgende Fehlermeldung auf:

„Sie versuchen eine Funktion auszuführen, die Makrounterstützung erfordert. Bei der Installation dieses Programms haben Sie (oder Ihr Administrator) entschieden, die Unterstützung für Makros oder Steuerelemente nicht zu installieren“ (deutsch)

„De functie die u probeert uit te voeren, bevat macro’s of inhoud waarvoor macro-ondersteuning vereist is. Bij het installeren van deze software hebt u (of de beheerder) ervoor gekozen geen ondersteuning voor macro’s of besturingselementen te installeren“ (niederländisch)

Dies trat beim Öffnen eines Word-Dokuments via Automation auf. Das Word-Dokument selbst wurde korrekt angezeigt, ganz am Ende bekam ich dann eine System.Reflection.TargetInvocationException mit der Meldung „Exception has been thrown by the target of an invocation.“ und der InnerException mit oben genannter „Sie versuchen eine Funktion auszuführen…“-Meldung.

Wichtiger Hinweis: Bei Exceptions immer auch die InnerException-Eigenschaft anschauen (rekursiv), weil die oft die eigentlichen, aussagekräftigen Fehlermeldungen enthalten.

Ursache

Unbekannt. Vermutlich (!) fehlt eine Einstellung/Komponente die durch das Setup nachinstalliert werden muß bzw. gesetzt werden muß.

Lösung

Allgemeine Vorschläge

Es gibt bei Google verschiedene Vorschläge, die ich hier zunächst kurz zitieren möchte.

Benutzer „peppi“ schrieb:

„ist die Sicherheitsstufe für die Makros auf niedrig gesetzt (im Menü Extras zu finden)?“

„Die Speicherung von Normal.dot kann auch angefragt werden, wenn Du an den Formatvorlagen mit dem Zusatz Zur Dokumentvorlage hinzufügen etwas geändert hast.“

„Hast Du vor Erscheinen der Fehlermeldung einen (neuen) Virenscanner oder ein Update installiert? Wenn ja, deaktiviere ihn mal und prüfe, ob dann diese Fehlermeldung immer noch kommt.“

„Ist irgendeine Dokumentvorlage im Startup-Ordner von Word hinzugekommen (findest Du im Installationspfad von Office XP oder in den Anwenderdaten).“

„Evtl. ist auch die Normal.dot kaputt (kann hin und wieder vorkommen). Teste es aus, indem Du sie einfach umbenennst (normal_dot.alt). Word erstellt beim Starten eine neue.“

Außerdem könnte auch noch der Data-Eintrag in der Registry defekt sein. Lösche hierzu folgendein Eintrag in der Registry (die Du aber vorher sichern solltest):
Arbeitsplatz\HKEY_CURRENT_USER\Software\ Microsoft\Office\n.n\Word\Data“ wobei n.n für die von Dir verwendete Wordversion steht.

Benutzer „a_c_klatt“ schrieb:

Vielen Dank für die Antwort; ich habe alle Punkte ausprobiert, aber ohne Erfolg.

Nun ist das Problem aber trotzdem gelöst. Diese Woche hatte ich Software für meinen Bluetooth-USB-Adapter installiert. Nach der Deinstallation (beim Deinstallieren wurde explizit gebeten, die Normal.dot zu schließen) ist das Problem verschwunden.

Inwiefern Bluetooth Software mit Office zusammenhängt, ist mir völlig schleierhaft. Wenn jemand eine Idee hat, wäre ich sehr daran interessiert.

Benutzer „Gast“ schrieb:

Hatte das selbe Problem. Bei mir hat folgende Lösung geklappt:

Office InstallationsCD einlegen,
System/Software dann MS Office „ändern“ und
bei „gemeinsam genutzte office features“ untersten Punkt „visual basic für applikationen“ „alles vom Arbeitsplatz starten“ wählen (und dann Installation ausführen lassen…)

Dann sind die lästigen und unverständlichen Meldungen weg – bei mir zumindest.

Was bei mir/meinen Kunden geholfen hat

Ich habe folgende Punkte nachträglich mit dem Microsoft Office 2003 Setup noch installiert:

  1. „Gemeinsam genutzte Office-Features“ > „Visual Basic für Applikationen“ > „Alles vom Arbeitsplatz starten“
  2. „Gemeinsam genutzte Office-Features“ > „Digitales Zertifikat für VBA-Projekte“ > „Alles vom Arbeitsplatz starten“

Danach funktionierte die Microsoft Office Word 2003-Automation.

Fehlermeldung „This application has failed to start because the application configuration is incorrect.“ beim Starten einer Anwendung

Beschreibung

Beim Starten einer .NET 1.1-Anwendung unter Windows 2003 kam folgende Fehlermeldung in Form eines Meldungsfensters:

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

Bzw. in deutsch:

Diese Anwendung konnte nicht gestartet werden, weil die Anwendungskonfiguration nicht korrekt ist. Zur Problembehebung sollten Sie die Anwendung neu installieren.

Die Anwendung beendet sich darauf hin und läßt sich somit nicht starten.

Ursache

Wie bei Google gefunden, war die Ursache eine falsche Manifest-Datei der Anwendung.

Eine Manifest-Datei hat immer den selben Namen wie die Anwendung und zusätzlich ein „.manifest“-Postfix. Wenn also z.B. die Anwendung „MyApplication.exe“ heißt, heißt die Manifest-Datei „MyApplication.exe.manifest“.

Normalerweise wird die Manifest-Datei verwendet um eine Anwendung zu konfigurieren um die neuen visuellen Stile von Windows XP zu verwenden.

Lösung

In meinem Fall habe ich schlicht die Manifest-Datei gelöscht und danach lief die Anwendung korrekt.

Fehlermeldung „Object does not match target type“ bei der Microsoft Office Word 2003-Automation von C# via Late Binding

Beschreibung

Bei der Microsoft Office Word 2003-Automation aus einer C#-Anwendung heraus trat beim Erstellen eines neuen Dokuments folgender Fehler (TargetException) auf (jeweils in verschiedenen Sprachen):

„Object does not match target type“ (Englisch)
„Das Objekt stimmt mit dem Zieltyp nicht überein“ (Deutsch)
„Het object komt niet overeen met het doeltype“ (Niederländisch)

Der Aufruf erfolgte über „Späte Bindung“ („Late Binding“) durch den Aufruf von Type.InvokeMember auf die Microsoft Office 2003 Word-Methoden Documents.Add oder Documents.Open.

Dieser Fehler trat interessanterweise nur auf manchen Systemen auf, nicht auf allen. Selbst bei identischen und komplett neu installierten Systemen (z.B. neues IBM Notebook mit Microsoft Windows XP Professional) zeigten manche Systeme diesen Fehler, andere wiederum funktionierten korrekt.

Ursache

Die genaue Ursache ist mir unbekannt, ich vermute eine (wie auch immer geartete) fehlerhafte Installation von Microsoft Office Word 2003.

Lösung

Der bei Google beschriebene Tipp hatte in allen Fällen Erfolg: Ich habe schlicht Microsoft Office Word 2003 deinstalliert und dann wieder neu installiert.

Der Fehler trat dann nicht mehr auf, ein Neustart des Betriebssystems war nicht notwendig.

Ergänzungen

2005-10-06:
Auf einigen Systemen hatte ich jetzt das Phänomen, daß auch eine Neuinstallation von Microsoft Office Word 2003 nichts geholfen hat. Die Fehlermeldung ist nach wie vor erschienen.

Außerdem war es recht ärgerlich und lästig sowie zeitintensiv jeweils auf den ganzen Arbeitsplatz-PCs Microsoft Office Word neu zu installieren. Deswegen musste eine andere Lösung her.

Die Microsoft Office Word-Automation bei der der Fehler auftrat wurde von mir via Late Binding gemacht. Mir kam da noch die Idee, das mit den Microsoft Office PIAs (Primary Interop Assemblies) zu machen.

Die Microsoft Office PIAs sind jeweils für eine bestimmte Microsoft Office-Version. Mein vorheriger Ansatz via Late Binding ging auch bei unterschiedlichen Microsoft Office-Versionen.

Da in meinem konkreten Fall aber immer Microsoft Office 2003 vorhanden war, konnte ich einfach die Microsoft Office 2003 PIAs verwenden.

Tatsächlich funktioniert die Microsoft Office-Automation mit den Microsoft Office 2003 PIAs fehlerfrei! Ich muß bei Gelegenheit ggf. mal mit Reflector nachschauen, was die bei der Initialisierung und Ähnlichem anders machen, daß das funktioniert.