Window Stations & Desktops in .NET (1.)

Pokud netusite o co jde, prectete si dokumentaci na MSDN. Ve zkratce, kazda Windowsi session ma typicky jednu window station, ktera obsahuje clipboard a jeden ci vice desktopu. Desktop je logicka jednotka, ktera obsahuje procesy a jejich okna. Procesy v ruznych desktopech nemohou vzajemne ovlivnovat svoje okna (ie, nemuzou si posilat zpravy). Pomoci desktopu bylo odjakziva implementovane oddeleni screensaveru a logon UI od normalnich programu. Ve Viste je take pomoci jineho desktopu implementovany UAC prompt, takze zle aplikace v defaultnim desktopu nemohou programove odkliknout tlacitko "Continue" v UAC desktopu.

Ja bych se sice docela divil, kdyby to nekdo dalsi vyuzil; nicmene: .NET Framework neobsahuje API, ktere by k Window Stations a desktopum umoznovalo pristup, tak jsem si ho musel napsat. Ale muzete tento a nasledujici clanky brat alespon jako lehky tutorial k platform invoke (P/Invoke)...

V tomto prvnim clanku bych ukazal tridu, ktera mi vznikla jako base trida pro objekty popisujici jak window stations, tak desktopy. Jsou si totiz docela podobne: oba objekty maji jmeno, a lze je otevrit, cimz dostame od systemu handle, kterou bychom nemeli zapomenout zavrit.

Tady bych malinko odbocil. V .NETu 2.0 se objevila funkcionalita zvana SafeHandles, coz je samo o sobe zalezitost, ktera vyda na nekolik samostatnych clanku. Hlavni vyhodou je, ze drahy finalizator je na male tride, ktera zapouzdruje pouze a jen ten IntPtr (to je ta handle). SafeHandles jsou implementovane pomoci .NET 2.0 kritickych finalizatoru, u kterych runtime zarucuje, ze 1. budou opravdu zavolany (v pripade nasilneho unloadu AppDomeny), a 2. budou zavolany az PO vsech normalnich finalizatorech. Nehrozi tudiz situace, ze treba FileStream pri finalizaci flushne data do zavrene handle. Soubor se fyzicky zavre az v kritickem finalizatoru SafeHandle. P/Invoke take ref-countingem zajistuje, ze nedojde k zavreni handle, dokud bezi nejaka nativni funkce, ktera ji dostala za parametr.

Dale take finalizator SafeHandles pouziva CER blok, takze uzavreni handle se podari i v pripade stack overflow, abortnuti threadu, nebo jine osklive okolnosti.

Tohle vsechno nas v pripade window stations a desktopu az tak moc netrapi, ale SafeHandles muzeme pouzit i pro ne. Staci z odpovidajici tridy zdedit, poskytnout defaultni konstruktor, overridnout metodu ReleaseHandle, a pouzivat nasi tridu namisto raw IntPtr. Uvidite v druhem clanku.

Takze, nase base trida vypada nasledovne. Ma genericky parametr, ktery specifikuje typ SafeHandle, kterou bude podtrida zapouzdrovat, a pamatuje si svoje jmeno.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace jachymko.Win32
{
    public abstract class NamedNativeObject : IDisposable where THandle : SafeHandle
    {
        private readonly String _name;
        private readonly THandle _handle;

        protected NamedNativeObject(string name, THandle handle)
        {
            if (handle.IsInvalid)
            {
                throw new Win32Exception();
            }

            _name = name;
            _handle = handle;
        }

        public void Dispose()
        {
            _handle.Dispose();
        }

        public string Name
        {
            get { return _name; }
        }

        protected THandle Handle
        {
            get { return _handle; }
        }
    }
}
Zveřejněno 18 June 07 01:30 by jachymko
Vedeno pod: , , ,

Komentář

# jachymko blog said on June 18, 2007 3:46 PM:

V predchozim clanku jsem ukazal base tridu pro nase pojmenovane nativni objekty. Nyni si napiseme implementace

Neregistrovaní uživatele nemužou přidávat komentáře.