
A mellékelt alkalmazás kipróbálása előtt telepítenie kell a SDService projekt által generált szervizet arra a számítógépre, melynek a leállítást el kívánja végezni. Ehhez a .NET Framework InstallUtil.exe segédprogramja használható, paraméterként átadva a szervizállomány elérési útvonalát.
Annak érdekében, hogy az illető számítógépet a saját gépünkön futó kliensről leállíthassuk, egy dolgot kell tennünk. Egy szervizet kell telepíteni az illető számítógépre, és utasítást adni a megfelelő, a gép leállítását elvégző metódus meghívására. A mellékelt alkalmazás két projektet tartalmaz, melyek közül az egyik a telepíthető szervizalkalmazás, a másik a kliens.
Szervizalkalmazás elkészítése
A szervizalkalmazás indulásakor egy szálat is elindít, mely folyamatosan figyeli a 9999 számú portot. Ezen a porton keresztül kapja ugyanis a szervizalkalmazás a klienstől az utasítást a leállításra.
ThreadStart ts = new ThreadStart(Listening);
th = new Thread(ts);
th.Start();
A szál a Listening metódusban figyeli a portot, itt fut egy ciklus, mely addig tart, amíg a klienstől nem érkezik utasítás. A TcpListener objektum AcceptSocket metódusa vizsgálja a szoftvercsatornát, és a ReadForNetwork metódusunkkal olvassuk ki a hálózati adatfolyamból az utasítást.
TcpListener l = new TcpListener(9999);
l.Start();
...
Socket s = l.AcceptSocket();
Minden akkor történik meg, ha a kliens TcpClient objektuma meghívja a Connect metódusát, vagyis csatlakozik.
if (s.Connected)
{
string str = ReadFromNetwork(s);
...
DoShutDown();
break;
}
s.Close();
...
A szerviz leállásakor a szálat is leállítjuk.
Ahhoz, hogy jogunk legyen újraindítani, leállítani egy gépen NT/2000/XP alatt, ahhoz szükséges a SE_SHUTDOWN_NAME privilégium megszerzése az alkalmazásunk, jelen esetben a szerviz számára. Ezt az AdjustTokenPrivileges függvény hívásával megtehetjük, viszont a függvény paramétereihez szükségünk van néhány értékre, melyek megszerzéséhez ismét további függvényeket kell meghívnunk ennek használata előtt.
Első lépésben megszerezzük az alkalmazásunk process-éhez kapcsolódó ACCESS TOKEN-t az OpenProcessToken metódussal.
LuidAttr tp;
IntPtr h = IntPtr.Zero;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref h);
Ezt követően egy egyedi azonosítót kell megszereznünk. Erre szolgál a LookupPrivilegeValue metódus.
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
Majd az AdjustTokenPrivileges metódussal kaphatjuk meg a privilégiumot.
AdjustTokenPrivileges(h, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
Végül az ExitWindowsEx metódussal elvégezhetjük a leállítást. Ezeket a műveleteket a szerviz StopWindows metódusában hajtjuk végre, melyet a DoShutDown függvényben hívunk meg. Az ExitWindowsEx metódus a EWX_SHUTDOWN + EWX_FORCE konstans átadásával végzi el a leállítást.
A szervizalkalmazás telepítése az InstallUtil.exe segédalkalmazással a következő módon végezhető el.
installutil.exe <elérési út>\SDService.exe
Kliensalkalmazás
A kliensalkalmazás Form-ján meg kell adni a leállítandó számítógép nevét, melyre telepítettük a szervizet (és ahol az fut is), valamint a „shutdown” utasítás karakterláncot.
A nyomógombra kattintva létrehozunk egy TcpClient objektumot.
TcpClient tc = new TcpClient();
Kapcsolódunk a portra a szerver-számítógépen.
tc.Connect(textBox1.Text, 9999);
Majd a hálózati adatfolyamba írjuk a karakterláncot.
NetworkStream ns = tc.GetStream();
StreamWriter writer = new StreamWriter(ns);
writer.WriteLine(textBox2.Text);
writer.Close();
A művelet eredményeképpen a számítógép leáll.