Gereksinimler ve Ön Hazırlık
Windows servisi geliştirmek için sisteminizde aşağıdaki araçların yüklü olması gerekmektedir. Bu araçlar, uygulamanızın derlenmesi ve yönetilmesi için temel teşkil eder:
- Visual Studio 2022 (17.8 veya üzeri) veya VS Code.
- .NET 8.0 veya .NET 9.0 SDK.
- Windows işletim sistemi (Geliştirme ve test için).
- Windows Service yönetimi için yönetici yetkileri (Administrator rights).
Projeye başlamadan önce, Windows üzerinde servisleri yönetmek için kullanılan sc.exe komut satırı aracı hakkında temel bilgi sahibi olmanız, hata ayıklama süreçlerinizi hızlandıracaktır.
Worker Service Projesi Oluşturma
Yeni bir Worker Service projesi oluşturmak, arka plan görevleri için en optimize yoldur. Bu yapı, IHostedService arayüzünü kullanarak uygulamanın yaşam döngüsünü yönetir.
dotnet new worker -n ArkaPlanServisim
cd ArkaPlanServisim
dotnet add package Microsoft.Extensions.Hosting.WindowsServices
Yukarıdaki komutlar, projenin temel iskeletini oluşturur ve Windows servis entegrasyonu için gerekli olan NuGet paketini projenize dahil eder. Microsoft.Extensions.Hosting.WindowsServices paketi, uygulamanızın bir servis olarak çalışmasını sağlayan kritik genişletme metodlarını içerir.
Program.cs Dosyasının Yapılandırılması
Servisinizin Windows ortamında bir servis olarak tanınması için Program.cs dosyasında küçük bir değişiklik yapmanız gerekir. Bu adım, uygulamanın konsol uygulaması mı yoksa servis mi olduğunu ayırt etmesini sağlar.
using ArkaPlanServisim;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService();
// Windows servisi desteğini etkinleştir
builder.Services.AddWindowsService(options =>
{
options.ServiceName = "OzelArkaPlanServisi";
});
IHost host = builder.Build();
host.Run();
Burada AddWindowsService metodu, uygulamanın Windows Service Control Manager (SCM) ile iletişim kurmasını sağlar. ServiceName parametresi, Windows Hizmetler listesinde görünecek olan benzersiz isimdir.
Worker Sınıfını Kodlama
Worker.cs dosyası, servisin asıl iş mantığının (business logic) çalıştığı yerdir. ExecuteAsync metodu, servis başladığında otomatik olarak tetiklenir.
public class Worker : BackgroundService
{
private readonly ILogger _logger;
public Worker(ILogger logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Servis çalışıyor: {time}", DateTimeOffset.Now);
// Burada iş mantığınızı çalıştırın
await Task.Delay(10000, stoppingToken); // 10 saniyede bir çalışır
}
}
}
Bu kod bloğu, servisin her 10 saniyede bir log kaydı oluşturmasını sağlar. stoppingToken kullanımı, servis durdurulmak istendiğinde döngünün güvenli bir şekilde sonlandırılması için hayati önem taşır.
Servisi Windows'a Kaydetme ve Başlatma
Uygulamanızı bir servis olarak sisteme yüklemek için yönetici olarak çalıştırılan bir komut istemi (CMD) kullanmanız gerekir. Aşağıdaki komut, uygulamanızı sistem servisi olarak kaydeder.
sc create OzelArkaPlanServisi binPath="C:\Yol\Dizin\ArkaPlanServisim.exe"
sc start OzelArkaPlanServisi
binPath kısmına derlenmiş .exe dosyanızın tam yolunu yazmalısınız. Servisi durdurmak için sc stop OzelArkaPlanServisi, tamamen kaldırmak için ise sc delete OzelArkaPlanServisi komutlarını kullanabilirsiniz.
Karşılaştırma: Windows Servisi Yöntemleri
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Worker Service | Modern, Cross-platform, Kolay test | Bağımlılık yönetimi gerektirir |
| Legacy ServiceBase | Eski sistemlere tam uyum | Hata ayıklaması zor, karmaşık |
Kritik Güvenlik Uyarısı: Windows servisleri SYSTEM veya LocalService yetkileriyle çalışır. Servisinizin okuduğu veya yazdığı dosyaların yetkilendirmelerini (ACL) dikkatli yapılandırın. Asla servis içinde hard-coded (kod içine gömülü) parola veya hassas veri saklamayın; bunun yerine Windows Certificate Store veya Azure Key Vault gibi güvenli yöntemleri tercih edin.
Sıkça Sorulan Sorular
Servisim neden başlamıyor?
Genellikle dosya yolu hataları veya eksik yetkilendirmelerden kaynaklanır. Windows Olay Görüntüleyicisi (Event Viewer) üzerinden "Windows Logs > Application" kısmına giderek hata kodunu inceleyebilirsiniz.
Servis içinde kullanıcı arayüzü (UI) açabilir miyim?
Hayır, Windows servisleri "Session 0"da çalışır ve etkileşimli kullanıcı arayüzü göstermeleri güvenlik nedeniyle engellenmiştir. UI gerektiren görevler için ayrı bir uygulama geliştirip servis ile haberleştirmeniz gerekir.
Servisi nasıl debug ederim?
Servisi yüklemeden önce Program.cs içerisinde if (Debugger.IsAttached) kontrolü yaparak uygulamayı bir konsol uygulaması gibi çalıştırıp adım adım hata ayıklayabilirsiniz.
Servis durdurulduğunda işleri nasıl tamamlarım?
ExecuteAsync içerisinde stoppingToken.IsCancellationRequested kontrolünü yaparak, servis durdurulma sinyali aldığında temizleme işlemlerini (veritabanı bağlantısını kapatma vb.) gerçekleştirebilirsiniz.
Servisin otomatik başlamasını nasıl sağlarım?
sc config OzelArkaPlanServisi start=auto komutunu kullanarak servisin bilgisayar açıldığında otomatik başlamasını yapılandırabilirsiniz.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (Production) kullanmadan önce hata yönetimi (try-catch blokları), loglama (Serilog vb.) ve güvenlik denetimlerini mutlaka uygulayın. Yazılımın kararlılığından geliştirici sorumludur.
Windows Servislerinde Performans Optimizasyonu ve Kaynak Yönetimi
Arka planda sürekli çalışan servislerde en büyük risk, sistem kaynaklarının (RAM ve CPU) zamanla tükenmesidir. Özellikle döngüsel işlemlerde bellek sızıntılarını (memory leak) önlemek ve sistemin yanıt verebilirliğini korumak için bazı kritik stratejiler izlemelisiniz.
Zamanlanmış Görevler İçin PeriodicTimer Kullanımı
Eski yöntemlerde kullanılan Thread.Sleep veya Task.Delay yöntemleri, servisin durdurulma sinyallerine (cancellation token) anında yanıt vermesini zorlaştırabilir. .NET 6 ve sonrasında gelen PeriodicTimer, zamanlanmış görevler için çok daha verimli bir mekanizma sunar.
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// 5 saniyelik periyotlarla çalışır
using PeriodicTimer timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
while (!stoppingToken.IsCancellationRequested && await timer.WaitForNextTickAsync(stoppingToken))
{
try
{
// İş mantığınız buraya gelecek
await DoWorkAsync();
}
catch (Exception ex)
{
// Hata yönetimi loglanmalı
_logger.LogError(ex, "İşlem sırasında hata oluştu.");
}
}
}
Bellek Yönetimi ve Garbage Collector İpuçları
Servisiniz büyük veri setleriyle çalışıyorsa, nesnelerin kapsamını (scope) doğru yönetmek hayati önem taşır. IServiceScopeFactory kullanarak her döngüde yeni bir scope oluşturmak, veritabanı bağlamları (DbContext) gibi kaynakların işlem bittikten sonra serbest bırakılmasını sağlar.
- Scope Yönetimi: Servis içinde
usingblokları kullanarakIServiceScopeoluşturun. - Büyük Nesneler: Çok büyük listelerle çalışıyorsanız
IEnumerableveyield returnkullanarak belleği optimize edin. - Loglama Seviyesi: Üretim ortamında
DebugveyaTraceloglarını kapatarak I/O yükünü azaltın.
Servis Dağıtımı (Deployment) ve İzleme Stratejileri
Servisiniz geliştirme ortamında sorunsuz çalışsa bile, sunucu ortamında "sessizce" başarısız olabilir. Bu yüzden servislerinizi dışarıdan izlenebilir hale getirmek profesyonel bir gerekliliktir.
Event Log ve Serilog Entegrasyonu
Windows Servisleri için en iyi izleme yöntemi, Windows Olay Görüntüleyicisi'ne (Event Viewer) veya merkezi bir log sunucusuna yazmaktır. Serilog.Sinks.EventLog paketini kullanarak servis hatalarını doğrudan Windows loglarına aktarabilirsiniz.
// Program.cs içerisine eklenmesi gereken yapılandırma
builder.Logging.AddEventLog(settings =>
{
settings.SourceName = "MyCustomService";
settings.LogName = "Application";
});
Servis Durumunu İzleme Tablosu
| İzleme Yöntemi | Avantajı | Kullanım Alanı |
|---|---|---|
| Event Viewer | Windows ile entegre, ek kurulum gerektirmez. | Kritik hata raporlama. |
| Serilog + Seq/ELK | Görselleştirme ve arama kolaylığı sağlar. | Büyük ölçekli sistemler. |
| Health Checks | Servis canlılığını HTTP üzerinden kontrol eder. | Mikroservis mimarileri. |
Servis dağıtımı yaparken, sc create komutu yerine NSSM (Non-Sucking Service Manager) gibi araçlar kullanmak, servisin çökmesi durumunda otomatik olarak yeniden başlatılmasını (recovery) yapılandırmanızı çok daha kolaylaştırır.
Sonuç
C# ile arka planda çalışan bir Windows servisi geliştirmek, modern .NET Worker Service yapısı sayesinde oldukça pratik ve sürdürülebilir bir hale gelmiştir. Bu rehberde, servisin oluşturulmasından sistem servisi olarak kaydedilmesine kadar olan tüm süreci tamamladınız. Bir sonraki adım olarak, servisinize bir veritabanı bağlantısı ekleyerek veya bir API üzerinden veri çekme yeteneği kazandırarak projenizi daha işlevsel hale getirebilirsiniz.


Yorumlar (0)
Yorum Yaz