Visual Studio'da Windows hizmetlerinde nasıl hata ayıklayabilirim?


85

Visual Studio'da Windows hizmetlerinde hata ayıklamak mümkün müdür?

Gibi kod kullandım

System.Diagnostics.Debugger.Break();

ancak aşağıdaki gibi bazı kod hatası veriyor:

İki olay hatası aldım: eventID 4096 VsJITDebugger ve "Hizmet, başlatma veya kontrol isteğine zamanında yanıt vermedi."

Yanıtlar:


124

Servis OnStartyönteminde aşağıdaki kodu kullanın :

System.Diagnostics.Debugger.Launch();

Açılır mesajdan Visual Studio seçeneğini seçin.

Not: Bunu yalnızca Hata Ayıklama modunda kullanmak için #if DEBUGaşağıdaki gibi bir derleyici yönergesi kullanılabilir. Bu, bir üretim sunucusunda yayın modunda yanlışlıkla veya hata ayıklamayı önleyecektir.

#if DEBUG
    System.Diagnostics.Debugger.Launch();
#endif

9
VS'yi Yönetici olarak çalıştırmayı unutmayın. Sonra listede mevcut olacak.
Michael

1
Pop-up mesajının ne anlama geldiğini birisi netleştirebilir mi? Bu ne zaman / nasıl ortaya çıkıyor?
Mike

@Mike, kur ve servisi başlat, görünecektir.
Harshit

@Mike, etkileşimli (oturum açılmış) masaüstünde açılan ve işlemde hata ayıklamak için bir uygulama seçmek isteyip istemediğinizi soran bir Windows iletişim kutusu. VS'yi seçerseniz, hata ayıklayıcıyı başlatır ve işleme eklenir
Chris Johnson

63

Bunu da deneyebilirsiniz.

  1. Windows hizmetinizi oluşturun ve kurun ve başlatın…. Yani, Windows hizmetlerinin sisteminizde çalışıyor olması gerekir.
  2. Hizmetiniz çalışırken, Hata Ayıklama menüsüne gidin, İşlemi Ekle'ye tıklayın (veya eski Visual Studio'da işlem yapın)
  3. Çalışan hizmetinizi bulun ve ardından İşlemi tüm kullanıcılardan göster ve İşlemleri tüm oturumlarda göster seçeneklerinin seçili olmadığından emin olun, ardından seçin.

görüntü açıklamasını buraya girin

  1. Click takın düğmesini
  2. tıklayın Tamam
  3. Kapat'ı tıklayın
  4. İstediğiniz yere bir kırılma noktası ayarlayın ve yürütülmesini bekleyin. Kodunuz o noktaya ulaştığında otomatik olarak hata ayıklayacaktır.
  5. UnStart () ise kesme noktanızı ulaşılabilir bir yere koyun , ardından durdurun ve hizmeti yeniden başlatın

(Bir sürü googling yaptıktan sonra bunu "Visual Studio'da Windows Hizmetlerinde nasıl hata ayıklanır?" Bölümünde buldum.)


2
Bu seçenek VS2013 Güncelleme 5'te göremiyorum. :(
sandeep talabathula

1
Ancak Vs-
2017'nizi

1
Bunu denedim. Servis ayıklayıcı ekli olmayan alır durduğunda çünkü OnStop içinde değil onStart üzerinde bir kesme noktası ile çalıştı
KansaiRobot

22

Sen edecek tüm kodu ayırmak gerekir yapmak ayrı bir projeye hizmet projesinden şeyler ve sonra normal çalıştırın ve hata ayıklama anlamına bir test uygulaması yapmak.

Hizmet projesi, yalnızca hizmet kısmını uygulamak için ihtiyaç duyulan kabuk olacaktır.


OOW !! ctrl + C sonra ctrl + V, yeni projeyi kastediyorum. Ya sadece ben yapıyorum. Ayrı bir proje yerine hata ayıklamak için herhangi bir işlem veya başka bir seçenek eklemek mümkün değil mi?
PawanS

1
Elbette mümkün, ancak geliştirme sırasında servis kısmını çıkarırsanız bir Windows servisi geliştirmek çok daha kolay.
Lasse V.Karlsen

hmmm ... bu iyi bir yol ama basitçe işi ikiye katlıyor. Başka bir yolun olabileceğini düşündüm.
PawanS

9
İşi nasıl "ikiye katlayacağını" anlamıyorum. Elbette, fazladan proje oluştururken ve hizmetteki kodu üçüncü bir projeye ayırırken biraz ek yük getirecek, ancak bunun dışında, kodun bir kopyasını oluşturmazsınız, onu hareket ettirirsiniz, ve bu projeye referans verin.
Lasse V.Karlsen

3
^ + 1. Geliştirme süresi açısından neredeyse sıfır olan hizmeti yönetme işini ikiye katlar ve yalnızca bir kez yaparsınız. Bir hizmetin hatalarını ayıklamak ZORLUKLU - daha ziyade komut satırı olarak ikili başlatma yapın. Bunu yapmaya izin veren önceden tanımlanmış sarmalayıcı sınıfları için Google'ı kontrol edin (hizmet sınıfını başlatma / durdurma simülasyonu için yansıma kullanırlar). bir saatlik çalışma, tonlarca tasarruf, net kayıp: negatif - zaman kazanırsınız.
TomTom

14

Ya Lasse V. Karlsen tarafından önerildiği gibi ya da hizmetinizde bir hata ayıklayıcının eklenmesini bekleyecek bir döngü oluşturun. En basit olanı

while (!Debugger.IsAttached)
{
    Thread.Sleep(1000);
}

... continue with code

Bu şekilde hizmeti başlatabilir ve Visual Studio'da "İşleme Ekle ..." yi seçebilir ve hizmetinize ekleyerek normal çalıştırmayı sürdürebilirsiniz.


yukarıdaki kodu nereye koymalıyım ... ve ekleme işleminde devre dışı bırakma adlı hizmetimi alıyorum
PawanS

3
biz de bunun gibi bir kod kullandık if (Environment.UserInteractive) { InteractiveRun(args); } else { Service instance = new Service(); ServiceBase[] servicesToRun = new ServiceBase[] { instance }; ServiceBase.Run(servicesToRun); }
Kirill Kovalenko

bu kod, hata ayıklamak istediğiniz herhangi bir kodun çalıştırılabilmesi için mümkün olduğunca erken olmalıdır.
Pauli Østerø

@Pawan: In Start/ OnStart()sanırım
abatishchev

@Kirill: Yorumların içindeki kodu vurgulamak için tildleri kullanın, örn.foo(bar)
abatishchev

7

Olduğu göz önüne alındığında ServiceBase.OnStartsahip protectedgörünürlük, ben hata ayıklama elde etmek yansıma rotayı aşağı indi.

private static void Main(string[] args)
{
    var serviceBases = new ServiceBase[] {new Service() /* ... */ };

#if DEBUG
    if (Environment.UserInteractive)
    {
        const BindingFlags bindingFlags =
            BindingFlags.Instance | BindingFlags.NonPublic;

        foreach (var serviceBase in serviceBases)
        {
            var serviceType = serviceBase.GetType();
            var methodInfo = serviceType.GetMethod("OnStart", bindingFlags);

            new Thread(service => methodInfo.Invoke(service, new object[] {args})).Start(serviceBase);
        }

        return;
    }
#endif

    ServiceBase.Run(serviceBases);
}

Bunun Threadvarsayılan olarak bir ön plan iş parçacığı olduğunu unutmayın. returnden ing Mainsahte hizmet ipler sürecini sonlandırmak olmaz çalışırken.


OnStart'ın hızlı bir şekilde dönmesi gerektiğinden, bunu başka bir iş parçacığında yapmanız gerekmez. Ancak, hizmet başka bir iş parçacığı başlatmazsa, işleminiz hemen sonlandırılacaktır.
Matt Connolly

@MattConnolly İkincisi: Gerekirse, sonsuza kadar uyuyan (normal işlemden önce) bir ön plan iş parçacığı başlatmak için yukarıdaki kodu değiştiririm.
ta.speot.is

Bu gerçek bir cevap olmalı. Güzel çalışıyor!
lentyai

4

Bir Microsoft makalesi, burada bir Windows hizmetinde nasıl hata ayıklanacağını ve bir işleme ekleyerek hata ayıklayan herhangi birinin hangi bölümü kaçırabileceğini açıklar .

Aşağıda çalışma kodum var. Microsoft'un önerdiği yaklaşımı izledim.

Bu kodu şuraya ekleyin program.cs:

static void Main(string[] args)
{
    // 'If' block will execute when launched through Visual Studio
    if (Environment.UserInteractive)
    {
        ServiceMonitor serviceRequest = new ServiceMonitor();
        serviceRequest.TestOnStartAndOnStop(args);
    }
    else // This block will execute when code is compiled as a Windows application
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new ServiceMonitor()
        };
        ServiceBase.Run(ServicesToRun);
    }
}

Bu kodu ServiceMonitor sınıfına ekleyin.

internal void TestOnStartAndOnStop(string[] args)
{
    this.OnStart(args);
    Console.ReadLine();
    this.OnStop();
}

Şimdi Proje Özelliklerine gidin , "Uygulama" sekmesini seçin ve hata ayıklama sırasında "Konsol Uygulaması" olarak Çıktı Tipini seçin veya hata ayıklama, yeniden derleyin ve hizmetinizi kurun.

Buraya resim açıklamasını girin


1
Çıkışta Debug'da Konsol Uygulaması ve Pencere Uygulaması için çıktı ayarlamanın bir yolu var mı?
kofifus

3

Konsol uygulaması yapabilirsiniz. Bu mainişlevi kullanıyorum:

    static void Main(string[] args)
    {
        ImportFileService ws = new ImportFileService();
        ws.OnStart(args);
        while (true)
        {
            ConsoleKeyInfo key = System.Console.ReadKey();
            if (key.Key == ConsoleKey.Escape)
                break;
        }
        ws.OnStop();
    }

Benim ImportFileServicesınıf inheritant hariç tam olarak benim, Windows hizmetinin uygulamada aynıdır ( ServiceBase).


aynı projede mi yoksa bu konsol uygulaması için başka bir proje mi
PawanS

Benzer sınıflara sahip 2 farklı proje. Benim durumumda, yalnızca ImportFileService sınıfının yinelenmiş olduğu basit bir hizmet. Geliştirme / test yapmak istediğimde consoleapp kullanıyorum ve sonra kopyala / yapıştır. Lasse V. Karlsen'in dediği gibi, bu bir hata ayıklama programı, tüm mantık (iş) üçüncü bir projede.
kerrubin

Evet, öyle. Bu yüzden "miras kalan ( ServiceBase) hariç" dedim . Konsol Uygulamasında hata ayıklamayı daha kolay buluyorum, ancak bunun herkesi ikna edip etmediğini anlıyorum.
kerrubin

3

ServiceProcess.Helpers adında harika bir Nuget paketi kullanıyorum.

Ve alıntı yapıyorum ...

Eklenmiş bir hata ayıklayıcı ile çalışırken bir oynat / durdur / duraklat kullanıcı arabirimi oluşturarak Windows hizmetlerinin hata ayıklamasına yardımcı olur, ancak hizmetin Windows sunucu ortamı tarafından yüklenmesine ve çalıştırılmasına da olanak tanır.

Bütün bunlar bir satır kodla.

http://windowsservicehelper.codeplex.com/

Kurulduktan ve bağlandıktan sonra yapmanız gereken tek şey, Windows hizmet projenizi başlangıç ​​projesi olarak ayarlamak ve hata ayıklayıcınızda başlat'a tıklamaktır.


Paylaşım için teşekkürler! Bu açık ara en basit çözümdü!
Wellington Zanelli

2

System.Diagnostics.Debugger.Launch () yöntemini de deneyebilirsiniz . Hata ayıklayıcı işaretçisini belirtilen konuma götürmenize yardımcı olur ve daha sonra kodunuzda hata ayıklayabilirsiniz.

Bu adımdan önce lütfen service.exe dosyanızı Visual Studio komut isteminin - installutil projectservice.exe komut satırını kullanarak yükleyin.

Ardından, Denetim Masası -> Yönetim Araçları -> Bilgisayar Yönetimi -> Hizmet ve Uygulama -> Hizmetler -> Hizmet Adınız'dan hizmetinizi başlatın


2

Bu kodu hizmet sınıfıma ekledim, böylece OnStop'a benzer şekilde OnStart'ı dolaylı olarak çağırabilirdim.

    public void MyOnStart(string[] args)
    {
        OnStart(args);
    }

2

Ben kullanıyorum /ConsoleVisual Studio projesi içinde parametre ayıklamaBaşlat SeçenekKomut satırı argümanları :

public static class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
         var runMode = args.Contains(@"/Console")
             ? WindowsService.RunMode.Console
             : WindowsService.RunMode.WindowsService;
         new WinodwsService().Run(runMode);
    }
}


public class WindowsService : ServiceBase
{
    public enum RunMode
    {
        Console,
        WindowsService
    }

    public void Run(RunMode runMode)
    {
        if (runMode.Equals(RunMode.Console))
        {
            this.StartService();
            Console.WriteLine("Press <ENTER> to stop service...");
            Console.ReadLine();

            this.StopService();
            Console.WriteLine("Press <ENTER> to exit.");
            Console.ReadLine();
        }
        else if (runMode.Equals(RunMode.WindowsService))
        {
            ServiceBase.Run(new[] { this });
        }
    }

    protected override void OnStart(string[] args)
    {
        StartService(args);
    }

    protected override void OnStop()
    {
        StopService();
    }

    /// <summary>
    /// Logic to Start Service
    /// Public accessibility for running as a console application in Visual Studio debugging experience
    /// </summary>
    public virtual void StartService(params string[] args){ ... }

    /// <summary>
    /// Logic to Stop Service
    /// Public accessibility for running as a console application in Visual Studio debugging experience
    /// </summary>
    public virtual void StopService() {....}
}

2

Bu soruyu buldum, ancak net ve basit bir cevabın eksik olduğunu düşünüyorum.

Hata ayıklayıcımı bir işleme eklemek istemiyorum, ancak yine de hizmeti OnStartve OnStopyöntemleri çağırabilmek istiyorum . Ayrıca bir konsol uygulaması olarak çalışmasını istiyorum, böylece NLog'daki bilgileri bir konsola kaydedebilirim .

Bunu yapan bu harika rehberleri buldum:

Projeleri Output typeolarak değiştirerek başlayın Console Application.

Buraya resim açıklamasını girin

Aşağıdaki Program.csgibi görünecek şekilde değiştirin :

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        // Startup as service.
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new Service1()
        };

        if (Environment.UserInteractive)
        {
            RunInteractive(ServicesToRun);
        }
        else
        {
            ServiceBase.Run(ServicesToRun);
        }
    }
}

Ardından, hizmetlerin etkileşimli modda çalışmasına izin vermek için aşağıdaki yöntemi ekleyin.

static void RunInteractive(ServiceBase[] servicesToRun)
{
    Console.WriteLine("Services running in interactive mode.");
    Console.WriteLine();

    MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Starting {0}...", service.ServiceName);
        onStartMethod.Invoke(service, new object[] { new string[] { } });
        Console.Write("Started");
    }

    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine(
        "Press any key to stop the services and end the process...");
    Console.ReadKey();
    Console.WriteLine();

    MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Stopping {0}...", service.ServiceName);
        onStopMethod.Invoke(service, null);
        Console.WriteLine("Stopped");
    }

    Console.WriteLine("All services stopped.");
    // Keep the console alive for a second to allow the user to see the message.
    Thread.Sleep(1000);
}

Harika Kod! Basit, etkili. +1. Ancak bunu bir Forms uygulaması yaptım. Konsol uygulamalarından gerçekten nefret ediyorum. Ayrıca, her hizmet olayı için kolayca bir Form Düğmesi uygulayabilirsiniz.
Roland

1

Ne yazık ki, bir Windows Hizmeti işleminin en başında hata ayıklamaya çalışıyorsanız, çalışan işleme "ekleme" çalışmayacaktır. OnStart procecdure içinde Debugger.Break () kullanmayı denedim, ancak 64 bit, Visual Studio 2010 derlenmiş uygulamasında, break komutu şu şekilde bir hata veriyor:

System error 1067 has occurred.

Bu noktada, yürütülebilir dosyanız için kayıt defterinizde bir "Görüntü Dosyası Yürütme" seçeneği ayarlamanız gerekir. Kurulumu beş dakika sürüyor ve çok iyi çalışıyor. Ayrıntıların bulunduğu bir Microsoft makalesi:

Nasıl yapılır: Hata Ayıklayıcıyı Otomatik Olarak Başlatma


1

Visual Studio'nun kendi oluşturma sonrası olay komut satırını deneyin .

Bunu yapım sonrası eklemeye çalışın:

@echo off
sc query "ServiceName" > nul
if errorlevel 1060 goto install
goto stop

:delete
echo delete
sc delete "ServiceName" > nul
echo %errorlevel%
goto install

:install
echo install
sc create "ServiceName" displayname= "Service Display Name" binpath= "$(TargetPath)" start= auto > nul
echo %errorlevel%
goto start

:start
echo start
sc start "ServiceName" > nul
echo %errorlevel%
goto end

:stop
echo stop
sc stop "ServiceName" > nul
echo %errorlevel%
goto delete

:end

Böyle bir mesajla derleme hatası varsa Error 1 The command "@echo off sc query "ServiceName" > nul, Ctrl+ Csonra Ctrl+ Vhata mesajını Not Defteri'ne girin ve mesajın son cümlesine bakın.

Söyleniyor olabilir exited with code x. Buradaki bazı yaygın hatalardaki kodu arayın ve nasıl çözüleceğini görün.

1072 -- Marked for deletion → Close all applications that maybe using the service including services.msc and Windows event log.
1058 -- Can't be started because disabled or has no enabled associated devices → just delete it.
1060 -- Doesn't exist → just delete it.
1062 -- Has not been started → just delete it.
1053 -- Didn't respond to start or control → see event log (if logged to event log). It may be the service itself throwing an exception.
1056 -- Service is already running → stop the service, and then delete.

Hata kodlarıyla ilgili daha fazla bilgiyi burada bulabilirsiniz .

Ve böyle bir mesajla ilgili yapı hatası varsa,

Error    11    Could not copy "obj\x86\Debug\ServiceName.exe" to "bin\Debug\ServiceName.exe". Exceeded retry count of 10. Failed.    ServiceName
Error    12    Unable to copy file "obj\x86\Debug\ServiceName.exe" to "bin\Debug\ServiceName.exe". The process cannot access the file 'bin\Debug\ServiceName.exe' because it is being used by another process.    ServiceName

cmd'yi açın ve sonra önce onu öldürmeye çalışın taskkill /fi "services eq ServiceName" /f

Her şey yolundaysa, F5hata ayıklamak için yeterli olmalıdır.


0

In OnStartyöntemle şunu yapın.

protected override void OnStart(string[] args)
{
    try
    {
        RequestAdditionalTime(600000);
        System.Diagnostics.Debugger.Launch(); // Put breakpoint here.

        .... Your code
    }
    catch (Exception ex)
    {
        .... Your exception code
    }
}

Ardından yönetici olarak bir komut istemi çalıştırın ve aşağıdakileri girin:

c:\> sc create test-xyzService binPath= <ProjectPath>\bin\debug\service.exe type= own start= demand

Yukarıdaki satır, servis listesinde test-xyzService oluşturacaktır.

Hizmeti başlatmak için, bu sizden Visual Studio'da ilk kullanıma eklemenizi isteyip istemediğinizi soracaktır.

c:\> sc start text-xyzService

Hizmeti durdurmak için:

c:\> sc stop test-xyzService

Silmek veya kaldırmak için:

c:\> sc delete text-xyzService

0

Http üzerinden bir Windows Hizmetinde hata ayıklama (VS 2015 Update 3 ve .Net FW 4.6 ile test edilmiştir)

Öncelikle VS Çözümünüz içinde bir Konsol Projesi oluşturmanız gerekir (Ekle -> Yeni Proje -> Konsol Uygulaması).

Yeni proje içinde, bu kodla bir "ConsoleHost" sınıfı oluşturun:

class ConsoleHost : IDisposable
{
    public static Uri BaseAddress = new Uri(http://localhost:8161/MyService/mex);
    private ServiceHost host;

    public void Start(Uri baseAddress)
    {
        if (host != null) return;

        host = new ServiceHost(typeof(MyService), baseAddress ?? BaseAddress);

        //binding
        var binding = new BasicHttpBinding()
        {
            Name = "MyService",
            MessageEncoding = WSMessageEncoding.Text,
            TextEncoding = Encoding.UTF8,
            MaxBufferPoolSize = 2147483647,
            MaxBufferSize = 2147483647,
            MaxReceivedMessageSize = 2147483647
        };

        host.Description.Endpoints.Clear();
        host.AddServiceEndpoint(typeof(IMyService), binding, baseAddress ?? BaseAddress);

        // Enable metadata publishing.
        var smb = new ServiceMetadataBehavior
        {
            HttpGetEnabled = true,
            MetadataExporter = { PolicyVersion = PolicyVersion.Policy15 },
        };

        host.Description.Behaviors.Add(smb);

        var defaultBehaviour = host.Description.Behaviors.OfType<ServiceDebugBehavior>().FirstOrDefault();
        if (defaultBehaviour != null)
        {
            defaultBehaviour.IncludeExceptionDetailInFaults = true;
        }

        host.Open();
    }

    public void Stop()
    {
        if (host == null)
            return;

        host.Close();
        host = null;
    }

    public void Dispose()
    {
        this.Stop();
    }
}

Ve bu Program.cs sınıfının kodudur:

public static class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
        var baseAddress = new Uri(http://localhost:8161/MyService);
        var host = new ConsoleHost();
        host.Start(null);
        Console.WriteLine("The service is ready at {0}", baseAddress);
        Console.WriteLine("Press <Enter> to stop the service.");
        Console.ReadLine();
        host.Stop();
    }
}

Bağlantı dizeleri gibi yapılandırmalar, Konsol projesinin App.config dosyasında kopyalanmalıdır.

Konsolu başlatmak için Konsol projesine sağ tıklayın ve Hata Ayıkla -> Yeni örnek başlat'a tıklayın.


0

Hizmet sınıfınıza bir yüklenici eklemeniz yeterlidir (eğer zaten sahip değilseniz). Aşağıda, görsel temel .net'i kontrol edebilir ve örnek verebilirsiniz.

Public Sub New()
   OnStart(Nothing) 
End Sub

Bundan sonra, projeye sağ tıklayın ve " Hata Ayıkla -> Yeni bir örnek başlat " ı seçin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.