Installing a Windows Service without MSI

30 July 2009

Recently I had to write a Windows service in C# and encountered an interesting issue: seems that, due to our setup, I was not allowed to use msi packages to install it.

This post doesn’t focus on writing Windows services, as there are numerous sources online that talk about this. For example you can take a look at this article on CodeProject: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

The interesting thing is that all articles on services end with installation through msi – you write the service installer class decorated with the RunInstaller attribute and use a custom action on the setup project that automatically takes care of running the installation code.

But, as I said, I couldn’t use such a setup project. After some more searching, I found another interesting article that suggested using the InstallUtil application that comes with .NET Framework: http://www.codeproject.com/KB/cs/DynWinServiceInstallUtil.aspx

Seems that the application does pretty much the same thing as a deployment through msi would do, namely it runs the required code in the RunInstaller class. But I was reluctant do depend on a batch file for deployment. Now considering that the RunInstaller attribute is implemented in the framework, I thought there also must be a class that interprets this attribute. Seems I was right: I found the AssemblyInstaller class in the System.Configuration.Install namespace.

The AssemblyInstaller constructor takes as argument an assembly and a set of command line options and provides the same methods available through msi deployment – Install, Commit, Rollback and Uninstall. More information on the AssemblyInstaller can be found on MSDN: http://msdn.microsoft.com/en-us/library/system.configuration.install.assemblyinstaller.aspx

I suggest this approach in case msi deployment is unavailable, the advantage over using a batch file being that it is completely independent of external applications (except the .NET Framework, of course), any custom deployment code can be added and you also get .NET exception handling for any errors that might occur.


C# Custom Indexers

25 February 2009

To add an indexer to a class, similar to the ones on Dictionary or List for example, all you need to do is to create a property object this[object indexer]. For example:

class MyClass
{
    public string this[int index]
    {
        get
        {
            return "Hello world!";
        }
    }
}

The class can now be indexed using an integer and returns a string (“Hello world!” in our case). An example of using this indexer:

class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();


        Console.WriteLine(myClass[10]);
    }
}

Indexing an instance of MyClass with any value yelds our string. Of course, any types can be used as indexer and returend values. And it is enough to implement a setter ( set { } ) to enable attributing to the indexed element.


Implicit Typecasting in C#

25 February 2009

To enable a class to be implicitely typecasted to or from another class, create a public static method marked with the implicit operator keywords as follows:

public static implicit operator ClassToCastFrom(ClassToCastTo object) {...} 

Either ClassToCastFrom or ClassToCastTo must be the containing class. As an example, consider the class MyClass:

class MyClass
{
    private string value;

    public MyClass(string value)
    {
        this.value = value;
    }

    public override string ToString()
    {
        return value;
    }

    public static implicit operator int(MyClass myClass)
    {
        return 10;
    }

    public static implicit operator MyClass(int int32)
    {
        return new MyClass("From int " + int32);
    }
}

The class encapsulates a string and implements operators that enable it to be implicitely casted to and from int. When typecasted to int, it will become 10. When typecasted from int, its value will become “From int ” + the value of the int.

An example of implicit typecasting:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(20 + new MyClass(""));

        MyClass myInstance = 10;
        Console.WriteLine(myInstance.ToString());
    }

    static void ToInt32(int int32)
    {
        Console.WriteLine(int32);
    }
}

Notice that you can add an instance of MyClass to an int and you can assign an int to a MyClass instance.

We need  to call myInstance.ToString() instead of just passing myInstance to WriteLine because WriteLine doesn’t have an overload that accepts MyClass parameters. We would expect to upcast MyClass to object and call the inherited ToString() method but implicit typecasting takes precedency over upcasting, so calling Console.WriteLine(myInstance) would in fact convert it to an int instead of an object.


ECall methods must be packaged into a system module

24 September 2008

After a long time, I’m writing a new technical post. Actually, I’m translating an older post I written in Romanian since the information about the exception is scarce. I stumbled upon the error while looking into the Assembly.Load method source code (/clr/src/bcl/system/reflection/Assembly.cs) which you can get through Rotor. I noticed that the method just calls another method, nLoad. In the same source file, nLoad is declared as:

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern Assembly nLoad(
    AssemblyName fileName,
    String codeBase,
    Evidence assemblySecurity,
    Assembly locationHint,
    ref StackCrawlMark stackMark,
    bool throwOnFileNotFound,
    bool forIntrospection);

I tried to call the same nLoad method by copying its declaration in my project but I quickly found out that it was harder than expected because StackCrawlMark, as it appears as a parameter, is actually declared as an alias:

using StackCrawlMark = System.Threading.StackCrawlMarl;

Where System.Threading.StackCrawlMark has an internal visibility so it can’t be used outside the assembly. Anyway, I was courious what

[MethodImplAttribute(MethodImplOptions.InternalCall)] meant.

MSDN says it is a method implemented in the CLR itself. After a bit of research, I found out that all methods of this kind are implemented in the ecall.cpp file (/clr/src/vm/ecall.cpp), ecall probably standing for Engine Call. Although the Base Class Library is written in C#, the virtual machine is written in C++. The file contains quite a lot of methods which BCL calls using the above attribute.

Out of curiosity, I tried to call one of those methods myself – not nLoad because of the StackCrawlMark type, but I found something simpler: string GetFullName(). So I create the declaration

[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string GetFullName();

and call

Console.WriteLine(GetFullName());

Keep in mind, if you want to recreate the experiment, to also add using System.Runtime.CompilerServices; because that namespace contains the attribute MethodImpl.

The result of running the application was a System.Security.SecurityException: ECall methods must be packaged into a system module. This means all calls of the InternalCall kind can be made only from mscorlib.dll and such but no user created assembly.


Structuri de date în C#

26 July 2008

O sursă foarte bună de informații privind structurile de date este chiar MSDN. Mai exact seria de articole An Extensive Examination of Data Structures Using C# 2.0.

Dau link-ul de mai sus pentru că am observat că mai multe persoane au ajuns să-mi viziteze blog-ul căutând pe Google arbori binari, arbori binari de căutare și alte structuri de date în C# și au fost probabil dezamăgiți pentru că nu am tratat așa ceva aici. Încercați articolele pentru că sunt explicate bine, este și cod, sunt până și desene.


Carets for Custom Controls

5 June 2008

I decided to start posting in English (at least the technical posts). I hope this way I can reach more people who might be interested in the things I blog about (the .NET Framework, C#, compilers and such).

Today I was thinking about developing a custom control that receives text input. But how am I supposed to display the caret? I searched the Internet for some .NET controls that do the same thing and the best I got was a separate thread used only for blinking a custom drawn caret. That seemed a bit strange – are all WinForm controls implemented that way?

I decided to go to the source – how does WinAPI go about drawing them? Well, pretty simple – there are a bunch of functions in user32.dll. I imported some of them:

[DllImport("user32.dll")]
static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);

[DllImport("user32.dll")]
static extern bool SetCaretPos(int X, int Y);

[DllImport("user32.dll")]
static extern bool ShowCaret(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool DestroyCaret();

From here on, things are pretty simple. One thing to note though, MSDN clearly states that there is only one caret created per message queue – that is, you can’t have two different carets blinking at the same time in different controls (or the same control for that matter). So, to add a custom caret to the form itself, I just handled the Activated and Deactivated events:

private void Form1_Activated(object sender, EventArgs e)
{
    CreateCaret(this.Handle, 1, 5, 10);
    SetCaretPos(0, 0);
    ShowCaret(this.Handle);
}

private void Form1_Deactivate(object sender, EventArgs e)
{
    DestroyCaret();
}

The argument 1 for hBitmap will give it the neat appearance – more about it on MSDN. This example is very basic but I think it’s a good starting point.


Fața nevăzută a CLR-ului

1 June 2008

Eram curios cum funcționează metoda Assembly.Load – nu mai conteză de ce. Ca norocul, am pe calculator Shared Source Common Language Infrastructure 2.0 (de pe DVD-ul ARK, dar daca vreti, il puteti lua si de la Microsoft Research sub numele de Rotor). SSCLI sunt sursele de la .NET Framework, compilatorul de C# și altele, distribuite ca shared source.

După cum ziceam, caut Assembly.Load și găsesc declarația în /clr/src/bcl/system/reflection/Assembly.cs. Metoda apelează nLoad. Caut nLoad și găsesc în același fișier următoarea declarație:

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern Assembly nLoad(
    AssemblyName fileName,
    String codeBase,
    Evidence assemblySecurity,
    Assembly locationHint,
    ref StackCrawlMark stackMark,
    bool throwOnFileNotFound,
    bool forIntrospection);

Sunt curios dacă pot și eu apela metoda nLoad. Aflu rapid că nu - StackCrawlMark este un alias declarat la începutul fișierului ca

using StackCrawlMark = System.Threading.StackCrawlMark;

unde System.Threading.StackCrawlMark are vizibilitatea internal – adică nu poate fi utilizat în afara assembly-ului în care apare :( OK, totuși, ce înseamnă atributul

[MethodImplAttribute(MethodImplOptions.InternalCall)]?

Cică, spune MSDN, atributul denotă o metodă implementată chiar în CLR. După încă puține săpături, descopăr toate metodele astfel implementate în fișierul ecall.cpp (/clr/src/vm/echall.cpp) – ecall probabil de la Engine Call. Chiar dacă Base Class Library e scris în C#, mașina virtuală e scrisă în C++. În fișier este o listă măricică de funcții care sunt apelate de BCL cu ajutorul atributului de mai sus.

De curiozitate, încerc să apelez și eu o astfel de metodă – nu nLoad pentru că nu pot din cauza lui StackCrawlMark, dar găsesc ceva mai simplu: string GetFullName(). Declar și eu frumos

[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string GetFullName();

și apelez

Console.WriteLine(GetFullName());

Să nu uit de using System.Runtime.CompilerServices pentru cine vrea să refacă experimentul – acolo e declarat atributul MethodImpl.

Rezultatul? Excepție de tip System.Security.SecurityException: ECall methods must be packaged into a system module. Deci apelurile de tip InternalCall pot fi făcute doar din mscorlib.dll. Asta este. Măcar acum știu de existența lor.


Reflection și obiecte dinamice

31 May 2008

În cele ce urmează vreau să prezint un exemplu de lucru cu obiecte dinamice folosind Reflection. Nu ține atât de mult de compilatoare cât de interpretoare, unde, pe baza unor șiruri de caractere, instanțiem obiecte și facem apeluri de metode.

Avem clasa System.Type care încapsulează informații despre tipuri, precum și clasele ConstructorInfo și MethodInfo derivate din MethodBase care încapsulează informații despre constructori, respectiv metode, clase pe care le găsim în namespace-ul System.Reflection.

Pentru a crea de exemplu o instanță a clasei StringBuilder și a concatena două șiruri de caractere, avem următoarele linii de cod:

ConstructorInfo ci = Type.GetType("System.Text.StringBuilder").GetConstructor (Type.EmptyTypes);
object test = ci.Invoke(null);

MethodInfo mi = test.GetType().GetMethod("Append", new Type[] { typeof(string) });
mi.Invoke(test, new object[] { "Hello " });
mi.Invoke(test, new object[] { "World!" });

Console.WriteLine(test);

Se observă că, din punct de vedere al compilatorului de C#, StringBuilder nu apare decât într-un șir de caractere iar obiectul utilizat este de tipul de bază object. Prima instrucțiune întoarce o instanță ConstructorInfo ce corespunde constructorului fără parametri a clasei StringBuilder. Metoda statică Type.GetType returnează instanța System.Type corespunzătoare tipului identificat printr-un șir de caractere. GetConstructor primește ca parametrii un vector de tipuri care reprezintă tipurile argumentelor – în cazul nostru nu avem argumente așa că folosim Type.EmptyTypes care este, de fapt, echivalent cu new Type[0] dar ne scutește de instanțiere.

Invoke apelează metoda cu o listă de argumente, null în cazul nostru și întoarce un obiect (System.Object). Am creat astfel dinamic o instanță StringBuilder.

Similar, luăm instanța System.Type corespunzătoare obiectului – test.GetType() - și apelăm GetMethod care primește un nume de metodă și o listă de argumente. Căutăm metoda Append cu un singur argument de tip string.

Aici, la apelul Invoke trebuie să precizăm și instanța cu care apelăm metoda (obiectul test) și argumentele.

Ultima linie va afișa pe ecran “Hello World!”.

Dacă snippet-ul de mai sus pare încă destul de hard-coded, putem, în locul lui, introduce următoarele:
un dicționar care să rețină instanțele pe care le-am creat, o metodă pentru a construi obiecte și o metodă pentru apeluri astfel:

private static Dictionary objects = new Dictionary();

public static void Create(string name, string type)
{
    ConstructorInfo ci = Type.GetType(type).GetConstructor(Type.EmptyTypes);
    object obj = ci.Invoke(null);

    objects.Add(name, obj);
}

public static void Call(string name, string method, params string[] arguments)
{
    // Aici construim tipurile pe baza argumentelor
    Type[] args = new Type[arguments.Length];

    for (int i = 0; i < args.Length; i++)
    {
        // Doar tipul string
        args[i] = Type.GetType("System.String");
    }

    MethodInfo mi = objects[name].GetType().GetMethod(method, args);
    mi.Invoke(objects[name], arguments);
}

Metoda Create primește ca argumente un nume de variabilă și un tip și apelează constructorul fără parametri al tipului, metoda Call primește numele variabilei, numele metodei și o listă de argumente de tip string. M-am limitat în exemplu la constructori fără parametri și metode ce primesc argumente string nu pentru că Reflection nu mi-ar permite mai mult, doar că, pentru a determina alte tipuri doar pe baza unor string-uri am avea nevoie de un parser (care să determine, de exemplu, că “10.5″ e de tip float).

Acum putem scrie “Hello World!” astfel:
 
static void Main(string[] args)
{
    Create("test", "System.Text.StringBuilder");
    Call("test", "Append", "Hello ");
    Call("test", "Append", "World!");

    Console.WriteLine(objects["test"]);
}

Și nu numai:

static void Main(string[] args)
{
    Create("test", "System.Text.StringBuilder");
    Call("test", "AppendFormat", "{0} {1}!", "Hello", "World");

    Console.WriteLine(objects["test"]);
}

Astfel se crează obiecte și se apelează metode dinamic utilizând Reflection. Desigur, se pot face multe altele – de exemplu putem seta valori la diferite atribute ale obiectelor instanțiate. Un dezavantaj ar fi timpul de execuție – codul compilat (MSIL) rulează mult mai repede decât apelurile Invoke dar pentru un interpretor aceasta ar fi una din posibilitățile de implementare.


DWM Managed API

25 May 2008

Desktop Window Manager was introduced with Windows Vista and it enables the Aero GUI. The library that exposes the DWM functionality is dwmapi.dll. A while ago, I wrote a C# wrapper over the library to enable WinForms applications to use the new user interface capabilities. The DWM Managed API covers most of the DWM functionality, except the frame timing API (which most developers shouldn’t need anyway).

Feel free to download, use, modify and extend it.

You can find more information on DWM (the Win32 API) here: http://msdn.microsoft.com/en-us/library/aa969540(VS.85).aspx