C# 如何使用 Visual Studio 为 .net Windows 服务创建安装程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9021075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create an installer for a .net Windows Service using Visual Studio
提问by Kelsey
How do I create an installer for a Windows Service that I have created using Visual Studio?
如何为使用 Visual Studio 创建的 Windows 服务创建安装程序?
采纳答案by Kelsey
In the service project do the following:
在服务项目中执行以下操作:
- In the solution explorer double click your services .cs file. It should bring up a screen that is all gray and talks about dragging stuff from the toolbox.
- Then right click on the gray area and select add installer. This will add an installer project file to your project.
- Then you will have 2 components on the design view of the ProjectInstaller.cs (serviceProcessInstaller1 and serviceInstaller1). You should then setup the properties as you need such as service name and user that it should run as.
- 在解决方案资源管理器中双击您的服务 .cs 文件。它应该显示一个全灰色的屏幕,并讨论从工具箱中拖动东西。
- 然后右键单击灰色区域并选择添加安装程序。这会将安装程序项目文件添加到您的项目中。
- 然后您将在 ProjectInstaller.cs 的设计视图上拥有 2 个组件(serviceProcessInstaller1 和 serviceInstaller1)。然后,您应该根据需要设置属性,例如服务名称和运行的用户。
Now you need to make a setup project. The best thing to do is use the setup wizard.
现在您需要制作一个安装项目。最好的办法是使用设置向导。
Right click on your solution and add a new project: Add > New Project > Setup and Deployment Projects > Setup Wizard
a. This could vary slightly for different versions of Visual Studio. b. Visual Studio 2010 it is located in: Install Templates > Other Project Types > Setup and Deployment > Visual Studio Installer
On the second step select "Create a Setup for a Windows Application."
- On the 3rd step, select "Primary output from..."
- Click through to Finish.
右键单击您的解决方案并添加一个新项目:添加 > 新建项目 > 安装和部署项目 > 安装向导
一种。对于不同版本的 Visual Studio,这可能略有不同。湾 Visual Studio 2010 位于:安装模板 > 其他项目类型 > 设置和部署 > Visual Studio 安装程序
在第二步中,选择“为 Windows 应用程序创建安装程序”。
- 第三步,选择“Primary output from...”
- 单击以完成。
Next edit your installer to make sure the correct output is included.
接下来编辑您的安装程序以确保包含正确的输出。
- Right click on the setup project in your Solution Explorer.
- Select View > Custom Actions. (In VS2008 it might be View > Editor > Custom Actions)
- Right-click on the Install action in the Custom Actions tree and select 'Add Custom Action...'
- In the "Select Item in Project" dialog, select Application Folder and click OK.
- Click OK to select "Primary output from..." option. A new node should be created.
- Repeat steps 4 - 5 for commit, rollback and uninstall actions.
- 右键单击解决方案资源管理器中的安装项目。
- 选择“查看”>“自定义操作”。(在 VS2008 中,它可能是 View > Editor > Custom Actions)
- 右键单击自定义操作树中的安装操作,然后选择“添加自定义操作...”
- 在“选择项目中的项目”对话框中,选择应用程序文件夹并单击确定。
- 单击“确定”以选择“来自...的主要输出”选项。应该创建一个新节点。
- 对提交、回滚和卸载操作重复步骤 4 - 5。
You can edit the installer output name by right clicking the Installer project in your solution and select Properties. Change the 'Output file name:' to whatever you want. By selecting the installer project as well and looking at the properties windows, you can edit the Product Name, Title, Manufacturer, etc...
您可以通过右键单击解决方案中的安装程序项目并选择属性来编辑安装程序输出名称。将“输出文件名:”更改为您想要的任何内容。通过选择安装项目以及并查看属性窗口,您可以编辑Product Name,Title,Manufacturer,等...
Next build your installer and it will produce an MSI and a setup.exe. Choose whichever you want to use to deploy your service.
接下来构建您的安装程序,它将生成一个 MSI 和一个 setup.exe。选择要用于部署服务的任何一个。
回答by Kelsey
I follow Kelsey's first set of steps to add the installer classes to my service project, but instead of creating an MSI or setup.exe installer I make the service self installing/uninstalling. Here's a bit of sample code from one of my services you can use as a starting point.
我按照 Kelsey 的第一组步骤将安装程序类添加到我的服务项目中,但我没有创建 MSI 或 setup.exe 安装程序,而是让服务自行安装/卸载。这是我的一项服务中的一些示例代码,您可以将其用作起点。
public static int Main(string[] args)
{
if (System.Environment.UserInteractive)
{
// we only care about the first two characters
string arg = args[0].ToLowerInvariant().Substring(0, 2);
switch (arg)
{
case "/i": // install
return InstallService();
case "/u": // uninstall
return UninstallService();
default: // unknown option
Console.WriteLine("Argument not recognized: {0}", args[0]);
Console.WriteLine(string.Empty);
DisplayUsage();
return 1;
}
}
else
{
// run as a standard service as we weren't started by a user
ServiceBase.Run(new CSMessageQueueService());
}
return 0;
}
private static int InstallService()
{
var service = new MyService();
try
{
// perform specific install steps for our queue service.
service.InstallService();
// install the service with the Windows Service Control Manager (SCM)
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
}
catch (Exception ex)
{
if (ex.InnerException != null && ex.InnerException.GetType() == typeof(Win32Exception))
{
Win32Exception wex = (Win32Exception)ex.InnerException;
Console.WriteLine("Error(0x{0:X}): Service already installed!", wex.ErrorCode);
return wex.ErrorCode;
}
else
{
Console.WriteLine(ex.ToString());
return -1;
}
}
return 0;
}
private static int UninstallService()
{
var service = new MyQueueService();
try
{
// perform specific uninstall steps for our queue service
service.UninstallService();
// uninstall the service from the Windows Service Control Manager (SCM)
ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
}
catch (Exception ex)
{
if (ex.InnerException.GetType() == typeof(Win32Exception))
{
Win32Exception wex = (Win32Exception)ex.InnerException;
Console.WriteLine("Error(0x{0:X}): Service not installed!", wex.ErrorCode);
return wex.ErrorCode;
}
else
{
Console.WriteLine(ex.ToString());
return -1;
}
}
return 0;
}
回答by Christopher Painter
InstallUtil classes ( ServiceInstaller ) are considered an anti-pattern by the Windows Installer community. It's a fragile, out of process, reinventing of the wheel that ignores the fact that Windows Installer has built-in support for Services.
InstallUtil 类 ( ServiceInstaller ) 被 Windows Installer 社区视为一种反模式。这是一种脆弱的、程序外的重新发明轮子,它忽略了 Windows Installer 具有对服务的内置支持这一事实。
Visual Studio deployment projects ( also not highly regarded and deprecated in the next release of Visual Studio ) do not have native support for services. But they can consume merge modules. So I would take a look at this blog article to understand how to create a merge module using Windows Installer XML that can express the service and then consume that merge module in your VDPROJ solution.
Visual Studio 部署项目(在 Visual Studio 的下一个版本中也没有受到高度重视和弃用)没有对服务的本机支持。但是它们可以使用合并模块。因此,我将查看这篇博客文章,以了解如何使用 Windows Installer XML 创建一个可以表达服务的合并模块,然后在您的 VDPROJ 解决方案中使用该合并模块。
Augmenting InstallShield using Windows Installer XML - Windows Services
使用 Windows Installer XML 增强 InstallShield - Windows 服务
回答by Alexey Obukhov
Nor Kelsey, nor Brendan solutions does not works for me in Visual Studio 2015 Community.
在 Visual Studio 2015 社区中,Kelsey 和 Brendan 解决方案都不适合我。
Here is my brief steps how to create service with installer:
这是我如何使用安装程序创建服务的简要步骤:
- Run Visual Studio, Go to File
->New->Project - Select .NET Framework 4, in 'Search Installed Templates' type 'Service'
- Select 'Windows Service'. Type Name and Location. Press OK.
- Double click Service1.cs, right click in designer and select 'Add Installer'
- Double click ProjectInstaller.cs. For serviceProcessInstaller1 open Properties tab and change 'Account' property value to 'LocalService'. For serviceInstaller1 change 'ServiceName' and set 'StartType' to 'Automatic'.
Double click serviceInstaller1. Visual Studio creates
serviceInstaller1_AfterInstallevent. Write code:private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e) { using (System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName)) { sc.Start(); } }Build solution. Right click on project and select 'Open Folder in File Explorer'. Go to bin\Debug.
Create install.bat with below script:
::::::::::::::::::::::::::::::::::::::::: :: Automatically check & get admin rights ::::::::::::::::::::::::::::::::::::::::: @echo off CLS ECHO. ECHO ============================= ECHO Running Admin shell ECHO ============================= :checkPrivileges NET FILE 1>NUL 2>NUL if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) :getPrivileges if '%1'=='ELEV' (shift & goto gotPrivileges) ECHO. ECHO ************************************** ECHO Invoking UAC for Privilege Escalation ECHO ************************************** setlocal DisableDelayedExpansion set "batchPath=%~0" setlocal EnableDelayedExpansion ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs" ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs" "%temp%\OEgetPrivileges.vbs" exit /B :gotPrivileges :::::::::::::::::::::::::::: :START :::::::::::::::::::::::::::: setlocal & pushd . cd /d %~dp0 %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i "WindowsService1.exe" pause- Create uninstall.bat file (change in pen-ult line
/ito/u) - To install and start service run install.bat, to stop and uninstall run uninstall.bat
- 运行 Visual Studio,转到 File
->New->Project - 选择 .NET Framework 4,在“搜索安装的模板”中输入“服务”
- 选择“Windows 服务”。键入名称和位置。按OK。
- 双击 Service1.cs,在设计器中右键单击并选择“添加安装程序”
- 双击 ProjectInstaller.cs。对于 serviceProcessInstaller1,打开 Properties 选项卡并将“Account”属性值更改为“LocalService”。对于 serviceInstaller1,更改“ServiceName”并将“StartType”设置为“Automatic”。
双击 serviceInstaller1。Visual Studio 创建
serviceInstaller1_AfterInstall事件。编写代码:private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e) { using (System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName)) { sc.Start(); } }构建解决方案。右键单击项目并选择“在文件资源管理器中打开文件夹”。转到bin\Debug。
使用以下脚本创建 install.bat:
::::::::::::::::::::::::::::::::::::::::: :: Automatically check & get admin rights ::::::::::::::::::::::::::::::::::::::::: @echo off CLS ECHO. ECHO ============================= ECHO Running Admin shell ECHO ============================= :checkPrivileges NET FILE 1>NUL 2>NUL if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) :getPrivileges if '%1'=='ELEV' (shift & goto gotPrivileges) ECHO. ECHO ************************************** ECHO Invoking UAC for Privilege Escalation ECHO ************************************** setlocal DisableDelayedExpansion set "batchPath=%~0" setlocal EnableDelayedExpansion ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs" ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs" "%temp%\OEgetPrivileges.vbs" exit /B :gotPrivileges :::::::::::::::::::::::::::: :START :::::::::::::::::::::::::::: setlocal & pushd . cd /d %~dp0 %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i "WindowsService1.exe" pause- 创建 uninstall.bat 文件(将 pen-ult 行更改
/i为/u) - 安装和启动服务运行 install.bat,停止和卸载运行uninstall.bat
回答by JustSomeDev
For VS2017 you will need to add the "Microsoft Visual Studio 2017 Installer Projects" VS extension. This will give you additional Visual Studio Installer project templates. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
对于 VS2017,您需要添加“Microsoft Visual Studio 2017 安装程序项目”VS 扩展。这将为您提供额外的 Visual Studio 安装程序项目模板。https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
To install the windows service you can add a new setup wizard type project and follow the steps from Kelsey's answer https://stackoverflow.com/a/9021107/1040040
要安装 Windows 服务,您可以添加一个新的安装向导类型项目,并按照 Kelsey 的回答https://stackoverflow.com/a/9021107/1040040 中的步骤操作

