विंडोज सेवा को डिबग करने का आसान तरीका


325

क्या विंडोज सर्विस कंट्रोल मैनेजर के माध्यम से सेवा शुरू करने और फिर डिबगर को थ्रेड में संलग्न करने की तुलना में कोड के माध्यम से कदम रखने का एक आसान तरीका है? यह बोझिल की तरह है और मैं सोच रहा हूं कि क्या अधिक सरल दृष्टिकोण है।


मैंने यह उपयोगकर्ता वॉयस टिकट बनाया है। इसके लिए मतदान पर विचार करें: visualstudio.uservoice.com/forums/121579-visual-studio-ide/…
डेविड

जवाबों:


271

अगर मैं जल्दी से इस सेवा को समाप्त करना चाहता हूं, तो मैं बस Debugger.Break()वहां से हट जाता हूं । जब वह लाइन पहुँच जाती है, तो वह मुझे वापस वी.एस. जब आप कर रहे हैं उस लाइन को हटाने के लिए मत भूलना।

अद्यतन:#if DEBUG प्रैग्मैस के विकल्प के रूप में , आप Conditional("DEBUG_SERVICE")विशेषता का उपयोग भी कर सकते हैं ।

[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
    Debugger.Break();
}

अपने पर OnStart, इस पद्धति को कॉल करें:

public override void OnStart()
{
     DebugMode();
     /* ... do the rest */
}

वहां, कोड केवल डीबग बिल्ड के दौरान सक्षम किया जाएगा। जबकि आपके पास, यह सेवा डिबगिंग के लिए एक अलग बिल्ड कॉन्फ़िगरेशन बनाने के लिए उपयोगी हो सकता है।


45
या आप Debugger.Launch का उपयोग कर सकते हैं () आपको Systems.Diagnostics नाम स्थान के लिए एक उपयोग कथन शामिल करना होगा।
उमर कोझी

1
आपके ब्लॉग पोस्ट ने ठीक काम किया और मेरे दिन को बचा लिया :) हालाँकि Debugger.Break () ने मेरे लिए काम नहीं किया। ऐसा लगता है कि .Net कुछ ऑप्टिमाइज़ेशन से संबंधित कारणों के लिए डीबगमोड फ़ंक्शन को छोड़ देता है।
बिशन डे

3
Debugger.Launch () मेरे लिए तब काम करता है जब Debugger.Break () नहीं करता है। (प्रक्रिया 255 के साथ बाहर निकलती है।)
ओलिवर बॉक

आप लोग इसे कैसे काम कर रहे हैं? कुछ नहीं हुआ। मैंने ब्रेक () और लॉन्च () की कोशिश की है।
स्पेस

13
@ 4thSpace: 1. अपनी सेवा के लिए एक इंस्टॉलर बनाएं, ताकि आप अपनी सेवा स्थापित कर सकें। 2. लाइन को डिबगर जोड़ें। लंच (); अपने मुख्य () की शुरुआत में। 3. अपने कोड को डीबग-मोड में बनाएँ। 4. डिबग-dll के साथ स्थापित dll को अधिलेखित करें। 5. Windows सेवा पैनल से सेवा शुरू करें। अब एक पॉपअप आपको डिबगर से जुड़ने के लिए कहता है। इस तरह मेरे लिए काम किया। उम्मीद है आपके लिए भी।
ffonz

210

मुझे यह भी लगता है कि सामान्य निष्पादन के लिए एक अलग "संस्करण" होना और एक सेवा के रूप में जाने का रास्ता है, लेकिन क्या वास्तव में उस उद्देश्य के लिए एक अलग कमांड लाइन स्विच समर्पित करना आवश्यक है?

क्या आप ऐसा नहीं कर सकते:

public static int Main(string[] args)
{
  if (!Environment.UserInteractive)
  {
    // Startup as service.
  }
  else
  {
    // Startup as application
  }
}

इसका "लाभ" होगा, कि आप अपने ऐप को डबलक्लिक के माध्यम से शुरू कर सकते हैं (ठीक है, अगर आपको वास्तव में इसकी आवश्यकता है) और यह कि आप F5विजुअल स्टूडियो में हिट कर सकते हैं (उस /consoleविकल्प को शामिल करने के लिए प्रोजेक्ट सेटिंग्स को संशोधित करने की आवश्यकता के बिना )।

तकनीकी रूप से, Environment.UserInteractiveयदि WSF_VISIBLEध्वज को वर्तमान विंडो स्टेशन के लिए सेट किया गया है , तो जांच करता है, लेकिन क्या कोई अन्य कारण है जहां वह false(गैर-संवादात्मक) सेवा के रूप में चलाया जा रहा है?


महान! मैंने पहले एक "if #debug" पद्धति का उपयोग किया था ताकि डिबगिंग के रूप में आवेदन शुरू किया जा सके, अन्यथा एक सेवा। यह एप्लिकेशन को सेवा के रूप में रन करने योग्य नहीं बनाता है यदि आप इसे डीबग करना चाहते हैं, लेकिन आपका समाधान इसे हल करता है और सेवा / ऐप और रिलीज़ / डीबग के सभी चार संयोजनों में इसे चलाने योग्य बनाता है।
जोनास

29
यदि आप नहीं चाहते हैं कि यह प्रोग्राम डबल-क्लिक होने पर चले (उपयोगकर्ता भ्रमित हो सकते हैं और कई इंस्टेंस आदि चला सकते हैं), तो आप System.Diagnostics.Debugger.IsAttachedइसके बजाय उपयोग कर सकते हैं Environment.UserInteractive
Blorgbeard

5
लेकिन क्या कोई और कारण है कि यह एक (गैर-संवादात्मक) सेवा के रूप में चलाया जा रहा है, इसके अलावा यह गलत है? मैं एक के बारे में सोच सकता हूं: एक निर्धारित कार्य जो कंसोल से जुड़ा नहीं है।
होगन

7
मैं इस मामले के लिए कमांड लाइन मापदंडों का उपयोग करता हूं। - सेवा को स्थापित करने के लिए स्थापना रद्द करें, - सेवा की स्थापना रद्द करने के लिए स्थापना रद्द करें और - आवेदन के रूप में सेवा को चलाने के लिए सक्रिय करें। मैं प्रोजेक्ट विकल्पों में डिबेंक्टिव जोड़ रहा हूं (डिबगिंग> कमांड आर्ग्युमेंट्स)। इसलिए मैं वी.एस. से आसानी से डिबग कर सकता हूं। डबल क्लिक करने से अवांछित रनिंग इंस्टेंस नहीं बनेगी - इन-एक्टिव सक्रिय होना आवश्यक है। सिर्फ मेरे 2 सेंट।
अमीर अकाएदीन

@ EmirAkaydın हां, वास्तव में मेरे पास "बैकअप" के रूप में कमांड लाइन पैरामीटर भी हैं। हालाँकि, मैं वास्तव में "इंटरेक्टिव" उदाहरण चाहता था जब डबल क्लिकिंग और न हो और इस तथ्य के बारे में त्रुटि संदेश कि इस तरह से एक सेवा शुरू नहीं की जा सकती है। मेरे द्वारा लक्षित लक्ष्य ;-)
क्रिश्चियन.के।

123

जब मैंने कुछ सप्ताह पहले एक नई सेवा परियोजना की स्थापना की तो मुझे यह पद मिला। हालांकि, कई शानदार सुझाव हैं, फिर भी मुझे वह समाधान नहीं मिला जो मैं चाहता था: सेवा वर्गों को कॉल करने की संभावना ' OnStartऔर सेवा वर्गों में OnStopबिना किसी संशोधन के तरीके।

समाधान मैं Environment.Interactiveचुनिंदा चल मोड का उपयोग करता हूं , जैसा कि इस पोस्ट के अन्य उत्तरों द्वारा सुझाया गया है।

static void Main()
{
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] 
    {
        new MyService()
    };
    if (Environment.UserInteractive)
    {
        RunInteractive(servicesToRun);
    }
    else
    {
        ServiceBase.Run(servicesToRun);
    }
}

RunInteractiveसहायक प्रतिबिंब का उपयोग करता है की रक्षा की कॉल करने के लिए OnStartऔर OnStopतरीके:

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);
}

यह सभी आवश्यक कोड है, लेकिन मैंने स्पष्टीकरण के साथ वॉकथ्रू भी लिखा ।


यह ServiceBase [] के लिए एक अच्छा एक्सटेंशन तरीका बनाता है। मेरे पास मेरे समाधान में कई सेवाएँ हैं, ताकि Program.cs के लिए एक सामान्य आधार वर्ग होने के बजाय, मैं बस सेवाओं को कॉल करता हूं। Run.unInteractive (args)। अच्छा समाधान @ और!
डेविड कीवेनी

3
महान समाधान वास्तव में। मैंने सर्विसबेस के लिए एक सरल एक्सटेंशन बनाया [] जैसा कि डेविड ने सुझाव दिया था जो कोड की सिर्फ एक लाइन में सेवाएं चलाने की अनुमति देता है: pastebin.com/F0fhhG2R
Funbit

4
+1 खदान के एक पूर्व सहयोगी ने एक "ईज़ीरन सर्विस" बेस क्लास (जो सर्विसप्रोसेस विरासत में मिला है) बनाया, जो कि बहुत ही समान काम करता है, लेकिन प्रतिबिंब की आवश्यकता के बिना (क्योंकि ऑनस्टार्ट अब बेस क्लास में है)। यह वास्तव में डिबगिंग को विंडोज़ सेवा को एक हवा बनाता है।
सोनडरगार्ड

3
@ Chazt3n सुनिश्चित करें कि आपका प्रोजेक्ट आउटपुट प्रकार "कंसोल एप्लिकेशन" पर सेट है। सेवा स्थापना के लिए, यह कोई फर्क नहीं पड़ता कि कौन सा आउटपुट प्रकार चुना गया है, व्यवहार समान है।
फनबिट

2
अभी भी एक महान समाधान! केवल एक चीज जो मैं जोड़ूंगा (जैसा कि दिखाया गया है walk through) यह सुनिश्चित करने के लिए है कि आप परियोजना के गुणों में जाते हैं और Console Applicationसंकलन करने और चलाने के लिए आउटपुट प्रकार को बदलने से पहले। इसे खोजो Project Properties -> Application -> Output type -> Console Application। इसके अलावा, इसके लिए मेरे लिए ठीक से काम करने के लिए मैंने startकमांड का उपयोग करके एप्लिकेशन को चलाने के लिए समाप्त कर दिया । Ex: C:\"my app name.exe" -serviceमेरे लिए काम नहीं करेगा। इसके बजाय मैंने इस्तेमाल कियाC:\start /wait "" "my app name.exe" -service
Arvo Bowen

47

कभी-कभी यह विश्लेषण करना महत्वपूर्ण है कि सेवा की शुरुआत के दौरान क्या हो रहा है प्रक्रिया में संलग्न होने से यहां मदद नहीं मिलती है, क्योंकि आप डिबगर संलग्न करने के लिए पर्याप्त जल्दी नहीं हैं, जबकि सेवा शुरू हो रही है।

संक्षिप्त उत्तर है, मैं यह करने के लिए कोड की 4 पंक्तियों का उपयोग कर रहा हूं :

#if DEBUG
    base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
    Debugger.Launch(); // launch and attach debugger
#endif

इन्हें OnStartसेवा की विधि में निम्नानुसार डाला गया है:

protected override void OnStart(string[] args)
{
    #if DEBUG
       base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
       Debugger.Launch(); // launch and attach debugger
    #endif
    MyInitOnstart(); // my individual initialization code for the service
    // allow the base class to perform any work it needs to do
    base.OnStart(args);
}

उन लोगों के लिए जिन्होंने इसे पहले नहीं किया है, मैंने नीचे विस्तृत संकेत शामिल किए हैं , क्योंकि आप आसानी से फंस सकते हैं। निम्न संकेत विंडोज 7x64 और विज़ुअल स्टूडियो 2010 टीम संस्करण को संदर्भित करते हैं , लेकिन अन्य वातावरणों के लिए भी मान्य होना चाहिए।


महत्वपूर्ण: "मैनुअल" मोड में सेवा को तैनात करें (या तो InstallUtilवीएस कमांड प्रॉम्प्ट से उपयोगिता का उपयोग करें या आपके द्वारा तैयार किए गए सेवा इंस्टॉलर प्रोजेक्ट को चलाएं)। सेवा शुरू करने से पहले विज़ुअल स्टूडियो खोलें और सेवा के स्रोत कोड वाले समाधान को लोड करें - अतिरिक्त ब्रेकप्वाइंट सेट करें जैसा कि आपको विज़ुअल स्टूडियो में उनकी आवश्यकता है - फिर सेवा नियंत्रण कक्ष के माध्यम से सेवा शुरू करें

वजह से Debugger.Launchकोड, यह एक संवाद का कारण होगा "एक माइक्रोसॉफ्ट .NET फ्रेमवर्क अपवाद में हुई बिना क्रिया Servicename.exe ।" उपस्थित होना। स्क्रीनशॉट में दिखाए अनुसार क्लिक करें :Elevate Yes, debug Servicename.exe
FrameworkException

बाद में, विंडोज 7 यूएसी में escp तौर पर आप व्यवस्थापक क्रेडेंशियल दर्ज करने के लिए संकेत दे सकते हैं। उन्हें दर्ज करें और आगे बढ़ें Yes:

UACPrompt

उसके बाद, प्रसिद्ध विज़ुअल स्टूडियो जस्ट-इन-टाइम डीबगर विंडो दिखाई देती है। यह आपसे पूछता है कि क्या आप डिले हुए डीबगर का उपयोग करके डिबग करना चाहते हैं। क्लिक करने से पहले Yes, यह चुनें कि आप एक नया उदाहरण (दूसरा विकल्प) नहीं खोलना चाहते - एक नया उदाहरण यहाँ मददगार नहीं होगा, क्योंकि स्रोत कोड प्रदर्शित नहीं होगा। इसलिए आप इसके बजाय पहले खोले गए विजुअल स्टूडियो उदाहरण का चयन करें: VSDebuggerPrompt

आपके द्वारा क्लिक किएYes जाने के बाद , थोड़ी देर के बाद विजुअल स्टूडियो उस पंक्ति में पीले रंग के तीर को दिखाएगा जहाँ Debugger.Launchकथन है और आप अपने कोड (विधि MyInitOnStart, जिसमें आपका आरंभीकरण है) को डीबग करने में सक्षम हैं । VSDebuggerBreakpoint

दबाने पर F5तुरंत निष्पादन जारी रहता है, जब तक कि आपके द्वारा तैयार किए गए अगले ब्रेकपॉइंट तक नहीं पहुंच जाता।

संकेत: सेवा चालू रखने के लिए, डीबग का चयन करें -> सभी को अलग करें । यह आपको सेवा के साथ संचार करने वाले ग्राहक को सही ढंग से शुरू करने के बाद चलाने की अनुमति देता है और आप स्टार्टअप कोड को डीबग करना समाप्त कर देते हैं। यदि आप Shift+F5 (डिबगिंग रोकें) दबाते हैं , तो यह सेवा समाप्त कर देगा। ऐसा करने के बजाय, आपको इसे रोकने के लिए सेवा नियंत्रण कक्ष का उपयोग करना चाहिए ।

नोट है कि

  • यदि आप एक रिलीज़ बनाते हैं , तो डिबग कोड स्वचालित रूप से हटा दिया जाता है और सेवा सामान्य रूप से चलती है।

  • मैं उपयोग कर रहा हूं Debugger.Launch(), जो डिबगर शुरू और संलग्न करता है । मैंने भी परीक्षण Debugger.Break()किया है, जो काम नहीं किया , क्योंकि सेवा के शुरू होने पर अभी तक कोई डिबगर संलग्न नहीं है (जिसके कारण "त्रुटि 1067: प्रक्रिया अनपेक्षित रूप से समाप्त हो गई है" )।

  • RequestAdditionalTimeसेवा के स्टार्टअप के लिए एक लंबा समय निर्धारित करता है (यह स्वयं कोड में देरी नहीं कर रहा है, लेकिन तुरंत Debugger.Launchबयान के साथ जारी रहेगा )। अन्यथा सेवा शुरू करने के लिए डिफ़ॉल्ट समय सीमा बहुत कम है और यदि आप base.Onstart(args)डिबगर से बहुत जल्दी कॉल नहीं करते हैं तो सेवा शुरू करना विफल हो जाता है । व्यावहारिक रूप से, 10 मिनट का समय बचा जाता है कि आप संदेश देखते हैं " डिबगर शुरू होने के तुरंत बाद सेवा ने जवाब नहीं दिया ..."

  • एक बार जब आप इसकी अभ्यस्त हो जाते हैं, तो यह विधि बहुत आसान है क्योंकि इसके लिए आपको मौजूदा सेवा कोड में 4 लाइनों को जोड़ने की आवश्यकता होती है , जिससे आप नियंत्रण और डिबग प्राप्त कर सकते हैं।


1
जिज्ञासा से बाहर, क्या आप जानते हैं कि क्या डिबगर.लंच () उपयोगकर्ता संकेत के साथ उपयोगकर्ता बातचीत के लिए एक समय सीमा है?
शिव

1
जैसा कि वर्णित है, base.RequestAdditionalTime(600000)सेवा नियंत्रण को 10 मिनट के लिए सेवा समाप्त करने से रोक देगा यदि वह base.OnStart(args)उस समय के भीतर नहीं बुलाता है )। इसके अलावा, मुझे याद है कि यदि आप थोड़ी देर के बाद व्यवस्थापक क्रेडेंशियल दर्ज नहीं करते हैं तो यूएसी गर्भपात भी कर देगा (मुझे नहीं पता कि कितने सेकंड में ठीक है, लेकिन मुझे लगता है कि आपको इसे एक मिनट के भीतर दर्ज करना होगा, अन्यथा यूएसी गर्भपात करें) , जो डिबग सत्र को समाप्त कर देगा।
मैट

2
मैंने कस्टमकोमैंड संदेशों को डीबग करने के लिए यह सबसे अच्छा तरीका पाया। +1।
जस्टिन

40

आमतौर पर मैं जो करता हूं, वह सेवा के तर्क को एक अलग वर्ग में शामिल करता है और एक 'धावक' वर्ग से शुरू करता है। यह धावक वर्ग वास्तविक सेवा या सिर्फ एक सांत्वना अनुप्रयोग हो सकता है। तो आपके समाधान में (कम से कम) 3 परियोजनाएँ हैं:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....

1
मैं इस दृष्टिकोण का भी उपयोग करता था, लेकिन मुझे लगता है कि इसका एक संयोजन और ऊपर दिया गया जवाब एक उपचार का काम करता है।
रोब्स

27

फैबियो स्कोपेल का यह यूट्यूब वीडियो बताता है कि विंडोज सेवा को कैसे अच्छी तरह से डीबग करना है ... इसे करने की वास्तविक विधि वीडियो में 4:45 से शुरू होती है ...

यहाँ वीडियो में समझाया गया कोड है ... आपके Program.cs फ़ाइल में, डीबग अनुभाग के लिए सामान जोड़ें ...

namespace YourNamespace
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
#if DEBUG
            Service1 myService = new Service1();
            myService.OnDebug();
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
#endif

        }
    }
}

अपनी Service1.cs फ़ाइल में, OnDebug () विधि जोड़ें ...

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }

    protected override void OnStart(string[] args)
    {
        // your code to do something
    }

    protected override void OnStop()
    {
    }

यह काम किस प्रकार करता है

मूल रूप से आपको एक public void OnDebug()कॉल करना होगा जो कि OnStart(string[] args)संरक्षित है और बाहर सुलभ नहीं है। void Main()इस कार्यक्रम के साथ जोड़ा जाता है #ifसाथ पूर्वप्रक्रमक #DEBUG

दृश्य स्टूडियो परिभाषित करता है DEBUGकि क्या परियोजना डिबग मोड में संकलित है। यह डिबग अनुभाग (नीचे) को निष्पादित करने की अनुमति देगा जब स्थिति सही हो।

Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

और यह एक कंसोल एप्लिकेशन की तरह ही चलेगा, एक बार जब चीजें ठीक हो जाती हैं तो आप मोड को बदल सकते हैं Releaseऔर नियमित elseअनुभाग तर्क को ट्रिगर करेगा


मैं इस उत्तर की तलाश में था, पता नहीं क्यों इसे इतना कम स्थान दिया गया था। दूसरों को या संभवतः अधिक टिप्पणियों की मदद करने के लिए कोड समझाया;)
विनोद श्रीवास्तव

14

अपडेट करें

यह तरीका सबसे आसान है:

http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx

मैं अपना मूल उत्तर पोस्टीरिटी के लिए नीचे छोड़ता हूं।


मेरी सेवाओं में एक वर्ग है जो टाइमर को एनकैप्सुलेट करता है क्योंकि मैं चाहता हूं कि सेवा नियमित अंतराल पर जांच करे कि क्या इसके लिए कोई काम करना है।

हम सर्विस स्टार्ट-अप के दौरान क्लास को नया बनाते हैं और StartEventLoop () कहते हैं। (इस क्लास को आसानी से कंसोल ऐप से भी इस्तेमाल किया जा सकता है।)

इस डिज़ाइन का अच्छा दुष्परिणाम यह है कि जिन तर्कों के साथ आपने टाइमर सेट किया है उनका उपयोग सेवा वास्तव में काम शुरू होने से पहले देरी के लिए किया जा सकता है, ताकि आपके पास डिबगर मैन्युअल रूप से संलग्न करने का समय हो।

ps डिबगर को मैन्युअल रूप से रनिंग प्रक्रिया में कैसे संलग्न किया जाए ...?

using System;
using System.Threading;
using System.Configuration;    

public class ServiceEventHandler
{
    Timer _timer;
    public ServiceEventHandler()
    {
        // get configuration etc.
        _timer = new Timer(
            new TimerCallback(EventTimerCallback)
            , null
            , Timeout.Infinite
            , Timeout.Infinite);
    }

    private void EventTimerCallback(object state)
    {
        // do something
    }

    public void StartEventLoop()
    {
        // wait a minute, then run every 30 minutes
        _timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
    }
}

इसके अलावा, मैं निम्नलिखित (पहले के उत्तरों में पहले से ही उल्लेख किया गया था लेकिन सशर्त संकलक [#if] झंडे के साथ रिलीज रिलीज से बचने में मदद करने के लिए) करता था।

मैंने इसे इस तरह से करना बंद कर दिया क्योंकि कभी-कभी हम रिलीज़ में निर्माण करना भूल जाते हैं और क्लाइंट डेमो (शर्मनाक!) पर चलने वाले ऐप में डिबगर ब्रेक होता है।

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif

क्या होता है जब // do somethingपूरा करने के लिए अधिक से अधिक 30 मिनट लगते हैं?
विनोद श्रीवास्तव

13

static void Main()
{
#if DEBUG
                // Run as interactive exe in debug mode to allow easy
                // debugging.

                var service = new MyService();
                service.OnStart(null);

                // Sleep the main thread indefinitely while the service code
                // runs in .OnStart

                Thread.Sleep(Timeout.Infinite);
#else
                // Run normally as service in release mode.

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]{ new MyService() };
                ServiceBase.Run(ServicesToRun);
#endif
}

[कोड - मार्कडाउन समस्याओं के साथ कोई स्पष्टीकरण के बारे में क्षमा करें] डिबग बिल्ड में सामान्य रूप से MS Visual Studio (F5) से चलना चाहिए। अभी भी रिलीज बिल्ड में एक सामान्य सेवा के रूप में चलता है।
थॉमस ब्राट

क्रिश्चियन के। द्वारा "पर्यावरण.उपयोगकर्ता" संपत्ति का उपयोग करने के लिए उपरोक्त समाधान के साथ इसे मिलाएं और समाधान वास्तव में साफ और सरल है।
बेन रॉबिंस

OnStartहै protectedऔर आप पहुँच स्तर को संशोधित नहीं कर सकते हैं :(
एडुआर्ड लुका

10

आप कमांड प्रॉम्प्ट (sc.exe) के माध्यम से भी सेवा शुरू कर सकते हैं।

व्यक्तिगत रूप से, मैं कोड को डिबगिंग चरण में एक स्टैंड-अलोन प्रोग्राम के रूप में चलाऊंगा, और जब अधिकांश बग्स को इस्त्री किया जाता है, तो इस सेवा को चलाने के लिए बदलें।


10

मैं जो कुछ भी करता था वह कमांड लाइन स्विच होता था जो प्रोग्राम को सेवा के रूप में या एक नियमित अनुप्रयोग के रूप में शुरू करता था। फिर, अपने आईडीई में मैं स्विच सेट करूंगा ताकि मैं अपने कोड के माध्यम से कदम रख सकूं।

कुछ भाषाओं के साथ आप वास्तव में यह पता लगा सकते हैं कि यह IDE में चल रहा है या नहीं और यह स्विच अपने आप काम करता है।

आप किस भाषा का उपयोग कर रहे हैं?


9

TopShelf लाइब्रेरी का उपयोग करें ।

एक कंसोल एप्लिकेशन बनाएं फिर अपने मेन में सेटअप कॉन्फ़िगर करें

class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {

                // setup service start and stop.
                x.Service<Controller>(s =>
                {
                    s.ConstructUsing(name => new Controller());
                    s.WhenStarted(controller => controller.Start());
                    s.WhenStopped(controller => controller.Stop());
                });

                // setup recovery here
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(delayInMinutes: 0);
                    rc.SetResetPeriod(days: 0);
                });

                x.RunAsLocalSystem();
            });
        }
}

public class Controller
    {
        public void Start()
        {

        }

        public void Stop()
        {

        }
    }

अपनी सेवा को डीबग करने के लिए, बस दृश्य स्टूडियो में F5 मारा।

सेवा स्थापित करने के लिए, cmd में टाइप करें "कंसोल। Exe स्थापित करें"

तब आप विंडो सेवा प्रबंधक में सेवा शुरू और बंद कर सकते हैं।


उनकी लाइसेंसिंग को समझने में बहुत उलझन थी
l --''''''--------- '' '' '' '' '' '' ''

वे अपाचे लाइसेंस afaik का उपयोग करें। Topshelf सबसे आसान तरीका है जिसका उपयोग मैंने विंडोज़ सेवाओं को विकसित करने और डिबग करने के लिए किया है। सुपर आसान उपयोग करने के लिए। कंसोल एप्लिकेशन के रूप में विकसित करें। एक कमांड लाइन स्विच के साथ एक सेवा के रूप में स्थापित करें। अत्यधिक सिफारिशित।
लूटता

TopShelf ने मुझे कई टन बचाया। Thx
L_7337

8

मुझे लगता है कि यह निर्भर करता है कि आप किस ओएस का उपयोग कर रहे हैं, विस्टा सत्रों के बीच अलगाव के कारण, सेवाओं से जुड़ना बहुत कठिन है।

मेरे द्वारा पूर्व में उपयोग किए गए दो विकल्प हैं:

  • किसी प्रक्रिया के लिए स्थायी डिबगर सेटअप करने के लिए GFlags (विंडोज के लिए डिबगिंग टूल्स में) का उपयोग करें। यह "छवि फ़ाइल निष्पादन विकल्प" रजिस्ट्री कुंजी में मौजूद है और अविश्वसनीय रूप से उपयोगी है। मुझे लगता है कि आपको "डेस्कटॉप के साथ सहभागिता" को सक्षम करने के लिए सेवा सेटिंग्स को मोड़ना होगा। मैं इसका उपयोग सभी प्रकार के डिबगिंग के लिए करता हूं, न कि केवल सेवाओं के लिए।
  • अन्य विकल्प, कोड को थोड़ा अलग करना है, ताकि सेवा का हिस्सा एक सामान्य ऐप स्टार्टअप के साथ विनिमेय हो। इस तरह, आप एक साधारण कमांड लाइन फ्लैग का उपयोग कर सकते हैं, और एक प्रक्रिया (सेवा के बजाय) के रूप में लॉन्च कर सकते हैं, जिससे डिबग करना बहुत आसान हो जाता है।

उम्मीद है की यह मदद करेगा।


GFlags के लिए +1। यदि आप स्रोत कोड को संशोधित नहीं कर सकते (या यदि आपके पास नहीं है) तो यह विशेष रूप से उपयोगी है।
क्रिस गिलम

6

मैं अपनी सेवा के हर पहलू को डिबेट करने में सक्षम होना पसंद करता हूं, जिसमें ऑनस्टार्ट () में कोई भी इनिशियलाइज़ेशन शामिल है, जबकि अभी भी इसे एससीएम के ढांचे के भीतर पूर्ण सेवा व्यवहार के साथ निष्पादित किया जाता है ... कोई "कंसोल" या "ऐप" मोड नहीं।

मैं दूसरी परियोजना बनाकर, उसी परियोजना में, डिबगिंग के लिए उपयोग करता हूं। डिबग सेवा, जब सामान्य रूप से शुरू की जाती है (यानी सेवाओं एमएमसी प्लगइन में), सेवा होस्ट प्रक्रिया बनाती है। यह आपको डिबगर संलग्न करने के लिए एक प्रक्रिया देता है भले ही आपने अभी तक अपनी वास्तविक सेवा शुरू नहीं की हो। डिबगर को प्रक्रिया में संलग्न करने के बाद, अपनी वास्तविक सेवा शुरू करें और आप ऑनस्टार्ट () सहित सेवा जीवनचक्र में कहीं भी इसे तोड़ सकते हैं।

क्योंकि इसमें बहुत न्यूनतम कोड घुसपैठ की आवश्यकता होती है, डिबग सेवा को आसानी से आपकी सेवा सेटअप परियोजना में शामिल किया जा सकता है, और कोड की एक पंक्ति को टिप्पणी करके और एकल प्रोजेक्ट इंस्टॉलर को हटाकर आसानी से आपके उत्पादन रिलीज़ से हटा दिया जाता है।

विवरण:

1) यह मानते हुए कि आप लागू कर रहे हैं MyService, भी बनाएँ MyServiceDebug। दोनों को ServiceBaseसरणी में इस Program.csतरह जोड़ें :

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService(),
            new MyServiceDebug()
        };
        ServiceBase.Run(ServicesToRun);
    }

2) सेवा परियोजना के लिए प्रोजेक्ट इंस्टॉलर में वास्तविक सेवा और डिबग सेवा जोड़ें:

यहां छवि विवरण दर्ज करें

जब आप सेवा प्रोजेक्ट आउटपुट को सेवा के लिए सेटअप प्रोजेक्ट में जोड़ते हैं तो दोनों सेवाएं (वास्तविक और डीबग) शामिल हो जाती हैं। स्थापना के बाद, दोनों सेवाएं service.msc MMC प्लगइन में दिखाई देंगी।

3) MMC में डिबग सेवा शुरू करें।

4) विजुअल स्टूडियो में, डिबगर को डीबग सेवा द्वारा शुरू की गई प्रक्रिया से जोड़ते हैं।

5) वास्तविक सेवा शुरू करें और डिबगिंग का आनंद लें।


5

जब मैं एक सेवा लिखता हूं तो मैं एक dll परियोजना में सभी सेवा तर्क रखता हूं और दो "मेजबान" बनाता हूं जो इस dll में कॉल करते हैं, एक विंडोज सेवा है और दूसरा एक कमांड लाइन एप्लिकेशन है।

मैं डिबगिंग के लिए कमांड लाइन एप्लिकेशन का उपयोग करता हूं और डिबगर को वास्तविक सेवा में केवल उन बगों के लिए संलग्न करता हूं जिन्हें मैं कमांड लाइन एप्लिकेशन में पुन: पेश नहीं कर सकता।

मैं आपको इस दृष्टिकोण का उपयोग करता हूं बस याद रखें कि आपको वास्तविक सेवा में चलते समय सभी कोड का परीक्षण करना होगा, जबकि कमांड लाइन टूल एक अच्छा डिबगिंग सहायता है यह एक अलग वातावरण है और यह वास्तव में एक वास्तविक सेवा की तरह व्यवहार नहीं करता है।


4

Windows सेवा को विकसित और डीबग करते समय मैं आमतौर पर / कंसोल स्टार्टअप पैरामीटर को जोड़कर और इसे चेक करके कंसोल एप्लिकेशन के रूप में चलाता हूं। जीवन को बहुत आसान बना देता है।

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}

जब तक आपको सेवा विशिष्ट मुद्दों को डीबग करना होगा।
लेप्पी

सही है, तो आपको डिबगर को वास्तविक सेवा प्रक्रिया में संलग्न करना होगा। लेकिन ज्यादातर मामलों में बग या तो प्रकट होने वाले हैं और विकास बहुत आसान है।
मौरिस

4

पहली पंक्ति में Debugger.Break () के बारे में कैसे?


2

Windows सेवाओं को डीबग करने के लिए मैं GFlags और regedit द्वारा बनाई गई एक .reg फ़ाइल को संयोजित करता हूं।

  1. Exe-name और vsjitdebugger निर्दिष्ट करते हुए GFlags चलाएँ
  2. Regedit चलाएं और उस स्थान पर जाएं जहां GFlags उसके विकल्प सेट करता है
  3. फ़ाइल-मेनू से "निर्यात कुंजी" चुनें
  4. उस फ़ाइल को .reg एक्सटेंशन के साथ कहीं सहेजें
  5. कभी भी आप सेवा को डीबग करना चाहते हैं: .reg फ़ाइल पर डबल क्लिक करें
  6. यदि आप डीबगिंग को रोकना चाहते हैं, तो दूसरी .reg फ़ाइल पर डबल क्लिक करें

या निम्नलिखित स्निपेट को सहेजें और वांछित निष्पादन योग्य नाम के साथ servicename.exe को बदलें।


debugon.reg:

Windows रजिस्ट्री संपादक संस्करण 5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image फ़ाइल निष्पादन विकल्प \ servicename.exe]
"GlobalFlag" = "0x00000000"
"डीबगर" = "vsjitdebugger.exe"

debugoff.reg:

Windows रजिस्ट्री संपादक संस्करण 5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image फ़ाइल निष्पादन विकल्प \ servicename.exe]
"GlobalFlag" = "0x00000000"

क्या यह अभी भी विन 7 / विन 2008 पर काम करता है? यह support.microsoft.com/kb/824344 से आ रहा है, लेकिन यह इंटरेक्टिव सेवाओं पर निर्भर करता है, और मुझे लगा कि वे मारे गए हैं? यह हमेशा मेरा पसंदीदा विकल्प हुआ करता था (चूंकि स्टार्टअप के मुद्दे उत्पादन में आ सकते हैं, जहां कोड में एक डिबगर.ब्रिक () को शामिल करना एक विकल्प नहीं हो सकता है)।
piers7

1

रूटीन छोटे-सामान की प्रोग्रामिंग के लिए मैंने अपनी सेवा को आसानी से डीबग करने के लिए एक बहुत ही सरल ट्रिक की है:

सेवा के शुरू होने पर, मैं एक कमांड लाइन पैरामीटर "/ डिबग" के लिए जांच करता हूं। यदि इस पैरामीटर के साथ सेवा को कॉल किया जाता है, तो मैं सामान्य सेवा स्टार्टअप नहीं करता हूं, लेकिन इसके बजाय सभी श्रोताओं को शुरू करें और बस एक संदेशबॉक्स प्रदर्शित करें "प्रगति में डिबग, समाप्त करने के लिए ठीक दबाएं"।

इसलिए यदि मेरी सेवा सामान्य तरीके से शुरू की जाती है, तो यह सेवा के रूप में शुरू होगी, अगर इसे कमांड लाइन पैरामीटर / डीबग के साथ शुरू किया जाता है, तो यह एक सामान्य कार्यक्रम की तरह काम करेगा।

VS में मैं डिबगिंग पैरामीटर के रूप में सिर्फ / डिबग जोड़ूंगा और सीधे सेवा कार्यक्रम शुरू करूंगा।

इस तरह मैं सबसे छोटी तरह की समस्याओं के लिए आसानी से डिबग कर सकता हूं। बेशक, कुछ सामान को अभी भी सेवा के रूप में डिबग करना होगा, लेकिन 99% के लिए यह काफी अच्छा है।



1

मैं JOP के उत्तर पर भिन्नता का उपयोग करता हूं। कमांड लाइन मापदंडों का उपयोग करके आप आईडीई में प्रोजेक्ट गुणों के साथ या विंडोज सेवा प्रबंधक के माध्यम से डिबगिंग मोड सेट कर सकते हैं।

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}

1

मौजूदा विंडोज सर्विस प्रोग्राम पर परेशानी की शूटिंग के लिए, अन्य लोगों द्वारा सुझाए गए अनुसार 'डीबगर.ब्रिक ()' का उपयोग करें।

नए विंडोज सर्विस प्रोग्राम के लिए, मैं जेम्स माइकल हरे की विधि http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable -windows-service-template- का उपयोग करने का सुझाव दूंगा redux.aspx


1

बस अपना डिबगर लंच कहीं भी डाल दें और स्टार्टअप पर विजुअलस्टडियो संलग्न करें

#if DEBUG
    Debugger.Launch();
#endif

इसके अलावा, आपको वीएस को प्रशासक के रूप में शुरू करने की आवश्यकता है और आपको अनुमति देने की आवश्यकता है, कि एक प्रक्रिया को एक अलग उपयोगकर्ता द्वारा डिबग किया जा सकता है (जैसा कि यहां बताया गया है ):

reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f

1

नई सेवा ऐप बनाने के लिए Windows सेवा टेम्पलेट C # प्रोजेक्ट का उपयोग करें https://github.com/HarpyWar/windows-service-tplplate

कंसोल / सर्विस मोड का स्वतः पता लगाया जाता है, आपकी सेवा के ऑटो इंस्टॉलर / इंस्टॉलर और कई सबसे अधिक उपयोग की जाने वाली सुविधाएँ शामिल हैं।


1

यहां वह सरल विधि है जिसका उपयोग मैंने सेवा का परीक्षण करने के लिए किया, बिना किसी अतिरिक्त "डीबग" के तरीकों के साथ और एकीकृत वीएस यूनिट टेस्ट के साथ।

[TestMethod]
public void TestMyService()
{
    MyService fs = new MyService();

    var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    OnStart.Invoke(fs, new object[] { null });
}

// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
     string[] par = parameters == null ? null : parameters.ToArray();

     var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

     OnStart.Invoke(service, new object[] { par });
}

1
static class Program
{
    static void Main()
    {
        #if DEBUG

        // TODO: Add code to start application here

        //    //If the mode is in debugging
        //    //create a new service instance
        Service1 myService = new Service1();

        //    //call the start method - this will start the Timer.
        myService.Start();

        //    //Set the Thread to sleep
        Thread.Sleep(300000);

        //    //Call the Stop method-this will stop the Timer.
        myService.Stop();

         #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };

        ServiceBase.Run(ServicesToRun);
         #endif
    }
}

यह आसान है। बस डिबग सेटिंग समाधान कॉन्फ़िगर करें, प्रोजेक्ट / समाधान चलाएँ, जैसे ही आप जाते हैं, ब्रेकप्वाइंट जोड़ें।
बहमुत

0

डिबगिंग करने के लिए आपके पास दो विकल्प हैं।

  1. एक लॉग फ़ाइल बनाएं: व्यक्तिगत रूप से मैं एप्लिकेशन लॉग या ईवेंट लॉग का उपयोग करके टेक्स्ट फ़ाइल की तरह एक अलग लॉग फ़ाइल पसंद करता हूं।
  2. एप्लिकेशन को कंसोल एप्लिकेशन में कनवर्ट करें: यह आपको सभी डिबगिंग टूल को सक्षम करेगा, जिसे हम वी.एस. में उपयोग कर सकते हैं।

कृपया इस विषय को देखें जो मैंने इस विषय के लिए बनाया था।


0

बस पेस्ट करें

Debugger.Break();

कोई भी जहाँ आप कोड में।

उदाहरण के लिए ,

internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main()
        {
            Debugger.Break();
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

Debugger.Break();जब आप अपना प्रोग्राम चलाएंगे तो यह हिट हो जाएगा ।


0

सबसे अच्छा विकल्प ' System.Diagnostics ' नामस्थान का उपयोग करना है ।

डिबग मोड और रिलीज़ मोड के लिए यदि ब्लॉक और डिबग स्टूडियो में रिलीज़ मोड के बीच स्विच करने के लिए नीचे दिखाया गया है, तो अपना कोड संलग्न करें,

#if DEBUG  // for debug mode
       **Debugger.Launch();**  //debugger will hit here
       foreach (var job in JobFactory.GetJobs())
            {
                //do something 
            }

#else    // for release mode
      **Debugger.Launch();**  //debugger will hit here
     // write code here to do something in Release mode.

#endif
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.