在做好一个WPF的程序后,有时候想让它的部分功能以服务的形式安装到Windows系统中,然后以Windows服务的方式运行,而图形界面仅作该服务的配置用途。在此记录一下开发的步骤以备忘。
- 新建一个WPF的App,其实WinForm类之类的大同小异,为了调试的方便,我一般先以普通的App的方式建议项目,然后把所有的配置功能等全做好,测试好,把功能部分全完成。
-
一切就绪好,开始来把这个WPF的App改造使之能支持Windows服务模式运行:
2.1 在解决方案浏览器的项目标题上右击后依次选“添加Add”、“新项目New Item”:
2.2 如下图的步骤操作,第三步给添加的Windows服务取一个名字(这里以这个ServiceWatchdogSwitch为例):
2.3 在解决方案浏览器里双击上面一步添加的服务ServiceWatchdogSwitch.cs,在属性窗口配置好服务的名称(ServiceName属性),接下来在打开的设计视图空白处点右键后在弹出菜单中选“添加安装程序Add Installer”
2.4 在解决方案浏览器里双击服务安装程序,然后在设计视图中分别选中两个安装器分别配置好其属性,包括服务的启动模式、描述、显示名称、运行账号等。服务安装程序是用于用其它工具比如InstallUtil等进行服务安装的时候用的。
2.5 给项目添加新的入口点(entry point)。在项目里添加一个新的类,这里给类起名叫Program,打开类的源代码,用下面的代码替换原有的类:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
string[] args = Environment.GetCommandLineArgs();
var findW = from arg in args
where arg.ToLower() == "w" || arg.ToLower() == "/w" || arg.ToLower() == "-w"
select arg;
if (args.Length == 2 && findW.Count() > 0)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceWatchdogSwitch()
};
ServiceBase.Run(ServicesToRun);
}
else
{
UIMode();
}
}
private static void UIMode()
{
// create a thread
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
var mw = new MainWindow()
{
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen
};
mw.ShowDialog();
Thread.CurrentThread.Abort();
}));
// set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// make the thread a background thread
newWindowThread.IsBackground = true;
// start the thread
newWindowThread.Start();
while (newWindowThread.ThreadState != ThreadState.Stopped) System.Threading.Thread.Sleep(50);
}
}
上面程序中,Main()里决定了,如果程序是带w、/w或者-w参数启动的,那么让它以服务的方式运行,否则调用UIMode()进入图形界面非服务模式。
2.6 在解决方案浏览器上点右键在弹出菜单中点“属性Properties”,在弹出的项目的属性里,将入口点改成Program类如下图:
至此,改装就完成了,只需要将服务妥妥地安装好就行了,注意启动命令要带参数w、/w或者-w。
达叔傻乐(darwin.zuo@163.com)