C# Windows Service에서 디비깅을 쉽게 하는 방법

Windows Service에서 디비깅을 쉽게 하는 방법은 까다롭다. 실행프로그램을 배포해 놓고 Log를 작성해서 결과를 확인해야 하는 번거로움이 있다.
찾아 보면 아래의 참조와 같은 방법을 사용해도 되기는 하겠지만 간단한 방법을 검토 해보자

http://devsw.tistory.com/153
https://msdn.microsoft.com/ko-kr/library/cktt23yw.aspx
http://www.codeproject.com/Articles/10153/Debugging-Windows-Services-under-Visual-Studio-NET
http://blog.aliencube.org/ko/2014/04/30/developing-windows-service-with-topshelf/

이글에서 설명하는 방법은  Serviced의 Method를 호출하는 코드를 작성하여 Service를 제어하여 쉽게 Debugging하는 방법 이다.. 간단하게 아래와 같이 서비스 메서드를 호출 하여 동작을 확인하고 코드를 수정하면 된다.
그러나 이 방법은 실제 서비스 프로그램이 배포 되었을 때와 동작이 다르므로 배포후 확인은 별도로 해애한다 
MethodInfo onStartMethod = typeof(ServiceBase).GetMethod(“OnStart”,
BindingFlags.Instance | BindingFlags.NonPublic); 
onStartMethod?.Invoke(service, new object[] { new string[] { } });

Service Test를 위한 윈도우 폼을 하나 만든다음 서버스를 제어하는 코드를 추가한다.

그리고 버튼이벤트 및 생성자를 아래의 코드와 같이 작성한다. 
ServiceRunner.cs

namespace MyWinService
{
    public partial class ServiceRunner : Form
    {
        private readonly ServiceBase[] _theService;
        private readonly MethodInfo onStartMethod;
        private readonly MethodInfo onStopMethod;
        private readonly MethodInfo onPauseMethod;
        private readonly MethodInfo onContinueMethod;
        public ServiceRunner(ServiceBase[] servicesToRun)
        {           
            InitializeComponent();
            #region GetMethodInfo
            onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
               BindingFlags.Instance | BindingFlags.NonPublic);

            onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
               BindingFlags.Instance | BindingFlags.NonPublic);

            onPauseMethod = typeof(ServiceBase).GetMethod("OnPause",
               BindingFlags.Instance | BindingFlags.NonPublic);

            onContinueMethod = typeof(ServiceBase).GetMethod("OnContinue",
               BindingFlags.Instance | BindingFlags.NonPublic);
            _theService = servicesToRun;
            #endregion
            Show();
        }

        private void startButton_Click(object sender, EventArgs e)
        {        
            toolStripStatusLabel1.Text = "Started";
            foreach (ServiceBase service in _theService)
            {               
                onStartMethod?.Invoke(service, new object[] { new string[] { } });               
            }
        }
        private void pauseButton_Click(object sender, EventArgs e)
        {            
            toolStripStatusLabel1.Text = "Paused";
            foreach (ServiceBase service in _theService)
            {
                onPauseMethod?.Invoke(service, null);
            }
        }
        private void continueButton_Click(object sender, EventArgs e)
        {            
            toolStripStatusLabel1.Text = "Started";
            foreach (ServiceBase service in _theService)
            {
                onContinueMethod?.Invoke(service, null);
            }
        }
        private void stopButton_Click(object sender, EventArgs e)
        {           
            toolStripStatusLabel1.Text = "Stopped";
            foreach (ServiceBase service in _theService)
            {              
                onStopMethod?.Invoke(service, null);               
            }
        }
}

program.cs

namespace MyWinService
{
    static class Program
    {
        ///
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// 
        static void Main(string[] args)
        {            
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
               new Service1()
            };
#if DEBUG
   System.Windows.Forms.Application.Run(new ServiceRunner(ServicesToRun));
#else
            ServiceBase.Run(ServicesToRun);
#endif
        }
    }
}

Service1.cs

namespace MyWinService
{
    partial class Service1 : ServiceBase
    {
        private System.Diagnostics.EventLog eventLog1;
        System.Timers.Timer timer = new System.Timers.Timer();
        public Service1()
        {
            InitializeComponent();
            this.eventLog1 = new System.Diagnostics.EventLog();
            if (!System.Diagnostics.EventLog.SourceExists("Test Source"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                    "Test Source", "MyNewLog");
            }
            eventLog1.Source = "Test Source";
            eventLog1.Log = "MyNewLog";
        }
        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("MyWinService Started", EventLogEntryType.Information);            
            timer.Interval = 20000; // 20 seconds
            timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
            timer.Start();
        }

        protected override void OnPause()
        {
            timer.Stop();
            eventLog1.WriteEntry("MyWinService OnPause", EventLogEntryType.Information);
        }

        protected override void OnContinue()
        {
            timer.Start();
            eventLog1.WriteEntry("MyWinService OnContinue", EventLogEntryType.Information);
        }
        protected override void OnStop()
        {
            eventLog1.WriteEntry("MyWinService Stoped", EventLogEntryType.Information);
        }

        private void OnTimer(object sender, ElapsedEventArgs e)
        {
            string message = ServiceName + " is beeping "+ string.Format("{0:d/M/yyyy HH:mm:ss}", DateTime.Now);
            System.Media.SystemSounds.Exclamation.Play();
            eventLog1.WriteEntry(message, EventLogEntryType.Information);
        }        
    }
}

Try Icon 메뉴로 디버깅 만들기

Program.cs

static class Program
{
        ///
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// 
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new ServiceProcess()
            };
#if DEBUG
            using (ServiceController pL = new ServiceController(ServicesToRun))
            {
                // Make sure the application runs!
                pL.Display();
                Application.Run();
            }
#else
            ServiceBase.Run(ServicesToRun);
#endif
}

ServiceController.cs 코드를 추가하여 메뉴와 동작을 추가한다

class ServiceController : IDisposable
{
   private readonly ServiceBase[] _theService;             
   NotifyIcon ni;
   public ServiceController(ServiceBase[] servicesToRun)
   {            
      _theService = servicesToRun;         
       ni = new NotifyIcon();
   }
  public void Dispose()
  {
      ni.Dispose();           
  }
  public ContextMenuStrip CreateContext()
  {
            // Add the default menu options.
            ContextMenuStrip menu = new ContextMenuStrip();
            ToolStripMenuItem item;
            ToolStripSeparator sep;

            item = new ToolStripMenuItem();
            item.Text = Properties.Resources.Start;
            item.Click += new EventHandler(Start);
            item.Image = Properties.Resources.CONGUIIMG;            
            menu.Items.Add(item);

            // pause.
            item = new ToolStripMenuItem();
            item.Text = Properties.Resources.Pause;
            item.Click += new EventHandler(Pause);
            item.Image = Properties.Resources.Pauseimg;
            menu.Items.Add(item);
            // restart.
            item = new ToolStripMenuItem();
            item.Text = Properties.Resources.Restart;
            item.Click += new EventHandler(Restart);
            item.Image = Properties.Resources.Restartimg;
            menu.Items.Add(item);

            // Windows Explorer.
            item = new ToolStripMenuItem();
            item.Text = Properties.Resources.Stop;
            item.Click += new EventHandler(Stop);
            item.Image = Properties.Resources.CONGUIOFFIMG;
            menu.Items.Add(item);            
            
            return menu;
 }
 /// Displays the icon in the system tray. 
 public void Display()
{
 // Put the icon in the system tray and allow it react to mouse clicks.//
  ni.MouseClick += new MouseEventHandler(ni_MouseClick);
  ni.Icon = Properties.Resources.CONGUI;
  ni.Text = "Launcher Application";
  ni.Visible = true;

  // Attach a context menu.
   ni.ContextMenuStrip = CreateContext();            
  }
  void Start(object sender, EventArgs e)
  {
          MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
          BindingFlags.Instance | BindingFlags.NonPublic);

         foreach (ServiceBase service in _theService)
         {
           onStartMethod?.Invoke(service, new object[] { new string[] { } });
         }

          ToolStripMenuItem item = (ToolStripMenuItem)sender;

          item.Visible = false;
          ni.ContextMenuStrip.Items[1].Visible = true;
          ni.ContextMenuStrip.Items[0].Visible = true;
          ni.Icon = Properties.Resources.CONGUI;          
        }
void Restart(object sender, EventArgs e)
{
            MethodInfo onContinueMethod = typeof(ServiceBase).GetMethod("OnContinue",
                BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in _theService)
            {
                onContinueMethod?.Invoke(service, null);
            }
}
void Pause(object sender, EventArgs e)
{
            MethodInfo onPauseMethod = typeof(ServiceBase).GetMethod("OnPause",
               BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in _theService)
            {
                onPauseMethod?.Invoke(service, null);
            }

}
void Stop(object sender, EventArgs e)
{
            MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
              BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in _theService)
            {
                onStopMethod?.Invoke(service, null);
            }
        }

}

“C# Windows Service에서 디비깅을 쉽게 하는 방법”의 24개의 댓글

  1. Hello there, just became aware of your blog through Google, and found that it
    is really informative. I’m going to watch out for brussels.
    I will be grateful if you continue this in future. Numerous people will be benefited from your writing.

    Cheers!

    Check out my homepage – 선릉안마

  2. CBD or Cannabidiol is a very interesting medicine since it is entirely untapped and the oil is drawn out from one more
    plant that does not contribute to international warming at all!
    It has been found to be extremely reliable in treating many
    types of diseases such as joint inflammation, clinical depression,
    anxiousness, nausea, epilepsy, erectile dysfunction and also much
    more. The oil is originated from the marijuana plant as well as
    has actually been made use of for years in the United States, in Mexico, in Canada, in Russia as well as several
    European countries.

    Feel free to visit my webpage: CBD oil

  3. Undeniably consider that that you said. Your favourite reason appeared to
    be on the web the simplest thing to take into account of.
    I say to you, I certainly get irked at the same time as other folks think about
    worries that they plainly do not understand about. You controlled to hit the nail upon the top as smartly as outlined out the
    entire thing with no need side-effects , people
    can take a signal. Will probably be again to get more.
    Thank you

  4. Cannabidiol, or CBD as it is understood medically, is an important component in numerous clinical cannabis supplements.
    It is estimated that the large bulk of energetic ingredients in today’s industrial marijuana supplements
    are comprised of CBD. This is unusual due to the fact that when you consider it, CBD is not actually
    a “cannabis” active ingredient in any way.
    Rather, it is a plant component that has been discovered
    to be very valuable in the context of certain medical problems such as persistent discomfort,
    queasiness, seizures, clinical depression, stress and anxiety, and nausea or vomiting.
    To this particular day, the CBD is the only approved prescription drug in the USA that is solely originated from plants.

    My web blog best CBD oils UK

  5. you’re in reality a just right webmaster. The website loading velocity is incredible.
    It seems that you’re doing any unique trick.

    In addition, The contents are masterwork. you’ve performed a fantastic
    process in this subject!

  6. My partner and I stumbled over here by a different web address and thought I might as well check things out.
    I like what I see so now i am following you. Look forward to
    exploring your web page repeatedly.

  7. Simply desire to say your article is as astonishing. The clearness in your post is
    just nice and i can assume you are an expert on this subject.

    Well with your permission allow me to grab your feed to keep
    up to date with forthcoming post. Thanks a million and please
    continue the enjoyable work.

    Here is my web blog – 먹튀사이트

  8. We’re a group of volunteers and starting a
    new scheme in our community. Your web site provided us with useful info
    to work on. You have performed a formidable job and our entire group might be thankful
    to you.

  9. Hi would you mind letting me know which web host you’re working with?
    I’ve loaded your blog in 3 different browsers and I must say this
    blog loads a lot faster then most. Can you suggest
    a good web hosting provider at a honest price? Kudos, I appreciate
    it!

  10. Hi there! I understand this is kind of off-topic
    but I needed to ask. Does operating a well-established website like yours take a massive amount
    work? I am brand new to operating a blog however I do write in my diary every day.
    I’d like to start a blog so I can share my personal experience and feelings online.
    Please let me know if you have any kind of ideas or tips for brand new
    aspiring blog owners. Appreciate it!

    Feel free to visit my homepage :: 사설토토

  11. พนันบอล เว็บไซต์พนันบอล มาตรฐานระดับนานาชาติ รับรองอันดับ 1 โดย Google บริการตลอด 1 วัน มีพนักงานมืออาชีพที่คอยให้บริการและให้คำปรึกษาในทุกคำถามตลอด 1 วัน ตรงนี้คือที่สุดของระบบ สมัครเป็นสมาชิก กับ Call Center ที่เยี่ยมที่สุด ทันสมัยที่สุดใน
    คาสิโนออนไลน์ และก็ฝาก-ถอน ทันใจใน 5 นาที ผ่านทุกแบงค์ชั้นแนวหน้า สมัครพนันบอลออนไลน์ ได้ตลอด 24 ชั่วโมง แม้ว่าคุณอยากใช้บริการ UFABET1688 เพื่อติดตามข้อมูลต่างๆของวงการฟุตบอล
    รวมทั้งการแทงบอลด้วย คุณควรต้องทราบสิ่งต่างๆเหล่านี้ก่อน เพื่อให้คุณรู้เรื่อง แล้วก็สามารถเล่นบอลได้อย่างมีคุณภาพสูงสุด

답글 남기기