我正在尝试部署Windows服务,但不太确定如何正确执行。我将它构建为一个控制台应用程序,我现在把它变成一个Windows服务项目,然后从服务中的OnStart方法调用我的类。
我现在需要在没有Visual Studio的服务器上安装它,如果我正确理解它意味着我不能使用InstallUtil.exe而必须创建一个安装程序类。这是对的吗?
我确实看过上一个问题,Install a .NET windows service without InstallUtil.exe,但我只是想确保我已正确理解。
如果我创建了问题已接受答案链接的课程,下一步是什么?将MyService.exe和MyService.exe.config上传到服务器,双击exe文件,Bob是我的叔叔?
该服务只会安装在一台服务器上。
答案 0 :(得分:44)
我知道这是一个非常古老的问题,但最好用新信息更新它。
您可以使用sc命令安装服务:
<强> InstallService.bat:强>
@echo OFF
echo Stopping old service version...
net stop "[YOUR SERVICE NAME]"
echo Uninstalling old service version...
sc delete "[YOUR SERVICE NAME]"
echo Installing service...
rem DO NOT remove the space after "binpath="!
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto
echo Starting server complete
pause
使用SC,您还可以执行更多操作:卸载旧服务(如果您之前已经安装过),检查是否存在具有相同名称的服务...甚至将您的服务设置为自动启动。
许多参考文献之一:creating a service with sc.exe; how to pass in context parameters
我已经通过这种方式和&amp; InstallUtil
。就个人而言,我觉得使用SC更清洁,更健康。
答案 1 :(得分:31)
你仍然可以在没有visual studio的情况下使用installutil,它包含在.net框架
中在服务器上,以管理员身份打开命令提示符:
CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version)
installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
要卸载:
installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
答案 2 :(得分:18)
InstallUtil.exe
工具只是针对服务中安装程序组件的一些反射调用的包装器。因此,它实际上没有做太多,但运用这些安装程序组件提供的功能。 Marc Gravell的解决方案只是提供了一种从命令行执行此操作的方法,这样您就不必再依赖于目标计算机上的InstallUtil.exe
。
以下是基于Marc Gravell解决方案的逐步步骤。
How to make a .NET Windows Service start right after the installation?
答案 3 :(得分:5)
为什么不创建一个安装项目?这真的很容易。
瞧,你已经完成了。
请点击此处了解更多信息: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
还有一种方法可以提示用户提供凭据(或提供自己的凭据)。
答案 4 :(得分:2)
这是一个基本服务类(ServiceBase子类),可以进行子类化以构建可以从命令行轻松安装的Windows服务,而无需installutil.exe。此解决方案派生自How to make a .NET Windows Service start right after the installation?,添加了一些代码以使用调用StackFrame获取服务类型
public abstract class InstallableServiceBase:ServiceBase
{
/// <summary>
/// returns Type of the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static Type getMyType()
{
Type t = typeof(InstallableServiceBase);
MethodBase ret = MethodBase.GetCurrentMethod();
Type retType = null;
try
{
StackFrame[] frames = new StackTrace().GetFrames();
foreach (StackFrame x in frames)
{
ret = x.GetMethod();
Type t1 = ret.DeclaringType;
if (t1 != null && !t1.Equals(t) && !t1.IsSubclassOf(t))
{
break;
}
retType = t1;
}
}
catch
{
}
return retType;
}
/// <summary>
/// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static AssemblyInstaller GetInstaller()
{
Type t = getMyType();
AssemblyInstaller installer = new AssemblyInstaller(
t.Assembly, null);
installer.UseNewContext = true;
return installer;
}
private bool IsInstalled()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
ServiceControllerStatus status = controller.Status;
}
catch
{
return false;
}
return true;
}
}
private bool IsRunning()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
if (!this.IsInstalled()) return false;
return (controller.Status == ServiceControllerStatus.Running);
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void InstallService()
/// {
/// base.InstallService();
/// }
/// </summary>
protected void InstallService()
{
if (this.IsInstalled()) return;
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Install(state);
installer.Commit(state);
}
catch
{
try
{
installer.Rollback(state);
}
catch { }
throw;
}
}
}
catch
{
throw;
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void UninstallService()
/// {
/// base.UninstallService();
/// }
/// </summary>
protected void UninstallService()
{
if (!this.IsInstalled()) return;
if (this.IsRunning()) {
this.StopService();
}
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Uninstall(state);
}
catch
{
throw;
}
}
}
catch
{
throw;
}
}
private void StartService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Running)
{
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
private void StopService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Stopped)
{
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
}
您所要做的就是在实际服务中实现两种公共/内部方法:
new internal void InstallService()
{
base.InstallService();
}
new internal void UninstallService()
{
base.UninstallService();
}
然后在您要安装服务时调用它们:
static void Main(string[] args)
{
if (Environment.UserInteractive)
{
MyService s1 = new MyService();
if (args.Length == 1)
{
switch (args[0])
{
case "-install":
s1.InstallService();
break;
case "-uninstall":
s1.UninstallService();
break;
default:
throw new NotImplementedException();
}
}
}
else {
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(MyService);
}
}
答案 5 :(得分:0)
不是双击,而是使用正确的命令行参数运行它,因此键入类似MyService -i
然后MyService -u
的内容来卸载它。
您可以使用sc.exe安装和卸载它(或沿InstallUtil.exe复制)。
答案 6 :(得分:0)
Topshelf是一个OSS项目,在这个问题得到解答后启动,它使Windows服务变得更加容易。我强烈建议您查看它。
答案 7 :(得分:0)
此问题是由于安全性,在RUN AS ADMINISTRATOR中更好地打开VS 2012的开发人员命令提示并安装您的服务,它确实可以解决您的问题。