Windows Service 專案並不能直接按 F5 進入除錯模式,這對開發人員來說還挺麻煩的,對 Windows Service 專案按下 F5,它會不客氣的跳出一個對話視窗
以往我會透過專案分層的方式來解決這個問題,Console App 和 Windows Service 兩者都依賴 BLL,BLL 處理邏輯依賴 DAL,DAL 處理IO(SQL | CSV);開發時預設專案選 Console App,佈署用 Windows Service
一次要維護兩個專案有點累,現在我要用一小技巧來將他們合併,原本 BLL.WinService 裡的 Program 如下:
namespace BLL.WinService
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
現在把它變這樣
namespace BLL.WinService
{
internal static class Program
{
///// <summary>
///// The main entry point for the application.
///// </summary>
//static void Main()
//{
// ServiceBase[] ServicesToRun;
// ServicesToRun = new ServiceBase[]
// {
// new Service1()
// };
// ServiceBase.Run(ServicesToRun);
//}
private static void Main(string[] args)
{
// Run Service
ServiceBase[] services =
{
new Service1()
};
if (Environment.UserInteractive)
{
RunInteractive(services);
}
else
{
ServiceBase.Run(services);
}
}
public static void RunInteractive(ServiceBase[] services)
{
Console.WriteLine();
Console.WriteLine("Install the services in interactive mode.");
Console.WriteLine();
// Get the method to invoke on each service to start it
var onStartMethod =
typeof(ServiceBase).GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
// Start services loop
foreach (var service in services)
{
Console.WriteLine("Installing {0} ... ", service.ServiceName);
onStartMethod.Invoke(service, new object[] {new string[] { }});
Console.WriteLine("Installed {0} ", service.ServiceName);
Console.WriteLine();
}
// Waiting the end
Console.WriteLine("Press a key to uninstall all services...");
Console.ReadKey();
Console.WriteLine();
// Get the method to invoke on each service to stop it
var onStopMethod = typeof(ServiceBase).GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
// Stop loop
foreach (var service in services)
{
Console.Write("Uninstalling {0} ... ", service.ServiceName);
onStopMethod.Invoke(service, null);
Console.WriteLine("Uninstalled {0}", service.ServiceName);
}
Console.WriteLine();
Console.WriteLine("All services are uninstalled.");
// Waiting a key press to not return to VS directly
if (Debugger.IsAttached)
{
Console.WriteLine();
Console.Write("=== Press a key to quit ===");
Console.ReadKey();
}
}
}
}
裡面有兩個關鍵:
- Environment.UserInteractive 用來判斷是否為互動模式
- RunInteractive 方法用反射調用 Service 裡的 OnStart 方法
在專案設定:
Output type:Console Application
大功告成,我再也不需要維護另外一個 Console 專案了
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET