2010-06-27 2 views
14

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

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

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

ऑपरेशन के इस अपाचे-जैसे मोड को कैसे प्राप्त किया जा सकता है? मेरा मानना ​​है कि समाधान सरल है, लेकिन मुझे वास्तव में कोई विचार नहीं है कि कहां से शुरू करना है।

निम्नानुसार कोड का टुकड़ा सेवा का आह्वान करने के लिए उपयोग किया जाता है। क्या इसे स्टैंडअलोन उपयोग की अनुमति देने के लिए संशोधित किया जा सकता है?

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    static void Main() 
    { 
     ServiceBase[] ServicesToRun; 
     ServicesToRun = new ServiceBase[] 
     { 
      new Service() // defined elsewhere as Service : ServiceBase 
     }; 
     ServiceBase.Run(ServicesToRun); 
    } 
} 

मेरी पसंद की भाषा सी # है।

संपादित करें: अलग विधानसभा में वर्तमान में, मैं निकाला गया है आम कोड (इसे Library.dll कॉल), और मैं दो निष्पादनयोग्य है: क्रमशः Console.exe और Service.exe, जो स्टैंडअलोन और खिड़कियों सेवा अनुप्रयोगों कर रहे हैं, , और दोनों पुस्तकालय.dll का आह्वान करने के लिए सिर्फ साधन हैं।

मेरा लक्ष्य उन दो निष्पादकों को एक में विलय करना है, जो अभी भी Library.dll पर कॉल करेंगे।

उत्तर

7

कुछ खोदने के बाद, मैंने अंततः नीचे देखा है।नेट हूड (System.ServiceProcess.ServiceBase.Run विधि), यह सुनिश्चित करने के लिए कि यह Environment.UserInteractive बूल जांचता है यह सुनिश्चित करने के लिए कि निष्पादन योग्य अंतःक्रियात्मक रूप से नहीं चल रहा है।

oversimplified समाधान है कि मेरे लिए काम करता है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     if (!Environment.UserInteractive) 
     { 
      ServiceBase[] ServicesToRun; 
      ServicesToRun = new ServiceBase[] 
      { 
       // Service.OnStart() creates instance of MainLib() 
       // and then calls its MainLib.Start() method 
       new Service() 
      }; 
      ServiceBase.Run(ServicesToRun); 
      return; 
     } 

     // Run in a console window 
     MainLib lib = new MainLib(); 
     lib.Start(); 
     // ... 
    } 
} 
+3

सावधान रहें: Environment.UserInteractive का उपयोग केवल यह जांचने के लिए किया जाता है कि कोई ग्राफिकल डेस्कटॉप सत्र है या नतीजा केवल यह निर्धारित करने के लिए उपयोग किया जाता है कि कोई संवाद या कंसोल संदेश दिखाना है या नहीं। डेस्कटॉप के साथ बातचीत करने की अनुमति देने वाली सेवा के रूप में चलते समय UserInteractive भी सही होगा। वास्तविक जांच मूल तरीकों के भीतर की जाती है। – Ishmaeel

+0

@ इश्मीएल: धन्यवाद, अच्छा बिंदु। पता नहीं था कि इन दो तरीकों से संबंधित थे। क्या आपके पास देशी तरीकों का एक उदाहरण है जो इसकी जांच कर सकता है? –

+1

स्पष्ट रूप से, सर्विसबेस केवल StartServiceCtrlDispatcher फ़ंक्शन (http://msdn.microsoft.com/en-us/library/ms686324(VS.85).aspx) को कॉल करता है और एक गैर-शून्य वापसी मूल्य (संभवतः) का अर्थ है कि आपको सेवा के रूप में लॉन्च नहीं किया गया है । बेशक, यह चेक के रूप में उपयोगी नहीं है क्योंकि यह एक बहुत ही ऑपरेशन है जिसे आप तय करना चाहते हैं कि निष्पादित करना है या नहीं। मैं अभी तक एक उचित चेक फ़ंक्शन नहीं ढूंढ पा रहा हूं। – Ishmaeel

0

उदाहरण में आप साइट पर, मुझे पूरा भरोसा है कि अपाचे ऐप सी या सी ++ में लिखा गया है। इसके लिए, आपको सर्विसमेन फ़ंक्शन की आवश्यकता होगी। यदि आप इसे सामान्य कार्यक्रम की तरह निष्पादित करते हैं, तो मुख्य कहलाता है। यदि आप उस पर सेवा नियंत्रण प्रबंधक को इंगित करते हैं, तो सेवामेन को इसके बजाय बुलाया जाता है।

सी # के संबंध में, यह नहीं कह सकता कि मैं इसके बारे में जानता हूं। अगर मुझे सी # में एक सेवा लिखनी पड़ी, तो मुझे लगता है कि मैं यहां शुरू करूंगा - http://msdn.microsoft.com/en-us/library/bb483064.aspx

3

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

जो आप यहां वर्णन कर रहे हैं उसे केवल अधिक अमूर्तता की आवश्यकता है। "सेवा" की कार्यक्षमता को कड़ाई से करने की आवश्यकता नहीं है - विंडोज सेवा कैसे संचालित होती है। उम्मीद है कि

+0

क्या मैं अभी एक पुस्तकालय है कि सभी तर्क होता है। मैं स्टैंडअलोन कंसोल एप्लिकेशन और सेवा अनुप्रयोग से एक ही लाइब्रेरी का आह्वान करता हूं। जो मैं खोज रहा हूं वह दो निष्पादन योग्यों को एक में विलय करने का एक तरीका है। तो, Console.exe और Service.exe दोनों को Library.dll पर कॉल करें, और मैं एकल ConsoleAndService.exe रखना चाहता हूं, जो Library.dll को कॉल करता है :) –

+0

कंसोल एप्लिकेशन के लिए प्रविष्टि-बिंदु एक स्थिर मुख्य() विधि है। सेवा के लिए प्रवेश बिंदु एक वर्ग है जो सर्विसबेस से प्राप्त होता है - और ऑनस्टार्ट() और ऑनस्टॉप() को कॉल किया जाता है। कोई संघर्ष नहीं होना चाहिए। लेकिन अनुभवी रूप से यदि आपको लगता है कि ऐसा है, तो मुझे नहीं लगता कि अलग-अलग निष्पादन योग्य होने के लिए यह अनुचित है। आखिरकार, वे पूरी तरह से अलग तरीके से भाग लेंगे। उम्मीद है कि –

+0

मदद करता है बेशक, यह अलग निष्पादन योग्य होने के लिए पूरी तरह से स्वीकार्य है। यदि संभव हो तो मैं उन्हें मर्ज करने का एक तरीका ढूंढ रहा था। यदि नहीं, तो, यह काम करना जारी रखेगा क्योंकि यह पहले से ही करता है। –

10

सी # में, इसे करने का एक आसान तरीका यह है कि इसे सेवा के रूप में चलाने के लिए कमांड लाइन तर्क की आवश्यकता होती है। यदि तर्क नहीं है, तो अपना फॉर्म/कंसोल ऐप चलाएं।

C:\MyApp\MyApp.exe -service 

वह कुछ इस तरह दिखेगा:: तो फिर सिर्फ अपने संस्थापक निष्पादन योग्य पथ में तर्क शामिल जब सेवा स्थापित करने तो यह लग रहा है तो तरह है

static void Main(string[] args) 
{ 
    foreach (string arg in args) 
    { 
     //Run as a service if our argument is there 
     if (arg.ToLower() == "-service") 
     { 
      ServiceBase[] servicesToRun = new ServiceBase[] { new Service1() }; 
      ServiceBase.Run(servicesToRun); 
      return; 
     } 
    } 

    //Run the main form if the argument isn't present, like when a user opens the app from Explorer. 
    Application.Run(new Form1()); 
} 

यह सिर्फ एक देने के लिए उदाहरण है आप एक विचार है, इस कोड को लिखने के लिए शायद क्लीनर तरीके हैं।

+0

यही वह है जो मैं पहले देख रहा था, लेकिन मुझे installutil के लिए तर्क पारित करने का कोई तरीका नहीं मिला, ताकि सेवा कुछ तर्क के साथ शुरू हो सके। ऐसा करने का एक और तरीका अंतःक्रियात्मक रूप से चलाने के लिए तर्क की आवश्यकता होगी, लेकिन यह इतना आसान नहीं है। यह देखने के लिए मेरा जवाब देखें कि मैंने अंत में इसे कैसे किया। बहुत आसान। –

+0

वैसे भी, क्या आप मुझे बता सकते हैं कि installutil के लिए तर्क कैसे पास किया जाए, ताकि मैं भविष्य में जान सकूं? –