以编程方式安装Windows服务

51

如何在不使用installutil.exe的情况下以编程方式安装Windows服务?


不使用任何其他第三方安装程序吗? - Paul Sasik
是的...我希望我能使用一个像installservice()这样的函数,当我双击windowsservice.exe时,它会检查是否已安装,如果没有安装,它会自动安装。 - Josh
2
那是一个很好的函数:):) - Danail
5个回答

74

您可以通过将以下代码(在程序文件Program.cs中)添加到命令行中使用指定参数运行时安装自身来安装服务:

/// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            if (System.Environment.UserInteractive)
            {

                if (args.Length > 0)
                {
                    switch (args[0])
                    {
                        case "-install":
                            {
                                ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                                break;
                            }
                        case "-uninstall":
                            {
                                ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                                break;
                            }
                    }
                }
            }
            else
            {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] { new MyService() };
                ServiceBase.Run(ServicesToRun);
            }
        }

6
虽然这是一种明确且适合的方法来完成此操作,而不使用“低级别”的advapi32.dll,但框架文档表示:“此 API 支持 .NET Framework 基础结构,不建议直接从代码中使用。”但我仍然更喜欢“ManagedInstallerClass”并愿意承担未来在新版本的.NET中出现不兼容性的风险。(http://msdn.microsoft.com/pt-br/library/system.configuration.install.managedinstallerclass) - Luciano
我想知道,如果我从另一个控制台应用程序中调用 ManagedInstallerClass.InstallHelper(srvExe),这个应用程序会等待 InstallHelper 退出(安装完成)吗?谢谢。 - Andrey K.
可能是最近框架版本(4.8)中的新内容,但是System.Configuration.Install命名空间以及其中的ManagedInstaller类仅存在于调试构建中。 - Luc VdV
更正之前的评论:对于调试版本,您可以包含对System.Configuration.Install.dll的引用,对于发布版本,则还必须添加System.Configuration.dll。 - Luc VdV

11

3
链接不错,但是它引用了一篇由Mahmoud Nasr撰写的损坏链接。我使用了这个并且对我有效。 https://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 - D. Kermott
我想知道,如果我从另一个控制台应用程序中调用 ManagedInstallerClass.InstallHelper(srvExe),这个应用程序会等待 InstallHelper 退出(安装完成)吗?谢谢。 - Andrey K.

5

我通过命令行安装和卸载Windows服务,例如MyWindowsService.exe -installMyWindowsService.exe -uninstall,以避免使用installutil.exe。 我已经编写了一组说明,说明如何在这里执行此操作。


4
楼主询问如何通过编程实现,而不是通过命令行操作。 - Mike
3
我的解决方案是一个通过命令行访问的程序化解决方案,与被接受的答案使用相同的方式。 - Matt Davis

0

由于声誉不足,我无法发表评论,但关于马克·雷德曼的解决方案 - 如果你想知道在给定路径中找不到你的键,可以看看 WOW6432Node

来自AdvancedInstaller

Wow6432Node 注册表条目表示您正在运行的是64位Windows版本。

操作系统使用此键来为在64位Windows版本上运行的32位应用程序显示HKEY_LOCAL_MACHINE\SOFTWARE的单独视图。当32位应用程序在 HKEY_LOCAL_MACHINE\SOFTWARE\<company>\<product> 子键下写入或读取值时,该应用程序从 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\<company>\<product> 子键中读取。

注册表反射器在32位和64位注册表视图之间复制某些值(主要用于COM注册),并使用“最后写入者胜出”的方法解决任何冲突。”


0
以上方法都不适用于.Net Core,但是可以参考我在这里提供的答案:https://dev59.com/MXE85IYBdhLWcg3wzm9p#76732404 使用System.Diagnostics.Process来启动sc.exe,可能会有解决方案。
使用命令行中的sc.exe而无需参数来查找其用法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接