DCSIMG
תמיכה ב WindowsService בזמן פיתוח - Yitzhak Gootvilig's Blog

Yitzhak Gootvilig's Blog

תמיכה ב WindowsService בזמן פיתוח

בעבודה עם WindowsService קיימת אי נוחות בסביבת הפיתוח.

  • אי אפשר סתם כך להריץ אותו ב VisualStudio (לא ניתן ללחוץ F5 ולהריץ).
  • יש צורך להוסיף שורה שטוענת את ה Debugger , זו שורה שנוספת לקוד על כל המשתמע מכך, ויש גם לדאוג שלא תופיע בסביבת Realese.
  • לא ניתן להדפיס הודעות ל Console

סדרת פוסטים זו , נועדה כדי לפתור בעיות אלו.

הרצת ה Service כ Console בזמן debug.

כדי להריץ את ה Service בלחיצת F5 (או סתם כך משורת הפקודה) , יש ליצור הבחנה בין הסביבה בה רצה האפליקציה כ Service לבין הסביבה בה רצה האפליקציה שלא כ Service.

הפתרון הפשוט הוא, לבצע אבחנה האם למשתמש יש אינטראקציה עם שלחן העבודה. למי אין? ל WindowsService (אלא אם כן הוגדר אחרת – ולזה ניתן פתרון אחר).

בעת עליית המערכת נבדוק:

            if (Environment.UserInteractive())

בדיקה זו תספק כמעט את כל הפתרון, וכך נוכל לבדל בין שתי סביבות ההרצה.

            if (Environment.UserInteractive)

            {

                RunServiceInConsole();

            }

            else

            {

                RunAsWindowsService();

            }

המתודה RunAsWindowsService תספק את המימוש הרגיל

        private static void RunService()

        {

            ServiceBase.Run(new[] { new MyService() });

        }

המתודה RunServiceInConsole תקרא למתודות של ה Service באמצעות Reflection:

 private static void RunServiceInConsole(string[] args)
 {
  MyService service = new MyService();
    service.Start(args);
 Console.WriteLine("Press <ENTER> to terminate service.");
    Console.ReadLine();
    service.Stop();
 }

המתודה service.Start אינה קיימת, אלא זו הרחבה:

public static class WindowsServiceHelper

{

    private static MethodInfo MethodInfo { get; set; }

    public static void Start(
                          this ServiceBase service, string[] args)

    {

        if (MethodInfo == null)

        {

            MethodInfo = service.GetType()
                         .GetMethod("OnStart",
                BindingFlags.Instance | BindingFlags.NonPublic);

           
            Debug.Assert(MethodInfo != null
                         , "Can't get method OnStart");

        }

        MethodInfo.Invoke(service, new[] { args })

}

}

בשיטה המתוארת כאן, נוכל להריץ את ה Service שלנו משורת הפקודה, והוא יריץ אותו כאפליקצית Console רגילה.

במידה ובחרנו שלService שלנו תהיה אינטראקציה עם ה desktop הפתרון המוצע כאן לא יועיל. למקרה זה יהיה פתרון ב post נוסף.

נקודה נוספת שחשוב להדגיש היא, שיש לשנות את סוג הפרויקט ל Console Application

 

כמובן שעדיף לשפר את הפתרון, ולהשתמש לשם כך ב generics:

public static class WindowsServiceRunner<TService>
where TService : ServiceBase, new()

{

    public static void Run(string[] args, string serviceName)

    {

       if (Environment.UserInteractive)

       {

           RunServiceInConsole(args);

       }

       else

       {

           RunService();

       }

    }

private static void RunService()
{
    ServiceBase.Run(new[] { new TService() });
}

private static void RunServiceInConsole(string[] args)
{
    TService service = new TService();
    service.Start(args);

         Console.WriteLine("Press <ENTER> to terminate service.");

         Console.ReadLine();

         service.Stop();

     }

}

להורדת הקוד לכל הסדרה

הפוסטים הבאים:

תוכן התגובה

משה כתב/ה:

אהבתי! :-)

# June 20, 2010 1:28 AM

Yitzhak Gootvilig's Blog כתב/ה:

post זה הוא המשך של קודמו: תמיכה ב WindowsService בזמן פיתוח בזמן שננצל את היכולת שהוצגה בpost הקודם

# June 21, 2010 9:25 PM

Yitzhak Gootvilig's Blog כתב/ה:

post זה הוא השלישי והאחרון בסדרה אודות תמיכה ב WindowsService בסביבת פיתוח קדמו לו: תמיכה ב WindowsService

# June 21, 2010 10:41 PM

Yitzhak Gootvilig's Blog כתב/ה:

post זה הוא השלישי והאחרון בסדרה אודות תמיכה ב WindowsService בסביבת פיתוח קדמו לו: תמיכה ב WindowsService

# June 22, 2010 10:52 PM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 6 and 5 and type the answer here:


Enter the numbers above: