【问题标题】:Windows Service without Visual Studio interference不受 Visual Studio 干扰的 Windows 服务
【发布时间】:2011-06-24 04:33:58
【问题描述】:

我想在没有 Visual Studio 设计器“帮助”的情况下创建和管理 Windows 服务应用程序。

由于这是 .NET,根据 MSDN 和设计者所做的判断,这意味着从 Installer 继承,并构造和处理 ServiceProcessInstallerServiceInstaller 以便能够管理安装时执行服务。

运行时,这意味着创建一个ServiceBase 子类并使用ServiceBase.RunMain 开始它(并覆盖各种ServiceBase 事件处理方法)。

但是,当我这样做时,Visual Studio 坚持将InstallerServiceBase 子类视为设计器编辑的文件。这并不完全有助于提高可读性,更不用说它通常根本无法处理手写代码。 我想避免设计人员以保持事情的可管理性(以避免模糊的谁知道什么时候运行,特别是对于那些难以测试和调试的代码,例如 Windows 服务,毕竟 必须安装才能运行),并且能够在运行时指定服务名称,而不是在编译时 - 设计者不支持。

如何创建一个 Windows 服务应用程序而不需要所有的垃圾?

【问题讨论】:

  • 您可能想看看 TopShelf 项目 - topshelf-project.com
  • 嗯 - 整洁!看起来有点矫枉过正,还不够成熟,但如果我要写一个新的应用程序,我肯定会考虑。

标签: .net windows-services designer


【解决方案1】:

ServiceBase 派生自 Component。要禁用设计器视图,您可以像这样附加属性:

[System.ComponentModel.DesignerCategory("Code")]
public class MyService : ServiceBase
{

}

【讨论】:

  • 这行得通,如果您在添加继承之前添加此行,则不会创建设计器。
  • 这确实是正确的答案,就像一个冠军!
  • 工作,但我必须删除并重新添加对System.ServiceProcess 的引用才能生效。
【解决方案2】:

好吧,只要删除构造函数中的 InitializeComponent() 调用,设计器生成的代码就不会了。

【讨论】:

  • 那行不通:Visual Studio 是“智能”的:它不关心您是将文件添加为类还是组件 - 重要的是继承层次结构。如果您继承自 Installer 并因此继承自 IComponent,您将获得设计器 - 即使您最初是通过“添加类”创建文件。
  • 我什至尝试在 Installer 之前添加一个废话类 - 它仍然使用设计器。一个(不令人满意的)解决方法是右键单击:打开并选择 CSharp Editor 并将其设置为默认值。这是不令人满意的,因为在另一台机器上新的源代码控制检查将丢失该用户设置并恢复到 please-mss-up-my-code 设计器。
  • 我复制。烦人,不是吗。
【解决方案3】:

由于我经常创建服务,所以这样做:

我有一个如下所示的通用基类:

internal class ServiceRunner : ServiceBase {
   protected static void Startup(string[] args, ServiceRunner instance, bool interactiveWait) {    
    if (instance == null)
        throw new ArgumentNullException("instance");

    if (Environment.UserInteractive) {
        instance.OnStart(args);
        if (interactiveWait) {
            Console.WriteLine("Press any key to stop service");
            Console.ReadKey();
        }
        instance.OnStop();
    }
    else
        Run(instance);
}

然后我像这样创建我的所有服务

internal class MyService : ServiceRunner
{
    public MyService() {
        ServiceName = ConfigurationManager.AppSettings["MyServiceName"];
    }

    private static void Main(string[] args) {
        Startup(args, new MyService(), true);
    }

    protected override void OnStart(string[] args) {
        base.OnStart(args);
        ...
    }

    protected override void OnStop() {
        ...
        base.OnStop();
    }
}

现在我可以通过在调试器或命令行中运行它来测试服务。

安装时我使用命令行

sc create ServiceName binPath= C:\...\MyService.exe

(我无法阻止设计器双击打开)

【讨论】:

    【解决方案4】:

    VS 确实添加了一些额外的东西,但我并不担心。这是在 VS2005 中手动创建简单服务的教程,它应该也适用于新版本。

    http://www.codeproject.com/KB/system/WindowsService.aspx

    【讨论】:

    • ServiceName 不恒定时,设计器会崩溃——它会改变我写的代码:我真的不想要设计器。此外,它生成的代码很容易比所需代码大 5 倍,而且更难理解。
    • 让我这么说吧:除了作为包含所需类型的初始模板之外,还有任何对设计师有用的功能吗?
    猜你喜欢
    • 2015-10-30
    • 2012-09-18
    • 1970-01-01
    • 2010-11-03
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多