Feed
Contact
XING
LinkedIn
Twitter
ICQ
meebo.com

BlogEngine.NET - Fehler beim ein- und ausschalten von Erweiterungen

by Roland Schumacher alias GENiALi 16. August 2010 -- 212 Wörter  -- 501 mal gelesen
Dieser Beitrag ist mir was wert:  

Wenn bei BlogEngine.NET eine Erweiterung aus- oder eingeschaltet wird kommt eine Meldung die einem mitteilt, dass auf die Web.config nicht geändert werden kann. Das kommt daher, dass der ExtensionManager versucht, bei einer Änderung des Status einer Erweiterung, das Blog neu zu starten. Versucht wird das in dem die Web.config geringfügig verändert wird. Bei einer Änderung der Web.config wird das Web automatisch neu gestartet.

Um den Fehler zu verhindern müsste man dem Account, unter dem das Web läuft, schreibrechte auf die Web.config geben. Wenn man einen eigenen IIS hat ist das kein Problem. Bei einem Shared Hosting geht das aber nicht immer. Ich kann z.B. auf den Dateien im root-Verzeichnis keine Rechte ändern. Die Web.config ist also immer schreibgeschützt für die Webanwendung. Dann kommt immer der Fehler.

Man kann das Web aber noch anders neu starten. Mit HttpRuntime.UnloadAppDomain(); erreicht man das selbe ohne die Fehlermeldung und gefühlt schneller. Angepasst werden muss folgendes.

In der ExtensionManager.cs:

public static void ChangeStatus(string extension, bool enabled)
{
    foreach (ManagedExtension x in _extensions)
    {
        if (x.Name == extension)
        {
            x.Enabled = enabled;
            BlogEngine.Core.DataStore.ExtensionSettings xs = new BlogEngine.Core.DataStore.ExtensionSettings(x.Name);
            xs.SaveSettings(x);
            SaveToCache();

            //string ConfigPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Web.Config";
            //File.SetLastWriteTimeUtc(ConfigPath, DateTime.UtcNow);

            HttpRuntime.UnloadAppDomain();
            break;
        }
    }
}
Die Zeilen 12 und 13 werden auskommentiert. Die Zeile 15 ist neu und bewirkt ein neustarten der Webanwendung.

Artikel empfehlen auf .NET-Kicks Deutschland

Tags: ,

Blog | Entwicklung

.NET Object to VBScript to .NET

by Roland Schumacher alias GENiALi 14. May 2010 -- 899 Wörter  -- 371 mal gelesen
Dieser Beitrag ist mir was wert:  
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

Tags: , , , ,

Entwicklung

C# Merkzettel

by Roland Schumacher alias GENiALi 16. April 2010 -- 672 Wörter  -- 536 mal gelesen
Dieser Beitrag ist mir was wert:  

Sachen die immer mal wieder nützlich sein können.

1. Kalenderwoche eines Datum ermitteln.
private int KW(DateTime datum)
{
    CultureInfo cultureInfo = CultureInfo.CurrentCulture;
    int kw = cultureInfo.Calendar.GetWeekOfYear(datum, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
    return kw;
}
2. Ein einfaches Event erstellen.
public event EventHandler<EventArgs> DeletePersonEvent;
public void DeletePerson()
{
	if(DeletePersonEvent != null)
	{
		DeletePersonEvent(this, new EventArgs());
	}
}
3. WPF Zeilenumbruch in einer Caption oder Text Tag.
<TextBox x:Name="myTextBox" Text="Linie 1 &#x0a; Linie 2" />

Zeilenumbruch mit: &#x0a;

4. DataTable über WCF

Das geht nicht. Man darf es zuerst noch in ein DataSet verpacken und dann über WCF übertragen.

public DataSet GetPersonenDataSet()
{
    DataSet ds = new DataSet();
    ds.Tables.Add(m_PersonDao.Read());

    return ds;
}

m_PersonDao.Read() gibt ein DataTable zurück.

5. WPF Datenbindung

Auch immer mal wieder etwas was ich suche, obwohl es eigentlich sehr einfach ist.

Wahrscheinlich gibt es etwa 1000 Möglichkeiten wie man es lösen kann. Ich mache es zur Zeit so.

Code-Behind vom XAML:

public RaumView(RaumModel model)
{
    InitializeComponent();

    this.m_Model = model;

    this.DataContext = m_Model;
}

In Zeile 7 binde ich eine Klasse, die meine Objekte enthält, an den DataContext.

Danach kann ich auf den Controls relativ einfach die Daten binden.

Text="{Binding Raum.Standort.Bezeichnung, Mode=OneWay}"

In diesem Text wird eigentlich m_Model.Raum.Standort.Bezeichnung angezeigt. Das Feld wird aber nicht zurück in den DataContext synchronisiert (Mode=OneWay). Wenn das der fall sein soll, dann macht man das so.

Text="{Binding Raum.Bezeichnung, Mode=TwoWay}"

Die Bezeichnung des Raumes wird jetzt in den DataContext zurück synchronisiert (Mode=”TwoWay”).

So in etwa reicht es für mich zur Zeit aus.

6. GUID im Debugger ändern

Hat man mal das Bedürfnis eine Variable zur Laufzeit zu ändern, die vom Typ GUID ist, kann man nicht einfach die neue GUID im Debugger reinschreiben.

So sieht es zur Laufzeit aus.

Original GUID

Einfach neue GUID zwischen die {} kopieren resultiert in einem Fehler.

Fehler

Lösung:

Richtig gemacht

new Guid(“<GUID>”)

So sieht es danach aus.

neue GUID

7. Irgend eine Datei öffnen

Ich will eine Datei öffnen ohne das ich das Programm kennen muss was für die Datei nötig ist. Das geht natürlich nur wenn ein Haendler für die Datei auf dem System registriert ist. Und wenn, dann ist es einfach.

Process myProcess = new Process();
myProcess.StartInfo.FileName = "<PFAD_ZUR_DATEI>";
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.RedirectStandardOutput = false;
myProcess.Start();

Der FileName muss ein kompletter Pfad zu seiner Datei sein. z.B.: “c:\temp\MeinProgi\MeineDatei.txt

8. Eine E-Mail mit dem Standard E-Mail Programm öffnen.

Auch das kann mit der Process Klasse gemacht werden.

Process myProcess = new Process();
myProcess.StartInfo.FileName = string.Format("mailto:{0}", mailto);
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.RedirectStandardOutput = false;
myProcess.Start();

Und schon öffnet sich eine E-Mail mit seinem Standard E-Mail Programm. Aber das geht nur wenn auf dem System ein mailto Haendler registriert ist. Aber sobald ein E-Mail Klient installiert ist ist das der Fall. Wenn kein mailto Haendler vorhanden ist kann eigenartiges Passieren. Bei uns auf einem Windows XP startete danach ein paar 100 Mal der Internet Explorer. Wie so er so oft startete ist mir nicht klar. Aber danach gab es eine Klickorgie bis alle IE’s geschlossen waren.

Der mailto Haendler ist unter HKEY_CLASSES_ROOT\mailto zu finden. Das heisst, es muss auch etwas in der Form HKEY_CLASSES_ROOT\mailto\shell\open\command mit einem Eintrag vorhanden sein.

So kann auch eine URL mit dem Standardbrowser geöffnet werden. Dann gibt man bei FileName nur die URL an. http://…

9. WCF Klassen und ihre Konstruktoren

Ich wollte bei der Initialisierung einer neuen Klasse einen Wert erzwingen. Der soll immer gesetzt werden. Dazu habe ich einfach den Konstruktor überladen, dass heisst, keinen leeren mehr angeboten.

Danach wollte der Host nicht mehr starten. Aber die Fehlermeldung gab keinen Hinweis darauf. Auch war in den Tracelogs vom WCF kein Hinweis zu finden. Per Zufall habe ich dann einen Haltepunkt geschickt gesetzt und dort den Hinweis bekommen das die Klasse Serie nicht serialisiert werden kann. Da machte es klick.

Man merke sich. Klassen die über WCF übertragen werden sollen MÜSSEN einen default Konstruktor haben ohne Überladung.

10. WPF Dantenbindung zwischen Controls Eigenschaften

Na ja, ob hier der Titel passt?! Schauen wir mal.

Ich komme immer mal wieder an die Situation das ich Controls einschalten oder ausschalten soll, und das anhand eines anderen Controls. Z.B. Wenn RadioButton IsChecked=true ist, dann bist du eingeblendet. Das geht mit WPF auch erstaunlich einfach.

IsEnabled="{Binding ElementName=optMamUnten, Path=IsChecked}"

Binding ElementName gibt an welches Control man nutzen will. Mit Path wird dann noch gesagt auf welches Property man achten will. Sobald das RadioButton mit dem Namen optMamUnten IsChecked=true ist wird das Control eingeschaltet. So einfach kann es sein.

Gibt dann einen ganz schönen und einfach umzusetzenden Effekt.

Checked 1

Checked 2

kick it on dotnet-kicks.de

Tags: , , , , , , , ,

Entwicklung

Visual Studio 2008 – Neue Klasse ist nicht public

by Roland Schumacher alias GENiALi 26. January 2010 -- 102 Wörter  -- 323 mal gelesen
Dieser Beitrag ist mir was wert:  

Irgend wie kann das gewaltig nerven. Ich bin an einem relativ grossen Projekt. Dabei muss ich, quasi Fliessbandmässig, neue Klassen erstellen.  Allerding sind die Klassen nicht public. Jedesmal das public ergänzen nervt doch gewaltig.

Lösung:

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplatesCache\CSharp\Code\1031\Class.zip
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplatesCache\CSharp\Code\1031\Interface.zip

In diesen zwei ZIP-Dateien sind die Vorlagen drin. Einfach noch ein public hinzufügen und schon klappt es wie gewünscht.

Wie so MS neue Klassen defaultmässig private macht ist mir nicht ganz klar. Ich brauche mehr public Klassen als private.

using System;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ == 3.5)using System.Linq;
$endif$using System.Text;

namespace $rootnamespace$
{
	public class $safeitemrootname$
	{
	}
}

Das public in Zeile 8 macht es möglich.

kick it on dotnet-kicks.de

Tags: , , , ,

Entwicklung

Sound der mir gefällt

by Roland Schumacher alias GENiALi 16. December 2009 -- 137 Wörter  -- 206 mal gelesen
Dieser Beitrag ist mir was wert:  

Zu erst dachte ich an einen Fehler. Das kann doch nicht sein. Der Titel eines Stückes heisst tatsächlich “C Sharp 2005”.

C Sharp 2005

Ich praktiziere jeden Morgen eine Stunde Selbststudium. Zur Zeit lese ich das Buch Effektive Softwarearchitekturen. Dabei höre ich Musik mit dem MediaMonkey.  Ich habe mir dabei angewöhnt die Titel zu bewerten. Das hat sich bewährt wenn man den Sound danach mit dem Mobile oder iPod synchronisiert. Dann ist nur der beste Sound auf dem Teil.

Heute viel mir dann wieder ein Stück auf, bzw. in die Ohren. “C Sharp 2005” von der CD “Dream Dance 35”? C Sharp? Das muss ein Fehler beim Taggen gewesen sein.

Also ab auf Amazon und nach der CD suchen. Tatsächlich, auch dort war der Titel mit “C Sharp 2005” gelistet.

Amazon - Dream Dance 35 - C Sharp 2005

Das ist doch richtiger Sound für einen C# Entwickler. :-)

Tags: , , ,

Ausbildung | Entwicklung

Übersetzen

Diverses

Seitwert

Locations of visitors to this page

Rating
Excellent - 97%overlay Icon

Statistik