Illegale Zeichen aus einem Dateinamen oder Pfad entfernen

 Entwicklung, Hilferuf und Lösung  Kommentare deaktiviert für Illegale Zeichen aus einem Dateinamen oder Pfad entfernen
Mrz 172011
 

Ein Problem das sich bei mir immer mal wieder auftut ist das erstellen einer Datei anhand irgend welcher Daten aus irgend welchen Quellen. Das kann bei einer Applikation ein Feld aus der Datenbank sein. Der Titel eines Buches mit dem man kurz eine Temporäre Datei erstellen will um sie als Attachement einem EMail anzuhängen. Aber um die Datei speichern zu können darf sie keine Sonderzeichen drin haben.

Wenn jetzt das Buch den Titel Mein <”Sonderzeichen”> Buch  hat wird das speichern schon schief gehen. Die “ und <> sind in Dateinamen und Pfadnamen nicht erlaubt.

Sofort baut man sich eine Methode die alle Sonderzeichen entfernt. Aber was sind den nun Sonderzeichen? Jetzt fängt die Suche im Internet an, in der Hoffnung eine Liste mit den ungültigen Zeichen zu finden. Seit dem .NET 2.0 Framework kann man dieses bemühen.

Path.GetInvalidFileNameChars() und Path.GetInvalidPathChars(). Schon muss man sich die Zeichen nicht mehr zusammensuchen.

Ich habe mir kurz mal eine Konsolen-Anwendung zur Demo gemacht. Man sieht hier zwei Möglichkeiten wie man die Sonderzeichen entfernen kann. Die erste Methode, die habe ich im Main auskommentiert (Zeile 19), macht es mit einer klassischen Methode die ab der Zeile 32 implementiert. Die Zweite, die aktive (Zeile 21), macht es mit einer Erweiterungsmethode die ab der Zeile 48 implementiert ist.

#region using

using System;
using System.IO;

#endregion

namespace IllegaleZeichen
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string folder = Path.GetTempPath();
            string fileName = "Mein <\"Sonderzeichen\"> Buch" + ".txt";

            Console.WriteLine(fileName);

            //string file = Path.Combine(folder, RemoveIlegaleCharackter(fileName));

            string file = Path.Combine(folder, fileName.RemoveIlegaleCharackter());

            using(StreamWriter sw = new StreamWriter(file))
            {
                sw.Write("Tut");
            }

            Console.WriteLine(file);
            Console.Read();
        }

        private static string RemoveIlegaleCharackter(string fileName)
        {
            string illegal = fileName;
            string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

            foreach(char c in invalid)
            {
                illegal = illegal.Replace(c.ToString(), "");
            }

            return illegal;
        }
    }

    public static class ExtMeth
    {
        public static string RemoveIlegaleCharackter(this string fileName)
        {
            string illegal = fileName;
            string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

            foreach(char c in invalid)
            {
                illegal = illegal.Replace(c.ToString(), "");
            }

            return illegal;
        }
    }
}

Die Datei wird dann mit dem Namen “Mein Sonderzeichen Buch.txt” im Temp-Verzeichnis erstellt.

.NET Object to VBScript to .NET

 Entwicklung  Kommentare deaktiviert für .NET Object to VBScript to .NET
Mai 142010
 
Ausganslage

Zur Zeit arbeite ich an einem grossen Projekt wo wir eine VB6 Anwendung nach .NET (C#) migrieren. Im grossen und ganzen wird einfach die Logik migriert, ohne gross neue Funktionen hinzuzufügen.

In der alten Anwendung wurde zu Berechnungszwecken einiges an Logik in VBScripte ausgelagert. Das machte man, um die Logik anpassen zu können ohne das neue DLLs erstellt werden müssten. Das muss ich jetzt in C# nachbauen. Die VBScripte sollen noch nicht migriert werden. Schlicht vom Aufwand her.

Ich muss ein .NET Objekt an ein VBScript übergeben, das macht die Berechnungen und gibt danach das Objekt wieder an C# zurück.

Zuerst dachte ich, man könnte einfach WScript.exe mit ein paar Parametern aufrufen. Allerdings kann ich so natürlich keine Objekte übergeben. Nach einigem suchen wurde ich dann fündig wie dich ein .NET Objekt an ein VBScript übergeben kann und auch wieder zurück bekomme. Das Stichwort lautet: Microsoft Script Control 1.0

Was muss nun alles gemacht werden um das Problemchen zu lösen.

Erstellen eines COM Visible .NET Objektes

Um ein .NET Objekt in einer COM Umgebung zu bearbeiten muss das Objekt für COM Sichtbar gemacht werden. Das kann in der Projekteinstellung der Klassen gemacht werden.

COM Visible einstellen

COM Visible registrieren

Mit diesen Einstellungen wird das Objekt automatisch von Visual Studio als COM Registriert. Auf einem produktiven System müsste das natürlich das Setup übernehmen oder ein Batch. Mit regasm MyAssembly.dll wird die DLL auf der Commandline registriert oder aus einem Batch raus.

Die Klasse selber kann sehr einfach aussehen.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComVisibleClass
{
	public class Person
	{
		private string m_Name;
		private string m_Vorname;
		private int m_Alter;
		public string Name
		{
			get{return m_Name;}
			set{m_Name = value;}
		}
		public string Vorname
		{
			get{return m_Vorname;}
			set{m_Vorname = value;}
		}
		public int Alter
		{
			get{return m_Alter;}
			set{m_Alter = value;}
		}
	}
}
Aufrufen des VBScriptes

Für den Test habe ich ein ganz einfaches VBScript erstellt. Es wird ein .NET Objekt übergeben und über eine MsgBox gibt es ein paar Meldungen zum Objekt. Somit ist klar das die Wert auch wirklich im VBScript manipuliert werden und auch wieder zurück ins .NET kommen.

Aber um ein VBScript auszuführen muss noch eine DLL eingebunden werden.

Microsoft Scripting Control 1.0

Unter Verweis hinzufügen wechselt man in das COM Register und sucht dort das Microsoft Scripting Control 1.0. Danach kann man auf das Control im Code zugreifen. Einfach noch das using hinzufügen wie in Zeile 6 im folgenden Code zu sehen.

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using ComVisibleClass;
using MSScriptControl;

namespace TestApp
{
	class Program
	{
		static void Main(string[] args)
		{
			StreamReader streamReader = new StreamReader("Script.vbs", Encoding.Default);
			string script = streamReader.ReadToEnd();
			streamReader.Dispose();

			RunScript(script);

			Console.ReadLine();
		}

		private static void RunScript(string scriptCode)
		{
			try
			{
				ScriptControlClass script = new ScriptControlClass();
				script.Language = "VBScript";
				script.Reset();
				script.AllowUI = true;
				script.UseSafeSubset = false;

				script.AddCode(scriptCode);

				Person person = new Person() { Name = "Schumacher", Vorname = "Roland", Alter = 35 };
				Console.WriteLine(person.Alter);

				script.AddObject("Person", person, true);

				Object[] objects = new object[] { };

				script.Run("CalculateStatus", ref objects);

				Console.WriteLine(person.Alter);
			}
			catch (COMException ex)
			{
				Console.WriteLine(ex.ToString());
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.ToString());
			}
		}
	}
}

In den Zeilen 14 bis 16 wird ein VBScript geladen das im selben Verzeichnis liegt wie die Testanwendung. Das Script wird noch erläutert.

In Zeile 27 bis 42 findet die Ausführung des VBScriptes statt. Zuerst wird eine neue Instanz von ScriptControlClass erstellt und ein paar Parameter gesetzt. Mit script.AddCode übergibt man dem Control den Code den es ausführen soll. Achtung. Wenn das VBScript keine Sub oder Function enthält wird das Script schon in der Zeile 38 ausgeführt. Aber sobald das VBScript eine Function oder Sub enthält passiert in dieser Zeile noch nichts.

In Zeile 35 erstelle ich das Objekt das ich an das VBScript übergeben will. Man beachte das Alter. Das ist beim initialisieren auf 35 gesetzt. Zur Kontrolle gebe ich das in Zeile 36 aus.

In Zeile 38 übergebe ich das Objekt an das VBScript. Hier wird es auch wieder interessant. Im ersten Parameter geben ich eine Bezeichnung für das Objekt an. Genau mit dieser Bezeichnung greift man dann im VBScript auf die Person zu. In Zeile 42 wird schlussendlich die Funktion CalculateStatus() aufgerufen.

In Zeile 44 gebe ich nochmals das Alter aus. Und siehe da, es ist nicht mehr 35 sondern 99. Das alter 99 wurde im VBScript gesetzt. Der Informationsaustausch fand also statt. Ich kann ein .NET Objekt in VBScript manipulieren und die Ergebnisse stehen mir in .NET zur Verfügung.

Das VBScript

Das VBScript macht nicht viel spezielles.

Public Sub CalculateStatus()

    Dim oPerson
    set oPerson = Person

    if err.number <> 0 then
        MsgBox "UPS : Error " & Err.number & " Creating Customer: " & Err.description
    else
        MsgBox "Customer Name: " & oPerson.Name & " -- Vorname: " & oPerson.Vorname & " -- Alter: " & oPerson.Alter
        
        oPerson.Alter = 99
        
        MsgBox "Customer Name: " & oPerson.Name & " -- Vorname: " & oPerson.Vorname & " -- Alter: " & oPerson.Alter
    end if
End Sub

In Zeile 1 ist die Sub CalculateStatus definiert. In Zeile 3 definiere ich das Objekt oPerson und setze es in der Zeile 4. Und hier sieht man wieder die Person. Das ist genau die Person die man mit script.AddObject("Person", person, true);  übergeben hat.

In Zeile 9 wird die original Person kurz Visualisiert. Und Zeile 11 wird das Alter auf 99 gesetzt und in Zeile 13 wird die Person nochmals Visualisiert. Danach ist das VBScript fertig.

Im .NET ist das Alter der Person nun 99.

Result

Fazit

Was mir am Anfang als unlösbar mit .NET erschien ist im nachhinein sehr einfach zu lösen. Dank dem Internet und Google findet man irgend wann schon eine Lösung.

Jetzt gilt es nur noch ein Problem zu lösen. Die VBScripte müssen im Debugger gestartet werden können. Dazu gäbe es ja das Schlüsselwort stop im VB. Allerdings greift das nicht. Hier muss ich noch nach einer Lösung suchen was aber auch machbar sein wird.

Was noch cool wäre

So etwas sollte es auch mit C# als Script geben.

kick it on dotnet-kicks.de

MSDN – Immer mal wieder Unklarheiten

 Entwicklung  Kommentare deaktiviert für MSDN – Immer mal wieder Unklarheiten
Aug 302008
 

Solche Sachen irritieren einem doch gewaltig. Zum Thema SetValidUntilExpires.

image

Ich verstehe das so, dass die Funktion mit dem .NET Framework 3.5 eingeführt wurde.

Aber wo soll das damit überein stimmen?

image

Angeblich gibt es die Funktion schon immer. Was nun? 🙂

Oder muss ich das anders Verstehen? Die Funktion wurde zwar erst mit dem 3.5’er eingeführt, läuft aber auch schon im 1.0’er Framework?

.NET BlogBook

 Allerlei, Entwicklung  Kommentare deaktiviert für .NET BlogBook
Jan 042007
 

Die zwei Bloger Kai Gloth und Norbert Eder haben ein interessantes Projekt gestartet.

Das .NETBlogBook.

Im Grossen und Ganzen geht es darum, dass sie ihre Blogpostings zum Thema .NET
zusammentragen und in einem PDF veröffentlichen. Dient als sehr gutes
Nachschlagewerk und hat bei mir auf dem Desktop einen Platz gefunden.

Connection Strings

 Entwicklung  Kommentare deaktiviert für Connection Strings
Jun 222006
 

Für alle die es noch nicht kennen.
http://www.connectionstrings.com/

Diese Webseite hat mir soeben wieder mal geholfen.
Hier werden die ConnectStrings zu diversen DB’s gelistet.

Hier ein Beispiel für den SQL Server (.NET):
[…]

  •  Standard Security:
    „Data Source=Aron1;Initial Catalog=pubs;User Id=sa;Password=asdasd;“
       - or -
    „Server=Aron1;Database=pubs;User ID=sa;Password=asdasd;Trusted_Connection=False“
       (both connection strings produces the same result)
  •  Connect via an IP address:
    „Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog=pubs;User ID=sa;Password=asdasd;“

    (DBMSSOCN=TCP/IP instead of Named Pipes, at the end of the Data Source is the port to use (1433 is the default))

[…]

.NET – Datenbindung optimieren

 Entwicklung  Kommentare deaktiviert für .NET – Datenbindung optimieren
Apr 272006
 

Ich bin vor kurzem über einen MSDN Bericht gestolpert
mit dem Thema „Windows-Forms-Anwendungen„. Es geht
darum, wie man eine Windows Form Anwendung optimiert
was das Startverhalten angeht.

Dabei bin ich über folgenden Code gestolpert.

Optimal:
comboBox1.ValueMember = „Name“;
comboBox1.DisplayMember = „Name“;
comboBox1.DataSource = test;

nicht Optimal:
comboBox1.DataSource = test;
comboBox1.ValueMember = „Name“;
comboBox1.DisplayMember = „Name“;

Die DataSource sollte erst am Schluss gesetzt werden.
Andernfalls werden auf das Ereignis der ValueMember-Änderung
die Daten nochmals gefüllt.

MSDN – Partner Resource DVD

 Entwicklung  Kommentare deaktiviert für MSDN – Partner Resource DVD
Mrz 312006
 

Vielleicht interessiert es ja jemanden.

[…] Order Your Free Partner Product DVD
Order this free DVD and receive over 50 tools, components and languages from Visual Studio Industry Partners.
These full, trial and and evaluation products can help save you time and money building applications
for Microsoft Windows, mobile devices, the Web, and Web services.
[…]