Bilgisayarı açıp şifreni yazmaya fırsat bulamadan, arka planda bir veritabanı motoru çoktan bağlantı bekliyor, antivirüs de diski izliyor olabilir. Ortada tıklanan tek bir şey yok. Bu işlerin çoğunu Windows Service yürütür. Peki Windows Service nedir?
Windows için yazılım geliştiriyorsan er ya da geç bir servisle karşılaşırsın, bazen de kendin yazman gerekir. Bu yazıda Windows Service’in ne olduğunu, Service Control Manager tarafından nasıl çalıştırıldığını, nerelerde kullanıldığını, nasıl yönetildiğini ve .NET Worker Service ile kendi servisini nasıl yazacağını anlatıyorum.
Windows Service nedir
Windows Service, arka planda uzun süre çalışan, arayüzü olmayan ve çalışması için kimsenin oturum açmasına gerek duymayan bir programdır. Microsoft dokümantasyonu servisleri, kullanıcı oturum açmış olsun ya da olmasın çalışan uygulamalar olarak tanımlar. Linux’tan geliyorsan en yakın akrabası daemon’dır.
Normal bir masaüstü uygulamasından üç noktada ayrılır.
- Arayüzü yoktur. Pencere ya da mesaj kutusu gösteremez, dış dünyayla log, Event Log, ağ portları ve dosyalar üzerinden konuşur.
- Ömrü kullanıcı oturumuna değil makineye bağlıdır. Açılışta başlayabilir, herkes oturumu kapattıktan sonra da çalışmaya devam eder.
- Standart bir arayüzle yönetilir. Kapat düğmesi yerine işletim sisteminden gelen başlat, durdur, duraklat ve devam ettir isteklerini dinler.
Servisler ayrıca Session 0 adı verilen, kullanıcıların çalıştığı etkileşimli oturumlardan ayrı bir oturumda çalışır. Bir servisin kullanıcının masaüstüne pencere açamamasının sebebi bu yalıtımdır.
Türkçe Windows’ta services.msc penceresi “Hizmetler” başlığıyla açılır, yani servis ve hizmet aynı şeyi anlatır. Bu yazıda yaygın kullanımı nedeniyle servis diyorum.
Windows Service nasıl çalışır
Her şey Service Control Manager (SCM) etrafında döner. services.exe içinde yaşayan bu sistem süreci, kurulu servislerin veritabanını registry’de HKLM\SYSTEM\CurrentControlSet\Services anahtarı altında tutar. Otomatik başlaması gereken servisleri başlatır, durumlarını izler ve kendisine gelen kontrol isteklerini servislere iletir.
SCM erken devreye girer ve oturum açma ekranı gelmeden önce çalışmaya başlar. Önce bu registry anahtarını tarar, kendi listesini oluşturur ve otomatik servisleri ayağa kaldırır. Bir servisin kimse oturum açmadan önce çalışıyor olabilmesi bu yüzdendir.
Servis, sıradan bir çalıştırılabilir dosya değildir. SCM’nin kendisini çağırabildiği küçük bir programatik arayüz uygular. Başlat, durdur ve duraklat sinyalleri servise bu arayüz üzerinden ulaşır. services.msc, sc.exe ve net start gibi araçlar servisle doğrudan konuşmaz. İstekleri SCM’ye iletir (yerel makinede ya da uzak bir makineye RPC ile), SCM de servise aktarır.
Başlangıç türleri
- Automatic (Otomatik) servisi sistem açılırken başlatır.
- Automatic (Delayed Start) (Otomatik, Gecikmeli Başlatma) servisi açılış tamamlandıktan kısa süre sonra başlatır. Windows Vista ile eklendi ve kritik olmayan servislerin açılışı uzatmasını önler.
- Manual (El ile) servisi yalnızca biri istediğinde başlatır. Bu bir yönetici, başka bir program ya da zamanlanmış görev olabilir.
- Disabled (Devre Dışı) servisin hiç başlamasını engeller.
Servis hesapları
Her servis bir hesap altında çalışır ve neye erişebileceğini bu hesap belirler. Yerleşik seçenekler şunlardır.
- LocalSystem makinede geniş yetkilere sahiptir ve ağda bilgisayarın kimliğiyle görünür.
- LocalService makinede yetkisiz bir kullanıcı gibi davranır ve uzak sunuculara anonim kimlik bilgisi sunar.
- NetworkService yerelde yetkisizdir ve uzak sunuculara bilgisayarın kimlik bilgilerini sunar.
Bunların dışında, parola yönetimini Windows’a bırakmak isteyenler için sanal hesaplar ve yönetilen servis hesapları (MSA ve gMSA) vardır. Kural basittir, işi görebilen en az yetkili hesap seçilir. Her şeyi LocalSystem ile çalıştırmak kolay yoldur ve en riskli olanıdır.
Hata sonrası yeniden başlatma
SCM, çöken bir servisi yapılandırdığın kurtarma seçeneklerine göre yeniden başlatabilir. Bir servisin, elle başlatılmış bir programa göre en büyük pratik avantajlarından biri budur.
Windows Service nerelerde kullanılır
Başında kimse olmadan erişilebilir kalması gereken her iş aday olabilir. Sık görülen örnekler şunlardır.
- SQL Server gibi veritabanı motorları bağlantıları gece gündüz dinler.
- Web sunucuları ve uygulama barındırıcıları, yani IIS ve IIS olmadan barındırılan ASP.NET Core uygulamaları.
- Antivirüs ve endpoint ajanları gibi dosya ve süreçleri sürekli izleyen güvenlik yazılımları.
- Metrik toplayan ya da veri gönderen izleme, loglama ve yedekleme ajanları.
- Gelen işleri işleyen kuyruk dinleyicileri ve arka plan işçileri.
- Bir klasör değişince tepki veren dosya izleyiciler ve senkronizasyon araçları.
- Windows Update, Print Spooler ve Task Scheduler gibi işletim sistemi bileşenleri.
Sonuncusu üzerinde durmaya değer. Zamanlanmış görevleri Task Scheduler adında bir Windows servisi başlatır. Yani servis yazmaktan kaçınmak için kullanılan şeyin kendisi de bir servistir.
Uygulama geliştirici için kalıp genelde aynıdır. API’yi yoklamak, kuyruğu boşaltmak ya da rapor üretmek gibi oturum açmış bir kullanıcıya bağlı olmaması gereken iş bir servise taşınır, ayakta tutma işi de işletim sistemine bırakılır.
Windows Service nerelerde çalışır
Servisler Windows’un her güncel sürümünde bulunur. Windows Server’da iş yüklerinin çoğunun bel kemiğidir. Windows 10 ve 11’de sistemin kendi altyapısını ve kurduğun arka plan ajanlarını yürütür. Bulutta çalışan Windows sanal makineleri de aynı şekilde davranır. Şirket içi bir sunucu için yazılmış servis bu yüzden genelde Azure ya da AWS üzerindeki bir sanal makineye kod değişikliği olmadan taşınır.
Container tarafı farklıdır. Container içinde uygulamayı düz bir ön plan süreci olarak çalıştırmak ve hata anında yeniden başlatma işini orkestratöre bırakmak yaygın yaklaşımdır. Orada Windows Service nadiren doğru sarmalayıcı olur.
Kod tarafında .NET kullanıyorsan Worker Service modeli tek kod tabanıyla iki dünyayı da hedeflemene izin verir. AddWindowsService çağrısı uygulamayı Windows servisine, AddSystemd çağrısı ise Linux’ta systemd daemon’ına dönüştürür. Uygulamayı servis yöneticisinin dışında başlattığında ise normal bir konsol süreci olarak çalışır, bu da yerelde hata ayıklamayı kolaylaştırır.
Servisleri yönetmek
Günlük işte üç araç kullanılır. Hizmetler penceresi (services.msc) her servisi durumu, başlangıç türü ve hesabıyla listeler. sc.exe komut satırı aracı doğrudan SCM ile konuşur. PowerShell ise Get-Service, Start-Service, Stop-Service ve Restart-Service cmdlet’lerini sunar.
Get-Service -Name "My Worker" Stop-Service -Name "My Worker" Start-Service -Name "My Worker" sc.exe query "My Worker" sc.exe config "My Worker" start= delayed-auto
İki ayrıntı sık takılma sebebidir. İlki, sc.exe her seçenekte eşittir işaretinden sonra boşluk bekler. start= delayed-auto çalışır, start=delayed-auto ise reddedilir. İkincisi, servisleri yönetmek için yükseltilmiş (yönetici) bir oturum gerekir, çünkü normal kullanıcılar varsayılan olarak servisleri kontrol edemez.
Servisler genelde Windows Event Log’a yazar. Bir servis sorun çıkardığında bakılacak ilk yer Event Viewer içindeki Windows Logs altında Application kaydıdır. Sistem servislerine dokunurken de dikkatli olmak gerekir. Yanlış servisi devre dışı bırakmak ağ bağlantısını, güncellemeleri ya da Store’u bozabilir.
Servis, zamanlanmış görev ve masaüstü uygulaması
İş ayakta kalmalıysa servis, çalışıp bitmeliyse zamanlanmış görev, kullanıcı yönetiyorsa masaüstü uygulaması seçilir.
| Özellik | Windows Service | Zamanlanmış görev | Masaüstü uygulaması |
|---|---|---|---|
| Başlangıç | Açılışta ya da istek üzerine | Belirli bir saatte ya da olay anında | Kullanıcı açınca |
| Çalışma biçimi | Durdurulana kadar sürekli | Çalışır, biter, kapanır | Kullanıcı kapatana kadar |
| Arayüz | Yok | Pratikte yok | Var |
| Oturum | Session 0 | Görev ayarına göre değişir | Kullanıcının oturumu |
| Kontrol | Başlat, durdur, duraklat, hatada otomatik yeniden başlatma | Tetikleyiciler ve yeniden deneme ayarları | Kullanıcı |
| En uygun iş | Sürekli açık arka plan işi | Periyodik bakım işleri | Etkileşimli iş |
Servis ayrıca işini düzgünce bitirip kapanabilmesi için bir durdurma sinyali alır ve Event Log’da doğal bir yere sahiptir, zamanlanmış görev bunları sunmaz. İş “gece 2’de çalış ve çık” şeklindeyse zamanlanmış görev daha basittir. İş “ayakta kal ve tepki ver” şeklindeyse servis yazılır.
.NET ile Windows Service yazmak
Modern .NET’te servis yazmanın yolu Worker Service şablonudur. Generic host ve BackgroundService üzerine kuruludur, tek bir NuGet paketi onu gerçek bir Windows servisine dönüştürür.
Projeyi oluşturmak
dotnet new worker --name MyWorker cd MyWorker dotnet package add Microsoft.Extensions.Hosting.WindowsServices
SDK 9 ve öncesinde son komut yerine dotnet add package kullanılır.
Host’u bağlamak
using MyWorker;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddWindowsService(options =>
{
options.ServiceName = "My Worker";
});
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
AddWindowsService, host’un SCM’den gelen başlat ve durdur sinyallerini dinlemesini sağlar. Servis adı, services.msc penceresinde görünen addır. Servis yöneticisinin dışında aynı uygulama konsol süreci olarak çalışır, bu yüzden geliştirirken dotnet run yine işe yarar.
Worker’ı yazmak
namespace MyWorker;
public sealed class Worker(ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogWarning("Worker çalışıyor ({Time})", DateTimeOffset.Now);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
catch (OperationCanceledException)
{
// Servis durdurulunca bu durum beklenir.
}
catch (Exception ex)
{
logger.LogError(ex, "{Message}", ex.Message);
// Sıfırdan farklı çıkış kodu, SCM'nin kurtarma ayarlarını uygulamasını sağlar.
Environment.Exit(1);
}
}
}
Döngü, durdurma belirteci iptal edilene kadar çalışır, servis durdurulduğunda olan da budur. Burada uyarı seviyesinde log yazmamın tek sebebi, Event Log sağlayıcısının varsayılan olarak daha düşük seviyeleri filtrelemesidir. Gerçek bir serviste seviye appsettings.json içinden ayarlanır.
Environment.Exit(1) çağrısı önemlidir. .NET 6’dan beri bir BackgroundService içindeki yakalanmamış istisna host’u temiz biçimde durdurur ve temiz durma, SCM’nin servisi yeniden başlatmayacağı anlamına gelir. Sıfırdan farklı kodla çıkmak hatayı çökme gibi gösterir ve kurtarma seçenekleri devreye girer.
Yayınlamak ve kurmak
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o C:\Services\MyWorker sc.exe create "My Worker" binpath= "C:\Services\MyWorker\MyWorker.exe" sc.exe failure "My Worker" reset= 86400 actions= restart/60000/restart/60000/restart/60000 sc.exe start "My Worker"
Kendi içinde çalışan tek dosyalı bir çalıştırılabilir dosya, SCM’nin takılabileceği gevşek bağımlılık bırakmadığı için en az hata çıkaran dağıtım şeklidir. failure satırı ilk üç hatanın her birinde servisi 60 saniye sonra yeniden başlatır ve hata sayacını bir gün sonra sıfırlar. Komutlar yönetici olarak açılmış PowerShell’de çalıştırılır.
Varsayılan olarak servis LocalSystem ile çalışır. Demo dışındaki her kurulum için düşük yetkili ayrı bir hesap oluşturulur ve sc.exe config ya da services.msc içindeki Oturum Aç sekmesiyle atanır. Servisi kaldırmak için önce durdurulur, sonra sc.exe delete "My Worker" çalıştırılır. Hâlâ çalışan bir servis hemen silinmez.
Sonuç
Windows Service, Service Control Manager’ın senin yerine başlattığı, durdurduğu ve gerekirse yeniden başlattığı, hiçbir kullanıcı oturumuna bağlı olmayan bir arka plan programıdır. Veritabanları, ajanlar, kuyruk dinleyicileri ve başında kimse yokken orada olması gereken her iş için doğru yerdir. Başlangıç türlerini ve hesapları öğrenip her servise gereken en düşük yetkiyi verdiğinde, kurtarma ayarlarını da yaptığında arka plan işlerin yeniden başlatmalara ve çökmelere kendi kendine dayanır.
Mesele .NET’e gelince giriş maliyeti de düşüktür. Bir şablon, bir NuGet paketi ve birkaç sc.exe komutuyla üretime yakın bir servis ortaya çıkar.
Tüm projelerim ve üzerinde çalıştığım konuları incelemek istersen https://hub.barisgunduz.com/ adresini ziyaret edebilirsin.
Kaynaklar
- Create Windows Service using BackgroundService, Microsoft Learn
- Host ASP.NET Core in a Windows Service, Microsoft Learn
- Service Control Manager, Microsoft Learn
- How to specify the security context for services, Microsoft Learn
- Services Overview, Windows 2000 Scripting Guide, Microsoft TechNet
- .NET Core Workers as Windows Services, .NET Blog
- Scheduling One-time and Recurring Tasks, O’Reilly
- Scheduled Task vs Windows Service, Core Technologies