Window Stations & Desktops in .NET (3.)

V predchozim clanku jsme napsali implementace SafeHandle, ktere zaobaluji handle k window station a k desktopu. Predtim jsme vytvorili base tridu, ktera si pamatuje jmeno a handle urciteho typu. Nyni je cas od teto tridy zdedit tridu, ktera bude predstavovat window station. Budeme ji modelovat podle WindowsIdentity a podobnych; konstruktor nechame privatni, jelikoz Win32 stejne neumoznuje vytvaret nove window stations. Misto toho vytvorime statickou metodu GetCurrent() a GetWindowStation(string name).

Nekoho by mohlo napadnout - proc delame metodu GetCurrent(), kdyz bychom mohli mit vlastnost Current? Metoda je v tomto pripade lepsi, protoze tim davame vic najevo, kdo je za zlikvidovani (disposnuti) instance zodpovedny. Mit vlastnost, ktera pri kazdem zavolani vytvari novou instanci, to je zverstvo. Takze pokud bychom sli cestou property, museli bychom instanci cachovat. To by mohlo prinest problemy s thread-safety (teoreticky, v pripade window stations asi ne; stejne s ni nemuzeme nic delat), a hlavne by porad nebyl jasny "otec", vlastnik objektu; instance by se pravdepodobne valela kolem az do unloadu AppDomeny. Proto jsem se rozhodnul imitovat WindowsIdentity spise nez treba HttpContext (u ktereho je, narozdil od tohoto pripadu, doba zivota presne dana zacatkem a koncem zpracovani pozadavku).

public sealed class WindowStation : NamedNativeObject<SafeWindowStationHandle>
{
    private const string Winsta0 = "Winsta0";

    private WindowStation(string name, SafeWindowStationHandle handle) : base (name, handle)
    {
    }

    public static WindowStation GetCurrent()
    {
        return new WindowStation(Winsta0, SafeNativeMethods.GetProcessWindowStation());
    }

    public static WindowStation GetWindowStation(string name)
    {
        return new WindowStation(name, OpenWindowStationRead(name));
    }

    private static SafeWindowStationHandle OpenWindowStationRead(string name)
    {
        return SafeNativeMethods.OpenWindowStation(name, false, GenericAccessMask.GenericRead);
    }
}

Takto sama o sobe je trida pomerne k nicemu. Potrebujeme dve hlavni metody; jednu, ktera nam rekne jmena vsech dostupnych window stations (i kdyz na stavajicich Windows se vam asi nestane, ze by tam byla jina nez Winsta0), a druhou, ktera nam rekne jmena desktopu v dane winsta. Obe metody jsou si podobne jako vejce vejci, pouzivaji anonymni metodu pro callback, ktera jmena hazi do Listu deklarovaneho ve "vnejsi" metode. Jeho obsah se pak vrati jako obycejne pole.

public static string[] GetWindowStationNames()
{
    List<String> names = new List<String>();

    EnumWindowStationProc callback = delegate(string winsta, IntPtr state)
    {
        names.Add(winsta);
        return true;
    };

    bool success = SafeNativeMethods.EnumWindowStations(callback, IntPtr.Zero);

    if (!success)
    {
        throw new Win32Exception();
    }

    return names.ToArray();
}

public string[] GetDesktopNames()
{
    List<String> desktopNames = new List<String>();

    EnumDesktopProc callback = delegate(string desktop, IntPtr state)
    {
        desktopNames.Add(desktop);
        return true;
    };

    bool success = SafeNativeMethods.EnumDesktops(Handle, callback, IntPtr.Zero);

    if (!success)
    {
        throw new Win32Exception();
    }

    return desktopNames.ToArray();
}

Posledni, co nam zbyva, jsou deklarace Win32 funkci ve tride SafeNativeMethods, spolu s delegaty a enumy. To vsechno naleznete v attachmentu tohoto postu, protoze jich je docela dost. Strucny popis atributu ReliabilityContract si muzete precist v minulem dile tohoto serialu.

Ted si jeste ukazeme jak tridu z PowerShellu zavolat:

PS C:\> $asmpath = 'D:\jachymko.Win32\bin\Debug\jachymko.Win32.dll'
PS C:\> [Reflection.Assembly]::LoadFrom($asmpath) | Out-Null
PS C:\>
PS C:\> $winsta = [jachymko.Win32.WindowStation]::GetCurrent()
PS C:\> $winsta

Name
----
Winsta0


PS C:\> $winsta.GetDesktopNames()
Screen-saver
testicek
Default
Winlogon
PS C:\> $winsta.Dispose()
PS C:\>
Zveřejněno 19 června 07 03:00 by jachymko
Vedeno pod: , ,

Attachment(s): SafeNativeMethods.cs.txt

Komentář

Žádné komentáře
Neregistrovaní uživatele nemužou přidávat komentáře.
Vyvojar.cz na prodej!