Ein Kunde ruft bei uns an und berichtet von einem Nutzer, bei dem nach der Deinstallation einer Software plötzlich Systemdateien fehlten. Er kündigt am nächsten Tag zu diesem Thema eine Telefonkonferenz an. Ein kurzer Blick in den Code offenbart furchtbares. Wenn jemand die Software nicht in den vorgeschlagenen Ortner installiert, sondern beispielsweise in den Systemordner, werden dort mit der Deinstallation alle Dateien gelöscht.

Es ist zwar noch nicht evaluiert, aber das dürfte das Problem sein. Eine mögliche Lösung: Mit dem ersten Start schreiben wir eine Datei mit den vorhandenen Dateien und Ordnern (also quasi dir /b > installed.txt). bei der Deinstallation lesen wir diese Datei aus und löschen nur die darin gelisteten Dateien einschließlich der Datei selbst. Der Ordner wird nur gelöscht, wenn er leer ist.

So geht es auf jeden Fall nicht:

private void Permission_AfterUninstall(object sender, InstallEventArgs e)
{
	string Path_LabelFiles = Path.Combine(Application.StartupPath, @"Labels");
	if (Directory.Exists(Path_LabelFiles))
	{
		try
		{
			Directory.Delete(Path_LabelFiles, true);
		}
		catch (Exception ex)
		{
			//nope
		}
	}

	try
	{
		Directory.Delete(Application.StartupPath, true);
	}
	catch
	{
	}

}

Heute während eines Versuchs beim Kunden per Communicator eine Neuerung in unserer Software vorzuführen. Entdeckt. Wer findet den Fehler?

if (mo.PanelCountConnected >= mo.PanelCountConnected)
{
  MessageBox.MsgBox.show("MSG_NOMORE_PANELS");
  return;
}

Lösung nach dem Klick.

fehlerNP

Wenn man mit dem Microsoft .net Framework 2.0 in C# mit der folgenden Zeile eine Liste der Named Pipes des Systems ermitteln will, kann es zu einer Fehlermeldung kommen:

string[] strPipes = System.IO.Directory.GetFiles(@"\\.\pipe\");

Ursache dafür ist, dass es eine Named Pipe mit einem Namen gibt, der kein gültiger Dateiname ist. Mit dem folgenden Code (C#) gelingt das Auslesen aller Named Pipes:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct WIN32_FIND_DATA
{
	public uint dwFileAttributes;
	public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
	public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
	public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
	public uint nFileSizeHigh;
	public uint nFileSizeLow;
	public uint dwReserved0;
	public uint dwReserved1;
	[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
	public string cFileName;
	[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
	public string cAlternateFileName;
}

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);


[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA
	 lpFindFileData);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FindClose(IntPtr hFindFile);

private List<string> getNamedPipes()
{
	List<string> liNamedPipes = new List<string>();
	WIN32_FIND_DATA lpFindFileData;

	var ptr = FindFirstFile(@"\\.\pipe\*", out lpFindFileData);
	liNamedPipes.Add(lpFindFileData.cFileName);
	while (FindNextFile(ptr, out lpFindFileData))
	{
		liNamedPipes.Add(lpFindFileData.cFileName.ToLower());
	}
	FindClose(ptr);

	liNamedPipes.Sort();

	return liNamedPipes;
}

Übrigens kann man mit dem Tool PipeList der Microsoft Sysinternals  per Kommandozeile eine Liste aller Named Pipes ausgeben lassen.

Vor einiger Zeit habe ich an der Arbeit ein Tool geschrieben, was zur elektronischen Erfassung von Telefonnotizen dient. Heute sind wir nur zu zweit im Büro und ich wollte eine Notiz erstellen. Leider gab es eine Exception und es funktionierte nichts. Also hab ich die Entwicklungsumgebung geöffnet und versucht zu debuggen. Es gab einen diffusen Fehler (xamlparseexception) beim Öffnen einer SQLConnection (SQL-Server 2008) um die Telefonnummer zu einem Kontakt aus der Datenbank auszulesen. Ein Versuch die Exception abzufangen schlägt fehl. Trage ich eine andere Datenbank ein funktioniert es.
Die Lösung:

In eine Datei mit Kalibrierwerten wird ein Zeitstempel geschrieben. Beim Starten der SW wird der Zeitstempel ausgelesen. Ist er älter wie 48 Stunden soll neu kalibriert werden. Auf dem Testsystem, einem deutschen Windows 7 tat es der folgende Code:

DateTime.ParseExact(strDatCalibrate,"dd.MM.yyyy_hh:mm", CultureInfo.CurrentCulture);


Bei anderen Sprachen/Regionen bzw. anders eingestelltem Datumsformat krachte es, da kein gültiger Datumsstring vorliegt. Die Lösung bringen hier die in der System.Globalization.CultureInfo definierten Patterns:



DateTime.TryParseExact(strDatCalibrate,
    string.Format("{0:s}_{1:s}",
        CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern,
        CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern),     
    CultureInfo.CurrentCulture,
    DateTimeStyles.None,
    out dt));