Erinevus teenuse ja rakenduse vahel. Milliseid Windowsi teenuseid on vaja ja milliseid saab keelata. Päästikupõhiste teenuste tekkimine

Tarkvara ühilduvuse seisukohalt. Seega on loomulik, et tuleme tagasi Windows 7 kontekstis teenuste arutamise juurde. Kuid seekord räägime mõnest Windows 7-s saadaolevate teenuste optimeerimise eelistest. See artikkel käsitleb Windows 7 uut funktsiooni – Käivitage käivitusteenused. Kuid enne API vaatamist vaatame teenuste suurt pilti.

Mis on teenused?

Teenus on Windowsi operatsioonisüsteemi sisseehitatud sisemine mehhanism. Teenused võivad mõelda kui erirakendused, mis töötavad olenemata praegusest kasutajakontekstist. Teenused erinevad tavalistest rakendustest selle poolest, et neid saab konfigureerida töötama süsteemi sisselülitamise (käivitamise) hetkest kuni sulgemiseni, ilma et oleks vaja kasutaja kohalolekut. See tähendab, et teenused võivad töötada ka siis, kui kasutaja pole sisse logitud.

Eelistame käsitleda teenuseid kui töötavaid ülesandeid, mis töötavad taustal ega mõjuta kasutaja toiminguid. Windowsi teenused vastutavad igat tüüpi taustatoimingute eest, alates kaugprotseduurikõnest (RPC), printeri spuulerist ja lõpetades võrgu asukohateadlikkusega.

Aastate jooksul on Windows kasvanud ja ka teenuste arv kasvanud. Olgem ausad, Windowsi taustteenused on natuke piin – operatsioonisüsteemiga on kaasas palju teenuseid. Lisaks lisavad sõltumatud tarkvaraarendajad (ISV) ja nende rakendused veelgi rohkem teenuseid. Näiteks tarkvarauuendusteenused. Mõned teenused on aga kriitilised ja vajalikud alglaadimisprotsessi ajal, samas kui teisi on vaja hiljem, kui konkreetne kasutaja sisse logib, ja teisi ei pea üldse käivitama enne, kui neile helistatakse. Sellele vaatamata näete praegu töötavate teenuste loendit vaadates palju objekte, mis ei pea 24x7 töötama.

Mis viga on teenustel, mis töötavad 24 tundi ööpäevas ja 7 päeva nädalas?

24x7 teenustega on seotud mitmeid probleeme. Esiteks, miks peaks midagi töötama (isegi taustal), kui seda pole vaja? Iga töötav protsess (sh teenused) kasutab väärtuslikku mälu ja protsessori ressursse, mida saaks kasutada muude rakenduste ja teenuste jaoks. Kui loendate kõik antud hetkel töötavad teenused, annavad need kokku märkimisväärse hulga mälu, käepidemeid, lõime ja protsessori kasutust. Kõik need "raisatud" ressursid vähendavad arvuti üldist jõudlust, vähendavad selle reageerimisvõimet ja muudavad arvuti loiduks ja aeglaseks. Lisaks, kuna paljud teenused on konfigureeritud automaatselt käivituma (hakkavad töötama süsteemi käivitumisel), mõjutavad need arvuti alglaadimisaega.

Teiseks mõjutavad need raisatud ressursid otseselt energiatarbimist. Mida suurem on protsessori koormus, seda rohkem energiat arvuti tarbib. See võib sülearvutite puhul olla kriitiline ja lühendada aku kasutusaega mitme tunni võrra.

Kolmandaks võib ebaproduktiivse tarkvara pidev töötamine põhjustada mälulekkeid ja süsteemi üldist ebastabiilsust. See põhjustab rakenduste ja lõpuks arvuti rikke.

Lõpuks, kui teenus töötab 24x7 ja kui see on tuntud teenus (mis võib olla igal populaarsel rakendusel, näiteks PDF-lugeja), loob see suure rünnakupinna. Ründaja võib kasutada teavet selle kohta, et teatud populaarne rakendus installib ööpäevaringse teenuse ja proovida seda arvutile juurdepääsu saamiseks häkkida.

Seda kõike arvesse võttes võite küsida, miks nii paljud arendajad seadistavad oma teenuseid pidevalt töötama, kui neil on mõni muu võimalus. Juba enne Windows 7 oli teenuste käivitamiseks saadaval mitu võimalust:

  • Keelatud keelab teenuse täielikult ja takistab selle ja sõltuvate teenuste käivitamist – see tähendab, et kasutaja peab teenuse juhtpaneelilt või käsurealt käsitsi lubama
  • Käsiraamat käivitab teenuse vastavalt vajadusele (muude teenuste sõltuvuste tõttu) või kui teenust kutsutakse vastavate API-de abil rakendusest, nagu allpool näidatud
  • Automaatne käivitab sisselogimisel teenuse
  • Automaatne viivitus– Windows Vistas kasutusele võetud uuemat tüüpi käivitus, millega teenus käivitub pärast alglaadimise lõppemist ja esmaste toimingute sooritamist, mis kiirendab süsteemi käivitamist.

Kahjuks määravad paljud ISV-d (sealhulgas Microsoft ise) jätkuvalt oma teenustele automaatse või automaatse viivitusega, kuna see tundub kõigi jaoks kõige lihtsam lahendus. Teenus töötab lihtsalt 24x7 ja on alati saadaval, välistades vajaduse kontrollida sõltuvusi või seda, kas teenus töötab.

On palju näiteid olemasolevatest teenustest, mis võivad kasutada palju vähem ressursse ja muutuda turvalisemaks ilma ööpäevaringselt töötamata. Mõelge näiteks värskendusteenusele, mis otsib rakendusele uusi värskendusi. Kui arvuti pole võrku ühendatud ja sellel pole IP-aadressi, siis miks peaks see töötama? See ei saa midagi teha, miks siis jätta tööle programm, mis ei tee midagi? Mõelge poliitikahaldusteenusele, mida kasutatakse rühmapoliitika muutmisel või arvuti liitumisel domeeniga või sellest lahkumisel, kuid nüüd, kui arvuti on ühendatud minu koduvõrguga, töötab teenus jälle tühjalt.

Päästikupõhiste teenuste tekkimine

Lahendus ülaltoodud probleemidele on teisaldada teenus "alati sisselülitatud olekust" teist tüüpi taustategevustele, näiteks ajastatud toimingutele või käivitatud teenustele. See artikkel käsitleb Windows 7 käivitusteenuseid. Windows 7 ajastatud ülesannete kohta võib öelda palju huvitavat, mida tehakse järgmistes artiklites.

Viimati uuendatud: 31.10.2015

Windows OS-i üks olulisemaid komponente on teenused. Tegelikult on need eraldi rakendused, millel puudub graafiline liides ja mis täidavad taustal erinevaid ülesandeid. Teenused saab käivitada operatsioonisüsteemi käivitumisel või muul ajal, kui kasutaja töötab. Levinud näide teenustest on erinevad veebiserverid, mis kuulavad taustal ühenduste loomiseks kindlat porti ja kui ühendused on olemas, siis suhtlevad nendega. See võib olla ka erinevad lisavärskendusteenused teistele installitud programmidele, mis võtavad serveriga ühendust, et teada saada, kas rakenduse uus versioon on saadaval. Üldiselt saame avada teenuste paneeli ja näha ise kõiki installitud ja töötavaid teenuseid:

Vaatame, kuidas C#-s oma teenuseid luua. Rakendatava ülesandena valime failisüsteemi konkreetse kausta muudatuste jälgimise. Nüüd loome selle täitmiseks teenuse.

Kõigepealt loome uue projekti, mille tüüp on Windows Service. Nimetagem projekti FileWatcherService:

Visual Studio genereerib seejärel projekti, milles on kõik vajalik. Kuigi me ei pea tingimata seda tüüpi projekti valima, võiksime luua klassiteegi projekti ja seejärel määratleda selles kõik vajalikud klassid.

Seega näeb uus projekt välja selline:

Samuti on fail Program.cs ja tegelik teenindussõlm Service1.cs.

Teenus kujutab endast tavalist rakendust, kuid see ei käivitu iseenesest. Kõik kõned ja juurdepääs sellele läbivad teenuse juhtimishalduri (Service Control Manager või SCM). Kui teenus käivitub automaatselt süsteemi käivitamisel või käsitsi, kutsub SCM klassis Programm põhimeetodit:

Staatilise klassi programm ( staatiline tühine Main() ( ServiceBase ServicesToRun; ServicesToRun = new ServiceBase ( new Service1() ); ServiceBase.Run(ServicesToRun); ) )

Põhimeetod on vaikimisi määratletud mitme teenuse korraga käitamiseks, mis on määratletud massiivi ServicesToRun. Vaikimisi sisaldab projekt aga ainult ühte teenust Service1. Käivitamine ise toimub Run-meetodi abil: ServiceBase.Run(ServicesToRun) .

Käivitavat teenust esindab sõlm Service1.cs. See pole aga tegelikult lihtne koodifail. Kui me selle sõlme avame, näeme teenuse kujundaja faili Service1.Designer.cs ja klassi Service1.

Service1 klass esindab tegelikult teenust. Vaikimisi on sellel järgmine kood:

Süsteemi kasutamine; kasutades System.Collections.Generic; kasutades System.ComponentModel; kasutades System.Data; kasutades System.Diagnostics; kasutades System.Linq; kasutades System.ServiceProcessi; kasutades System.Text; kasutades System.Threading.Tasks; nimeruum FileWatcherService ( avalik osaline klass Service1: ServiceBase ( avalik teenus1() ( InitializeComponent(); ) protected override void OnStart(string args) ( ) Protected override void OnStop() ( ) ) )

Teenuseklass peab pärinema ServiceBase'i baasklassist. See klass määratleb mitmeid meetodeid, millest olulisemad on meetod OnStart(), mis käivitab teenuse poolt sooritatavad toimingud, ja meetod OnStop(), mis peatab teenuse.

Pärast seda, kui SCM helistab põhimeetodile ja registreerib teenuse, kutsutakse see otse välja, käivitades meetodi OnStart.

Kui saadame teenuste konsoolis või käsurea kaudu käsu teenuse peatamiseks, kutsub SCM selle peatamiseks OnStop-meetodi.

Lisaks nendele kahele teenuseklassi meetodile saate alistada veel mitu ServiceBase'i baasklassi meetodit.

    OnPause: helistatakse, kui teenus on peatatud

    OnContinue: helistatakse, kui teenus jätkub pärast selle peatamist

    OnShutdown: kutsutakse välja, kui Windows lülitub välja

    OnPowerEvent: kutsutakse välja, kui toiterežiim muutub

    OnCustomCommand: kutsutakse välja, kui teenus saab teenusehaldurilt (SCM) kohandatud käsu

Klassi Service1 konstruktoris kutsutakse välja meetod InitializeComponent(), mis on määratletud kujundajafailis Service1.Designer.cs:

Nimeruum FileWatcherService ( osaline klass Service1 ( privaatne System.ComponentModel.IContainer komponendid = null; kaitstud alistamine void Dispose(bool disposing) ( if (disposing && (components != null)) ( komponentid.Dispose(); ) base.Dispose(disposing ); ) private void InitializeComponent() ( komponendid = new System.ComponentModel.Container(); this.ServiceName = "Service1"; ) ) )

Ainus asi, mida tuleb märkida, on teenuse nime määramine (ServiceName atribuut):

This.ServiceName = "Teenus1";

See on nimi, mis kuvatakse teenusekonsoolis pärast selle teenuse installimist. Me saame seda muuta või jätta nii nagu see on.

Nüüd muudame teeninduskoodi järgmiselt:

Süsteemi kasutamine; kasutades System.ServiceProcessi; kasutades System.IO; kasutades System.Threading; nimeruum FileWatcherService ( avalik osaline klass Service1: ServiceBase ( logija logija; avalik teenus1() ( InitializeComponent(); this.CanStop = true; this.CanPauseAndContinue = true; this.AutoLog = true; ) kaitstud alistamine void OnStart(string args) ( logija = new Logger(); Thread.Sleep(1000); ) ) class Logger ( FileSystemWatcheri jälgija; objekt obj = uus objekt(); bool lubatud = tõene; public Logger() ( jälgija = new FileSystemWatcher("D:\\Temp"); jälgija.Kustutatud += Watcher_Deleted; watcher.Created + = Watcher_Created; Watcher.Changed += Watcher.Renamed += Watcher_Renamed = false = false ) // failide ümbernimetamine string filePath = e.OldFullPath; RecordEntry(failisündmus, failitee); ) // failide muutmine privaatne void Watcher_Changed(objekti saatja, FileSystemEventArgs e) ( string fileEvent = "changed"; string filePath = e.FullPath; RecordEntry(fileEvent, filePath); ) // failide loomine privaatne void Watcher_Created(objekti saatja, FileSysys e) ( string fileEvent = "loodud"; string filePath = e.FullPath; RecordEntry(fileEvent, filePath); ) // failide kustutamine private void Watcher_Deleted(objekti saatja, FileSystemEventArgs e) ( string fileEvent = "kustutatud"; string filePath = e.FullPath; RecordEntry(fileEvent, filePath privaatne void RecordEntry(string fileEvent, string filePath) ( lukk (obj) ( kasutades (StreamWriter writer = new StreamWriter("D:\\templog.txt", true)) (kirjutaja); .WriteLine(String.Format("(0) fail (1) oli (2)", DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss"), failitee, failisündmus Flush()); ; ) ) )

Võtmeklass, mis hõlmab kõiki funktsioone, on Loggeri klass. Objekti FileSystemWatcher abil jälgib see kaustas tehtud muudatusi D://Temp. Meetod Start() määrab, et jälgime muudatusi FileSystemWatcheri objekti kaudu. Ja kogu töö jätkub seni, kuni lubatud tõeväärtusmuutuja on tõene. Ja Stop() meetod võimaldab klassil lõpetada.

FileSystemWatcheri sündmused võimaldavad teil jälgida kõiki vaadeldavas kaustas tehtud muudatusi. See salvestab faili templog.txt muudatused. Vältimaks ressursijooksu templog.txt faili pärast, millesse muudatused salvestatakse, blokeerib salvestusprotseduuri lock(obj) tünn.

Selle tulemusena sisaldab logifail pärast loomist, muutmist, ümbernimetamist ja kustutamist midagi sellist:

30.07.2015 12:15:40 fail D:\Temp\Uus tekstidokument.txt loodi 30.07.2015 12:15:46 fail D:\Temp\Uus tekstidokument.txt nimetati ümber D:\ Temp\tere 07/30/2015 12:15:55 faili D:\Temp\hello.txt muudeti 30.07.2015 12:15:55 faili D:\Temp\hello.txt muudeti 30.07. /2015 12:16:01 fail D: \Temp\hello.txt on kustutatud

Teenindusklassis Service1 on konstruktoris seatud mitu valikut:

This.CanStop = tõsi; // teenuse saab selle peatada.CanPauseAndContinue = true; // teenuse saab peatada ja seejärel seda jätkata.AutoLog = true; // teenus saab logisse kirjutada

OnStart() meetodi puhul kutsutakse Loggeri objekti käivitamiseks uus lõim:

Kaitstud alistamine void OnStart(string args) ( logija = new Logger(); Thread loggerThread = new Thread(new ThreadStart(logger.Start)); loggerThread.Start(); )

Uut lõime on vaja, kuna praegune lõim töötleb ainult SCM-i käske ja peab võimalikult kiiresti OnStart-meetodilt tagasi pöörduma.

Kui SCM-ilt saadakse käsk teenuse peatamiseks, käivitub meetod OnStop, mis kutsub välja meetodi logger.Stop(). Täiendav viivitus võimaldab logija lõimel peatada:

Kaitstud alistamine void OnStop() ( logger.Stop(); Thread.Sleep(1000); )

Kuid teenindusklassist iseenesest ei piisa. Peame looma ka teenuse paigaldaja.

Või kasutajate töölaud (nii lokaalne kui ka kaugjuhtimine), kuid mõne teenuse puhul on võimalik erand - suhtlus konsooliga (seansi number 0, millesse kasutaja registreeritakse kohapeal või teenuse käivitamisel mstsc lülitiga /console).

Teenuste jaoks on mitu režiimi:

  • vettelaskmine keelatud;
  • käsitsi käivitamine (soovi korral);
  • automaatne käivitamine arvuti käivitumisel;
  • automaatne (viivitatud) käivitamine (kasutusele võetud opsüsteemides Windows Vista ja Windows Server 2008);
  • kohustuslik teenus/draiver (automaatne käivitus ja võimetus (kasutaja jaoks) teenust peatada).

Taustarežiim

Käivitage, peatage ja muutke Windowsi teenuseid

MMC-s saab teenuseid ja nende atribuute muuta:

Operatsioonisüsteemide erinevatel versioonidel võivad mõned teenused olla ja teised mitte. Mõned eraldi installitud rakendused ja programmid saavad luua ka oma teenuseid.

Microsoft Windowsi operatsioonisüsteemi teenuste loend

Kuvatav nimi Teenuse nimi Funktsioonid Kirjeldus
DHCP klient Dhcp Registreerib ja värskendab selle arvuti IP-aadresse ja DNS-kirjeid. Kui see teenus peatatakse, ei saa see arvuti dünaamilisi IP-aadresse hankida ega DNS-i värskendusi teha.
DNS-klient Dnscache DNS-klienditeenus (dnscache) salvestab vahemällu domeeninimesüsteemi (DNS) nimed ja registreerib antud arvuti täielikult kvalifitseeritud nime. Kui teenus peatatakse, jätkatakse DNS-nime lahendamist. DNS-i nimejärjekordade tulemusi aga vahemällu ei salvestata ja arvuti nime ei registreerita.
KtmRm hajutatud tehingute koordinaatori jaoks KtmRm Koordineerib tehinguid MSDTC ja Kernel Transaction Manageri (KTM) vahel.
ReadyBoost EMDMgmt ReadyBoost Süsteemi jõudluse parandamise tugi ReadyBoosti tehnoloogia abil.
Superfetch SysMain Superfetch Säilitab ja parandab süsteemi jõudlust.
Windows Audio Audiosrv Windowsi programmide helitööriistade haldamine. Kui see teenus peatatakse, ei tööta heliseadmed ja efektid õigesti.
Windows CardSpace idsvc Pakub turvalise võimaluse luua, hallata ja paljastada digitaalseid identiteete.
Automaatne värskendus WUAUSERV Sisaldab Windowsi värskenduste allalaadimist ja installimist. Kui teenus on keelatud, ei saa see arvuti kasutada automaatvärskendusi ega Windows Update'i veebisaiti.
Remote Procedure Call (RPC) RpcSs Pakub lõpp-punktide ja muude RPC-teenuste vahelist vastendamist.

Microsofti rakenduste ja programmide loodud teenuste loend

Näited kolmandate osapoolte rakenduste ja programmide loodud teenustest

Kuvatav nimi Teenuse nimi Funktsioonid Kirjeldus
ESET HTTP server EhttpSrv viirusetõrje ESET HTTP serveri komponent

Kuidas rakendust Windowsi teenusena käivitada

Kas kliendirakendust on võimalik teenusena käivitada? Ühes neist kirjeldasin Windowsi teenuse loomiseks tavalisi OS-i tööriistu. Kuid mitte iga konsoolirakendus ei saa töötada teenusena ja graafilise liidesega programmid ei saa põhimõtteliselt sel viisil töötada. Kuid rakendust on siiski võimalik teenusena käivitada ja selles aitab meid algse nimega programm Mitteimemise teenusejuht.

NSSM on tasuta ja avatud lähtekoodiga tarkvara ning toetab kõiki Microsofti operatsioonisüsteeme alates Windows 2000 kuni Windows 8. NSSM ei vaja installimist, lihtsalt laadige see alla ja pakkige lahti. Distributsioon sisaldab versioone 32- ja 64-bitiste operatsioonisüsteemide jaoks. Programmi saad kodulehelt nssm.cc, hetkel on viimane stabiilne versioon 2.21.1, mida kasutan.

NSSM-i võimaluste demonstreerimiseks proovime Windows 8.1-s teenusena käivitada Windows Notepad.

Teenuse loomine

Teenuse loomiseks nimega märkmik käivita käsukonsool, mine lahtipakkitud NSSM-iga kausta (64-bitise Windowsi jaoks) ja sisesta käsk nssm install notepad, mis avab NSSM-i graafilise installeri akna. Teenuse loomiseks määrake lihtsalt väljal Path käivitatava faili tee ja klõpsake nuppu "Installi teenus". Lisaks saate väljal Valikud määrata teenuse käivitamiseks vajalikud võtmed.

Uue teenuse loomisel saate määrata ka mõned lisaparameetrid.

Vahekaardil Shutdown on loetletud sulgemismeetodid ja ajalõpud, mida kasutatakse siis, kui rakendus tavapäraselt lülitub välja või jookseb kokku. Kui NSSM saab seiskamiskäsu (näiteks kui rakendus suletakse), proovib see juhitavat rakendust tavapärasel viisil peatada. Kui rakendus ei reageeri, võib NSSM sunniviisiliselt lõpetada selle rakenduse kõik protsessid ja alamprotsessid.

Rakenduse sulgemiseks on neli sammu ja vaikimisi kasutatakse neid järgmises järjekorras:

Esimeses etapis proovib NSSM sündmust genereerida ja saata Ctrl+C. See meetod töötab hästi konsoolirakenduste või skriptide puhul, kuid ei ole rakendatav graafiliste rakenduste puhul;
Seejärel tuvastab NSSM kõik rakenduse loodud aknad ja saadab neile WM_CLOSE-teate, mis põhjustab rakenduse väljumise;
Kolmas samm on see, et NSSM arvutab kõik rakenduse loodud lõimed ja saadab neile WM_QUIT sõnumi, mis võetakse vastu, kui rakendusel on lõime sõnumite järjekord;
Viimase abinõuna võib NSSM kutsuda välja TerminateProcess() meetodi, sundides rakendust lõpetama.

On võimalik keelata mõned või isegi kõik meetodid, kuid erinevad meetodid töötavad erinevate rakenduste jaoks ja on soovitatav jätta kõik nii nagu on, et tagada rakenduse õige väljalülitamine.

Vaikimisi proovib NSSM teenuse kokkujooksmisel seda taaskäivitada. Vahekaardil „Väljumise toimingud” saate muuta automaatset toimingut, kui rakendus lõpetab ebatavalise töö, samuti saate määrata viivituse, enne kui rakendus automaatselt taaskäivitub.

Vahekaardil „Sisend/väljund (I/O)” saate määrata rakenduse sisendi/väljundi ümbersuunamise määratud faili.

Vahekaardil "Keskkond" saate määrata teenusele uusi keskkonnamuutujaid või alistada olemasolevad.

Samuti ei saa te kasutada graafilist kesta ja luua kohe teenust konsoolis järgmise käsuga:

nssm install notepad ″C:\Windows\system32\notepad.exe″

Teenuse juhtimine

Pärast teenuse loomist NSSM-i abil minge teenuste lisandmoodulisse ja leidke märkmikuteenus. Nagu näete, ei erine see välimuselt teistest teenustest, samuti saame selle käivitada, peatada või käivitusrežiimi muuta. Pange tähele, et nssm.exe on täitmisfailina loetletud.

Ja kui me läheme Task Manageri, näeme järgmist pilti: NSSM töötab põhi- (ema)protsessina, notepadi teenus töötab selle alamprotsessina ja Notepadi rakendus töötab juba selles alamprotsessis.

Teenuse eemaldamine

Teenuse eemaldamiseks sisestage käsk nssm remove notepad ja kinnitage selle eemaldamine. Ja sisestades käsu nssm remove notepad confirm , saate teha ilma kinnituseta.

Käivitage teenus interaktiivselt

Peamine erinevus kasutajarakenduse ja teenuse vahel seisneb selles, et pärast käivitamist võib rakendus nõuda töö jätkamiseks täiendavaid kasutajatoiminguid, näiteks nupu vajutamist või käsu sisestamist. Selleks peate saama sellele juurdepääsu, mida, nagu selgub, pole nii lihtne teha.

Teenuse interaktiivses režiimis käivitamiseks peate avama selle atribuudid teenuste lisandmoodulis ja vahekaardil „Sisselogimine” märkima ruut „Luba töölauaga suhtlemine”.

Ja siis algavad imed :) Interaktiivses režiimis käivitatud teenus avaneb isoleeritud seansis (seanss 0). Sellele seansile pääseb juurde ainult interaktiivsete teenuste tuvastamise teenuse (ui0detect) abil, mis jälgib interaktiivsete teenuste käivitamist arvutis ja väljastab hoiatuse. Operatsioonisüsteemis Windows 7\Server 2008 on see teenus vaikimisi aktiivne, kuid operatsioonisüsteemis Windows 8\Server 2012 on see keelatud ega ilmu teenuste graafilises lisandmoodulis (vähemalt mina seda sealt ei leidnud). Veelgi enam, kui leiate selle salapärase teenuse ja proovite seda käivitada, kuvatakse teile veateade.

Kuid tõsiasi on see, et selle käitamiseks peate lubama oma arvutis interaktiivsetel teenustel töötada. Seetõttu avage registriredaktor ja leidke jaotisest HKLM\System\CurrentControlSet\Control\Windows DWORD-tüüpi parameeter nimega NoInteractiveServices ja määrake selle väärtuseks 0 .

Seejärel avage PowerShelli konsool ja käivitage avastamisteenus käsuga:

Start-Service -Name ui0detect

Kui olete veendunud, et tuvastusteenus töötab, taaskäivitame märkmikuteenuse ja saame selle akna. Valige "Kuva sõnum"

ja leiame end nullseansist, milles meie rakendus töötab. Seejärel teostame sellega vajalikud toimingud ja pöördume tagasi.

See on huvitav lahendus rakenduste käitamiseks Windowsi teenustena. Mitte just kõige ilusam, aga oma nimega üsna kooskõlas :)


Windows NT teenus on spetsiaalne protsess, millel on ühtne liides Windows NT operatsioonisüsteemiga suhtlemiseks. Teenused jagunevad kahte tüüpi – Win32 teenused, mis suhtlevad operatsioonisüsteemiga Service Control Manageri (SCM) kaudu, ja draiverid, mis töötavad Windows NT seadmedraiveri protokolli kasutades. Selles artiklis käsitleme Win32 teenuseid ainult hiljem.

Teenuste rakendamine

Teenuse üks olulisemaid omadusi on mitteinteraktiivsus. Tüüpiline teenus töötab taustal tavakasutajale märkamatult. Seetõttu sobivad teenused kõige paremini järgmist tüüpi rakenduste juurutamiseks:

  • Serverid klient-server arhitektuuris (näiteks MS SQL, MS Exchange Server)
  • Võrguteenused Windows NT (server, tööjaam);
  • Serveri (funktsionaalsuse poolest) hajutatud rakenduste komponendid (näiteks kõikvõimalikud seireprogrammid).

Teenuste põhiomadused

Teenust eristab tavalisest Win32 rakendusest 3 peamist omadust. Vaatame igaüht neist.

Esiteks on võimalik teenus õigesti peatada (peatada). Kasutajal või muul standardmehhanisme kasutaval rakendusel on võimalus muuta teenuse olekut – teisaldada see töötavast olekust peatatud olekusse või isegi peatada selle töötamise. Sel juhul saab teenus enne oleku muutmist spetsiaalse teatise, tänu millele saab ta teha uude olekusse üleminekuks vajalikke toiminguid, näiteks vabastada hõivatud ressursse.

Teiseks võimalus teenust käivitada enne kasutaja registreerimist ja sellest tulenevalt võimalus töötada üldse ilma registreeritud kasutajata. Mis tahes teenust saab automaatselt käivitada operatsioonisüsteemi käivitumisel ja alustada tööd isegi enne, kui kasutaja süsteemi sisse logib.

Ja lõpuks, võime töötada suvalises turvakontekstis. Windows NT turbekontekst määratleb protsessi juurdepääsuõiguste kogumi erinevatele süsteemiobjektidele ja andmetele. Erinevalt tüüpilisest Win32 rakendusest, mis töötab alati süsteemi sisse logitud kasutaja turbekontekstis, saab teenuse puhul selle täitmise turvakonteksti eelnevalt kindlaks määrata. See tähendab, et teenusel võib olla oma juurdepääsuõiguste kogum süsteemiobjektidele eelnevalt määratletud ja seeläbi piirata oma tegevuste ulatust. Teenuste jaoks on olemas spetsiaalne vaiketurbekontekst, mida nimetatakse kohalikuks süsteemiks. Selles kontekstis töötaval teenusel on õigused ainult kohaliku arvuti ressurssidele. Kohaliku süsteemi õigustega ei saa teha ühtegi võrgutoimingut, kuna sellel kontekstil on mõtet ainult kohalikus arvutis ja teised võrgu arvutid seda ei tuvasta.

Teenuse koostoime teiste rakendustega

Iga rakendus, millel on asjakohased õigused, saab teenusega suhelda. Interaktsioon hõlmab ennekõike teenuse oleku muutmist, st selle ülekandmist ühte kolmest olekust - töötab (Start), peatatakse (Paus), peatub ja see toimub SCM-i taotluste esitamisega. Päringuid on kolme tüüpi - teenuste sõnumid (nende olekute fikseerimine), teenuse konfiguratsiooni muutmise või selle kohta teabe hankimisega seotud päringud ja rakenduste taotlused teenuse oleku muutmiseks.

Teenuse haldamiseks peate esmalt hankima selle käepideme, kasutades OpenService Win32 API funktsiooni. Funktsioon StartService käivitab teenuse. Vajadusel muudetakse teenuse olekut funktsiooni ControlService kutsumisega.

Teenuste andmebaas

Teave iga teenuse kohta salvestatakse registris - võtmes HKLM\SYSTEM\CurrentControlSet\Services\ServiceName. See sisaldab järgmist teavet:

  • Teenuse tüüp. Näitab, kas see rakendus rakendab ainult ühte teenust (eksklusiivne) või on neid rakenduses mitu. Eksklusiivne teenus võib toimida igas turbekontekstis. Sama rakenduse mitu teenust saavad töötada ainult kohaliku süsteemi kontekstis.
  • Käivitamise tüüp. Automaatne – teenus käivitub süsteemi käivitamisel. Nõudmisel – teenuse käivitab kasutaja käsitsi. Deaktiveeritud – teenust ei saa käivitada.
  • Käivitatava mooduli nimi (EXE-fail).
  • Käivitustellimus seoses muude teenustega. Mõnel juhul peab teenuse korrektseks toimimiseks töötama üks või mitu muud teenust. Sel juhul sisaldab register teavet enne seda alustatud teenuste kohta.
  • Teenuse täitmise turvakontekst (võrgu nimi ja parool). Vaikimisi on turbekontekst LocalSystem.

Rakendused, mis soovivad hankida teavet teenuse kohta või muuta teenuse sätteid, peavad sisuliselt muutma teavet teenuse registris andmebaasis. Seda saab teha vastavate Win32 API funktsioonide abil:

  • OpenSCManager, CreateService, OpenService, CloseServiceHandle – teenuse loomiseks (avamiseks);
  • QueryServiceConfig, QueryServiceObjectSecurity, EnumDependentServices, EnumServicesStatus – teenuse kohta teabe hankimiseks;
  • ChangeServiceConfig, SetServiceObjectSecurity, LockServiceDatabase, UnlockServiceDatabase, QueryServiceLockStatus – teenuse konfiguratsiooniteabe muutmiseks.

Teenuse sisemine struktuur.

Selleks, et see juhtuks, peab rakendus olema vastavalt struktureeritud, nimelt sisaldama teatud funktsioonide komplekti (C++ mõistes) teatud funktsionaalsusega. Vaatame lühidalt igaüks neist.

põhifunktsioon

Nagu teate, on põhifunktsiooniks mis tahes Win32 konsoolirakenduse sisenemispunkt. Kui teenus käivitub, hakkab esmalt täitma selle funktsiooni kood. 30 sekundi jooksul pärast käivitamist peab põhifunktsioon helistama StartServiceCtrlDispatcherile, et luua ühendus rakenduse ja SCM-i vahel. Kogu suhtlus antud rakenduse mis tahes teenuse ja SCM-i vahel toimub funktsiooni StartServiceCtrlDispatcher raames, mis lõpeb alles pärast seda, kui kõik rakenduses olevad teenused on peatunud.

ServiceMain funktsioon

Lisaks kogu protsessi hõlmavale sisestuspunktile on iga rakenduses rakendatud teenuse jaoks eraldi sisenemispunkt. Teenuse sisenemispunktideks olevate funktsioonide nimed (lihtsuse huvides nimetagem neid kõiki ühtemoodi - ServiceMain) edastatakse StartServiceCtrlDispatcheri kutsumisel SCM-ile ühes parameetris. Iga teenuse käivitamisel luuakse ServiceMaini käivitamiseks eraldi lõim.

Pärast kontrolli kättesaamist peab ServiceMain esmalt registreerima rakenduse iga teenuse jaoks teenusepäringute töötleja, funktsiooni Handler. Tavaliselt järgneb sellele ServiceMainis mõned toimingud teenuse lähtestamiseks – mälu eraldamine, andmete lugemine jne. Nende toimingutega peavad kaasnema SCM-i teatised, et teenus on alles käivitumas ja tõrkeid pole esinenud. Teavitused saadetakse funktsiooni SetServiceStatus kõnede abil. Kõik kõned, välja arvatud viimane, peavad olema parameetriga SERVICE_START_PENDING ja viimane kõne peab olema parameetriga SERVICE_RUNNING. Kõnede sageduse määrab teenuse arendaja järgmise tingimuse alusel: kahe kõrvuti asetseva SetServiceStatus kõne vahelise ajaintervalli kestus ei tohi ületada kahest kõnest esimese kõne ajal SCM-ile edastatud parameetri dwWaitHint väärtust. Vastasel juhul peatab SCM, kui ei saa õigel ajal järgmist teadet, teenuse jõuga. See meetod võimaldab teil vältida teenuse käivitamise olukorda teatud tõrgete ilmnemise tagajärjel (pidage meeles, et teenused on tavaliselt mitteinteraktiivsed ja neid saab käivitada ka kasutaja puudumisel). Tavaline praktika on see, et SCM-i teavitatakse pärast järgmise lähtestamisetapi lõpetamist.

Käitleja funktsioon

Nagu eespool mainitud, on Handler tagasihelistamisfunktsiooni prototüüp, teenusepäringute töötleja, mis on rakenduse iga teenuse jaoks unikaalne. Handler kutsutakse välja siis, kui teenus saab päringu (start, pause, resume, stop, hetkeseisu teade) ja teeb vastavalt päringule vajalikud toimingud, misjärel teatab uuest olekust SCM-ile.

Eraldi tuleb ära märkida üks taotlus – süsteemi väljalülitamisel saadud päring (Shutdown). See taotlus annab märku vajadusest initsialiseerida ja lõpetada. Microsoft ütleb, et igale teenusele antakse 20 sekundit enne sulgemist. Testid on aga näidanud, et see tingimus ei ole alati täidetud ja teenus on sunnitud enne selle aja möödumist peatama.

Teenuse turvasüsteem

Iga teenustega seotud toiming eeldab, et rakendusel on vastavad õigused. Kõigil rakendustel on õigus SCM-iga ühenduse loomiseks, teenuste loetlemiseks ja teenuste andmebaasi blokeerimise kontrollimiseks. Ainult administraatoriõigustega rakendused saavad süsteemis uut teenust registreerida või teenuste andmebaasi blokeerida.

Igal teenusel on turbedeskriptor, mis kirjeldab, millistel kasutajatel on millise toimingu õigused. Vaikimisi:

  • Kõigil kasutajatel on SERVICE_QUERY_CONFIG, SERVICE_QUERY_STATUS, SERVICE_ENUMERATE_DEPENDENTS, SERVICE_INTERROGATE ja SERVICE_USER_DEFINED_CONTROL õigused;
  • Võimsate kasutajate gruppi kuuluvatel kasutajatel ja LocalSystem'i kontol on lisaks õigused SERVICE_START, SERVICE_PAUSE_CONTINUE ja SERVICE_STOP;
  • Administraatorite ja süsteemioperaatorite rühma kuuluvatel kasutajatel on SERVICE_ALL_ACCESS õigus.

Teenused ja interaktiivsus

Vaikimisi saavad interaktiivsed teenused töötada ainult kohaliku süsteemi turbekontekstis. Selle põhjuseks on Windows NT monitori ekraanil kuvamise iseärasused, kus on näiteks selline objekt nagu "Töölaud", millega töötamiseks peavad teil olema asjakohased juurdepääsuõigused, mis on suvaline konto peale LocalSystem. ei pruugi olla. Vaatamata asjaolule, et enamikul juhtudel pole see piirang oluline, on mõnikord vaja luua teenus, mis kuvaks teavet monitori ekraanil ja samal ajal käivitataks muus turbekontekstis kui LocalSystem, näiteks rakendusserveri komponent rakenduste käivitamiseks kaugarvutis.

Koodilõik alates . illustreerib seda võimalust.

Selles fragmendis kuvab teenus vastusena rakenduse kliendipoole poolt RPC tagajärjena saadetud päringule monitori ekraanil tekstisõnumi.

Näidisteenus (võtmelõigud)

Vaatame näidet Windows NT teenust rakendava rakenduse võtmefragmentidest C++ keeles. Selguse huvides on koodi ebaolulised osad välja jäetud.

põhifunktsioon

Põhifunktsiooni kood on näidatud jaotises B.

ServiceMain funktsioon

ServiceMainis sisalduva koodi eripäraks on see, et sageli on võimatu ette ennustada konkreetse toimingu täitmisaega, eriti kui arvestada, et selle täitmine toimub ennetava multitegumtöötlusega operatsioonisüsteemis. Kui toiming võtab kauem aega kui kõneparameetris SetServiceStatus määratud ajavahemik, ei saa teenus õigel ajal järgmist teatist saata, mistõttu SCM peatab oma töö. Potentsiaalsete toimingute näideteks on suurte ajalõppudega helistamine võrgufunktsioonidele või suure hulga teabe samaaegne lugemine aeglasest andmekandjast. Lisaks on see lähenemine teenuse silumisel täiesti rakendamatu, kuna programmi käivitamisega siluris kaasnevad pikad pausid, mis on arendajale vajalikud.

Selle probleemi lahendamiseks tuleks kõik SCM-iga suhtlevad toimingud läbi viia eraldi lõimes, sõltumata lähtestamisfaasis toimuvatest toimingutest.

B näitab algoritmi teenuse õigeks käivitamiseks abikeerme abil.

Käitleja funktsioon

B näitab Handler funktsiooni ja abikeermete koodi. Päringute "Stop" ja "Shutdown" puhul kasutatakse teenuse õigeks peatamiseks algoritmi, mis sarnaneb teenuse käivitamisel kasutatavale algoritmile, selle ainsa erinevusega, et parameetri SERVICE_START_PENDING asemel edastatakse parameeter SERVICE_STOP_PENDING parameetrile SetserviceStatus ja selle asemel SERVICE_RUNNING-st – SERVICE_STOPPED.

Ideaalis peaksid seda lähenemisviisi kasutama ka päringud "Paus" ja "Jätka". Uudishimulik lugeja saab selle nende näidete põhjal hõlpsasti rakendada.

Järeldus

Kokkuvõtteks tahame märkida, et teenuste areng ei muutunud Windows NT 2000-le üleminekuga. Teenused on jätkuvalt Windowsi platvormi tarkvara oluline osa, pakkudes arendajatele laia valikut võimalusi.


// Funktsioon, mis sarnaneb MessageBox Win32 API-ga int ServerMessageBox(RPC_BINDING_HANDLE h, LPSTR lpszText, LPSTR lpszTitle, UINT fuStyle) ( DWORD dwThreadId; HWINSTA hwinstaSave; HDESK hdeskSave int hwintKESTA; HWINtSerista; HWINtSerista; s "Aken jaam " ja "Desktop". GetDesktopWindow(); hwinstaSave = GetProcessWindowStation(); dwThreadId = GetCurrentThreadId(); hdeskSave = GetThreadDesktop(dwThreadId); // Muutke turbekontekst sellele RPC-le ja //, millele // mis helistab saada juurdepääs kasutajale // objektidele "Window station" ja "Desktop" SetProcessWindowStation( hwinstaUser); ) SetThreadDesktop(hdeskUser); // Tavalise tekstiakna kuvamine. tulemus = MessageBox(NULL, lpszText, lpszTitle, fuStyle); // Salvestatud objektide taastamine // "Window station" ja "Desktop". SetThreadDesktop(hdeskSave); SetProcessWindowStation(hwinstaSave); CloseDesktop(hdeskUser); CloseWindowStation(hwinstaUser); tagastada tulemus; ) void main() ( SERVICE_TABLE_ENTRY steTable = ((SERVICENAME, ServiceMain), (NULL, NULL) ); // Loo ühendus SCM-iga. Selle funktsiooni sees // päringuid võetakse vastu ja saadetakse. StartServiceCtrlDispatcher(steTable); ) void WINAPI ServiceMain (DWORD dwArgc, LPSTR *psArgv) ( // Registreerige päringute töötleja kohe. hSS = RegisterServiceCtrlHandler(SERVICENAME, ServiceHandler); sStatus.dwCheckPoint = 0; sStatus.dwControlsAccepted = SERVICE_ACCEPT_ACTINUS.d wServiceType = SERVICE_WIN32_OWN_PROCESS sStatus.dwWaitHint = 0; // sekundis, et teenus on initsialiseerimisel // Lõime sünkroonimiseks luuakse sündmus // Pärast seda käivitatakse töölõng, // mille jaoks luuakse ka sündmus. hSendStartPending = CreateEvent(NULL, TRUE, FALSE, NULL); HANDLE hSendStartThread; DWORD dwThreadId; hSendStartThread = CreateThread(NULL, 0, SendStartPending, NULL, 0, &dwThreadId); //Siin tehakse kogu teenuse lähtestamine. InitService(); SetEvent(hSendStartPending); if(WaitForSingleObject(hSendStartThread, 2000) != WAIT_OBJECT_0) ( TerminateThread(hSendStartThread, 0); ) CloseHandle(hSendStartPending); CloseHandle(hSendStartThread); hWork = CreateEvent(NULL, TRUE, FALSE, NULL); hServiceThread = CreateThread(NULL, 0, ServiceFunc, 0, 0, &dwThreadId); sStatus.dwCurrentState = TEENUSE_TÖÖTAMINE; SetServiceStatus(hSS, &sStatus); ) // Lõimefunktsioon, mis saadab SCM-ile teateid // iga sekund, kui initsialiseerimisprotsess on pooleli. Funktsioon // lõpeb, kui on määratud sündmus hSendStartPending //. DWORD WINAPI SendStartPending(LPVOID) ( sStatus.dwCheckPoint = 0; sStatus.dwCurrentState = SERVICE_START_PENDING; sStatus.dwWaitHint = 2000; // "Sleep" 1 sekundiks. Kui pärast 1 sekundit pole hdingi signaal // sisestatud // olek (teenuse initsialiseerimine ei ole // lõppenud), saatke järgmine teade, // määrake maksimaalseks ajavahemikuks // 2 sekundiks, nii et // järgmise teateni jääks aega (tõene) ( SetServiceStatus(hSS, &sStatus) .dwCheckPoint++; Andmete lugemine, // mälu eraldamine jne. void InitService() ( ... ) // Teenuse koodi sisaldav funktsioon. DWORD WINAPI ServiceFunc(LPVOID) ( while (true) ( ​​if (!bPause) ( // See sisaldab koodi, mis tavaliselt // sooritab mingisuguseid tsüklilisi toiminguid... ) if (WaitForSingleObject(hWork, 1000)!=WAIT_TIMEOUT ) break ) return 0; TRUE, FALSE, NULL); hSendStopThread = CreateThread(NULL, 0, SendStopPending, NULL, 0, & dwThreadId) if (WaitForSingleObject(hServiceThread, 1000)! SetEvent(hSendStopPending) ; CloseHandle(hServiceThread); murda; case SERVICE_CONTROL_PAUSE: bPaus = tõene; sStatus.dwCurrentState = TEENUS_PAUSED; SetServiceStatus(hSS, &sStatus); murda; juhtum SERVICE_CONTROL_CONTINUE: bPaus = tõene; sStatus.dwCurrentState = TEENUSE_TÖÖTAMINE; SetServiceStatus(hSS, &sStatus); murda; juhtum SERVICE_CONTROL_INTERROGATE: SetServiceStatus(hSS, &sStatus); murda; vaikimisi: SetServiceStatus(hSS, &sStatus); murda; ) ) // Teenuse peatamiseks lõime funktsiooniga SendStartPending sarnane lõime //. DWORD WINAPI SendStopPending(LPVOID) ( sStatus.dwCheckPoint = 0; sStatus.dwCurrentState = SERVICE_STOP_PENDING; sStatus.dwWaitHint = 2000; while (true) ( ​​​​SetServiceStatus(Scketstusw) aitForSingleObject) (hSendStopPending, 1000 ) = WAIT_TIMEOUT) sStatus.dwCheckPoint = 0;