Windows 服务如何以编程方式自行重启?

发布于 2024-07-07 18:59:57 字数 93 浏览 6 评论 0 原文

我需要在 .NET 中编写可靠的代码,以使 Windows 服务(服务器 2003)能够自行重新启动。 最好的方法是什么? 有一些 .NET API 可以做到这一点吗?

I need to write robust code in .NET to enable a windows service (server 2003) to restart itself. What is the best way to so this? Is there some .NET API to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

知足的幸福 2024-07-14 18:59:57

将服务设置为在失败后重新启动(双击控制面板中的服务并查看这些选项卡 - 我忘记了它的名称)。 然后,只要您希望服务重新启动,只需调用 Environment.Exit(1) (或任何非零返回),操作系统就会为您重新启动它。

Set the service to restart after failure (double click the service in the control panel and have a look around on those tabs - I forget the name of it). Then, anytime you want the service to restart, just call Environment.Exit(1) (or any non-zero return) and the OS will restart it for you.

柠檬心 2024-07-14 18:59:57
Dim proc As New Process()
Dim psi As New ProcessStartInfo()

psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
Dim proc As New Process()
Dim psi As New ProcessStartInfo()

psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
幼儿园老大 2024-07-14 18:59:57

您可以使用 Windows cmd.exe 创建一个自行重新启动的子进程:

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();

You can create a subprocess using Windows cmd.exe that restarts yourself:

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();
执手闯天涯 2024-07-14 18:59:57

您甚至无法确定运行服务的用户帐户是否有权停止和重新启动该服务。

You can't be sure that the user account that your service is running under even has permissions to stop and restart the service.

兔姬 2024-07-14 18:59:57
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

其中 SERVICENAME 是您的服务名称(包含双引号以解决服务名称中的空格,否则可以省略)。

干净,无需自动重启配置。

const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

where SERVICENAME is the name of your service (double quotes included to account for spaces in the service name, can be omitted otherwise).

Clean, no auto-restart configuration necessary.

请爱~陌生人 2024-07-14 18:59:57

这取决于您希望它自行重启的原因。

如果您只是寻找一种让服务定期自行清理的方法,那么您可以在服务中运行一个计时器,定期引发清除例程。

如果您正在寻找一种在失败时重新启动的方法 - 服务主机本身可以在设置时提供该功能。

那么为什么需要重启服务器呢? 你想达到什么目的?

It would depend on why you want it to restart itself.

If you are just looking for a way to have the service clean itself out periodically then you could have a timer running in the service that periodically causes a purge routine.

If you are looking for a way to restart on failure - the service host itself can provide that ability when it is setup.

So why do you need to restart the server? What are you trying to achieve?

挽清梦 2024-07-14 18:59:57

我不认为你可以在独立的服务中(当你调用重新启动时,它将停止服务,这将中断重新启动命令,并且它不会再次启动)。 如果您可以添加第二个 .exe(使用 ServiceManager 类的控制台应用程序),那么您可以启动独立的 .exe 并让它重新启动服务,然后退出。

再想一想,您可能可以让服务注册一个计划任务(例如,使用命令行“at”命令)来启动服务,然后让它自行停止; 那可能会起作用。

I don't think you can in a self-contained service (when you call Restart, it will stop the service, which will interrupt the Restart command, and it won't ever get started again). If you can add a second .exe (a Console app that uses the ServiceManager class), then you can kick off the standalone .exe and have it restart the service and then exit.

On second thought, you could probably have the service register a Scheduled Task (using the command-line 'at' command, for example) to start the service and then have it stop itself; that would probably work.

爱你是孤单的心事 2024-07-14 18:59:57

处理批处理文件或 EXE 的问题在于,服务可能具有也可能不具有运行外部应用程序所需的权限。

我发现最简洁的方法是使用 OnStop() 方法,它是服务控制管理器的入口点。 然后,所有清理代码都将运行,并且假设您的停止代码正在执行其工作,您将不会有任何挂起的套接字或其他进程。

为此,您需要在终止之前设置一个标志,告诉 OnStop 方法退出并显示错误代码; 那么SCM就知道该服务需要重新启动。 如果没有此标志,您将无法从 SCM 手动停止服务。 这还假设您已将服务设置为在出现错误时重新启动。

这是我的停止代码:

...

bool ABORT;

protected override void OnStop()
{
    Logger.log("Stopping service");
    WorkThreadRun = false;
    WorkThread.Join();
    Logger.stop();
    // if there was a problem, set an exit error code
    // so the service manager will restart this
    if(ABORT)Environment.Exit(1);
}

如果服务遇到问题并需要重新启动,我会启动一个线程来从 SCM 停止服务。 这允许服务自行清理:

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}

The problem with shelling out to a batch file or EXE is that a service may or may not have the permissions required to run the external app.

The cleanest way to do this that I have found is to use the OnStop() method, which is the entry point for the Service Control Manager. Then all your cleanup code will run, and you won't have any hanging sockets or other processes, assuming your stop code is doing its job.

To do this you need to set a flag before you terminate that tells the OnStop method to exit with an error code; then the SCM knows that the service needs to be restarted. Without this flag you won't be able to stop the service manually from the SCM. This also assumes you have set up the service to restart on an error.

Here's my stop code:

...

bool ABORT;

protected override void OnStop()
{
    Logger.log("Stopping service");
    WorkThreadRun = false;
    WorkThread.Join();
    Logger.stop();
    // if there was a problem, set an exit error code
    // so the service manager will restart this
    if(ABORT)Environment.Exit(1);
}

If the service runs into a problem and needs to restart, I launch a thread that stops the service from the SCM. This allows the service to clean up after itself:

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}
海未深 2024-07-14 18:59:57

我将使用 Windows Scheduler 来安排服务的重新启动。 问题是你无法重新启动自己,但你可以阻止自己。 (你基本上已经锯掉了你坐的树枝......如果你明白我的类比)你需要一个单独的过程来为你做这件事。 Windows Scheduler 是一个合适的选择。 安排一项一次性任务来重新启动您的服务(甚至从服务本身内部)以立即执行。

否则,您将必须创建一个“引导”流程来为您完成这件事。

I would use the Windows Scheduler to schedule a restart of your service. The problem is that you can't restart yourself, but you can stop yourself. (You've essentially sawed off the branch that you're sitting on... if you get my analogy) You need a separate process to do it for you. The Windows Scheduler is an appropriate one. Schedule a one-time task to restart your service (even from within the service itself) to execute immediately.

Otherwise, you'll have to create a "shepherding" process that does it for you.

自由范儿 2024-07-14 18:59:57

对这个问题的第一个回答是最简单的解决方案:“Environment.Exit(1)”我在 Windows Server 2008 R2 上使用它,它运行得很好。 服务自行停止,操作系统等待 1 分钟,然后重新启动。

The first response to the question is the simplest solution: "Environment.Exit(1)" I am using this on Windows Server 2008 R2 and it works perfectly. The service stops itself, the O/S waits 1 minute, then restarts it.

紫罗兰の梦幻 2024-07-14 18:59:57

我认为不可以。 当服务“停止”时,它就会完全卸载。

好吧,我想总有办法的。 例如,您可以创建一个分离的进程来停止服务,然后重新启动它,然后退出。

I don't think it can. When a service is "stopped", it gets totally unloaded.

Well, OK, there's always a way I suppose. For instance, you could create a detached process to stop the service, then restart it, then exit.

神魇的王 2024-07-14 18:59:57

只是路过:我想我会添加一些额外的信息...

你也可以抛出一个异常,这将自动关闭 Windows 服务,并且自动重新启动选项就会启动。唯一的问题是,如果你有在你的电脑上安装一个开发环境,然后 JIT 尝试启动,你会得到一个提示,提示“debug Y/N”。 说“不”,然后它将关闭,然后重新正常启动。 (在没有 JIT 的 PC 上一切正常)。
我的原因是这个 JIT 对于 Win 7 来说是新的(它曾经在 XP 等上工作得很好)并且我试图找到一种禁用 JIT 的方法....我可以尝试这里提到的 Environment.Exit 方法看看如何这也有效。

克里斯蒂安:英国布里斯托尔

Just passing: and thought i would add some extra info...

you can also throw an exception, this will auto close the windows service, and the auto re-start options just kick in. the only issue with this is that if you have a dev enviroment on your pc then the JIT tries to kick in, and you will get a prompt saying debug Y/N. say no and then it will close, and then re-start properly. (on a PC with no JIT it just all works).
the reason im trolling, is this JIT is new to Win 7 (it used to work fine with XP etc) and im trying to find a way of disabling the JIT.... i may try the Environment.Exit method mentioned here see how that works too.

Kristian : Bristol, UK

离笑几人歌 2024-07-14 18:59:57

创建一个像这样的 restart.bat 文件

@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%

schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%

然后在 %service% 启动时删除任务 %taskname%

Create a restart.bat file like this

@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%

schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%

Then delete the task %taskname% when your %service% starts

暗地喜欢 2024-07-14 18:59:57

创建一个单独的应用程序域来托管应用程序代码。 当需要重新启动时,我们可以卸载并重新加载应用程序域而不是进程(Windows 服务)。 这就是 IIS 应用程序池的工作方式,它们不直接运行 asp.net 应用程序,它们使用单​​独的 appdmain。

Create a separate appdomain to host the application code. When requires restart, we could unload and reload the appdomain instead the process (windows service). This is how IIS app pool works, they dont run asp.net app directly, they use separate appdmain.

酸甜透明夹心 2024-07-14 18:59:57

使用 Process.Start 运行 sc stop OwnServiceName ,然后运行 ​​sc start OwnServiceName 仅当服务进程有权控制自身时才有效 - 它们总是不这样做。

...即使服务进程确实有权限,只需运行 cmd.exe /c sc stop Self && sc start Self 不会工作,因为 sc stop 立即返回,而不等待服务停止(而旧的 net stop 命令会等待,< a href="https://stackoverflow.com/questions/2874911/halt-batch-file-until-service-stop-is-complete#comment26512590_2874964">它不会无限期地等待)。 更好的方法是将这个多步骤逻辑放入 .cmd 批处理文件中,并使用 Process.Start( "cmd.exe", "/ c RestartService.cmd")


至于确保服务有足够的权限自行重启:

如果您使用 WIX MSI 来安装 Windows 服务,则可以使用 WIX 的 util:PermissionEx 元素:

<Component Id="cmpYourServiceHostExe" Directory="INSTALLDIR" Guid="*">
    <File Id="fleYourServiceHostExe" KeyPath="yes" Source="YourServiceHost.exe">
        <netfx:NativeImage Id="Ngen_fleYourServiceHostExe" Platform="32bit" Priority="0" AppBaseDirectory="INSTALLDIR"/>
    </File>

    <ServiceInstall
        Id="srvYourService"
        Name="YourService"
        Account= "NT AUTHORITY\LocalService"
        Type= "ownProcess"
    >
        <ServiceConfig
            DelayedAutoStart="yes"
            FailureActionsWhen="failedToStopOrReturnedError"
                
            OnInstall="yes"
            OnUninstall="no"
            OnReinstall="yes"
        />
        <util:ServiceConfig
            FirstFailureActionType="restart"
            SecondFailureActionType="restart"
            ThirdFailureActionType="restart"
            ResetPeriodInDays="1"
        />

        <util:PermissionEx
            User                       = "NT AUTHORITY\LocalService"
            ServiceEnumerateDependents = "yes"
            ServiceInterrogate         = "yes"
            ServicePauseContinue       = "yes"
            ServiceQueryConfig         = "yes"
            ServiceQueryStatus         = "yes"
            ServiceStart               = "yes"
            ServiceStop                = "yes"
            ServiceUserDefinedControl  = "yes"
        />

    </ServiceInstall>

</Component>

如果您手动安装服务 - 或使用其他一些技术,然后您可以通过运行 sc sdset 设置服务权限,这需要熟悉 Windows 的 SDDL 语法它与 Windows 服务安全性的关系

Windows 服务的默认 SDDL 似乎是这样的:

D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

...使用这些定义:

winsvc.h Service Access Right         == Iads.h ADS_RIGHT name       == Sddl.h               == SDDL String
--------------------------------------------------------------------------------------------------------
SERVICE_QUERY_CONFIG           0x0001 == ADS_RIGHT_DS_CREATE_CHILD   == SDDL_CREATE_CHILD    ==  "CC"
SERVICE_CHANGE_CONFIG          0x0002 == ADS_RIGHT_DS_DELETE_CHILD   == SDDL_DELETE_CHILD    ==  "DC"
SERVICE_QUERY_STATUS           0x0004 == ADS_RIGHT_ACTRL_DS_LIST     == SDDL_LIST_CHILDREN   ==  "LC"
SERVICE_ENUMERATE_DEPENDENTS   0x0008 == ADS_RIGHT_DS_SELF           == SDDL_SELF_WRITE      ==  "SW"
SERVICE_START                  0x0010 == ADS_RIGHT_DS_READ_PROP      == SDDL_READ_PROPERTY   ==  "RP"
SERVICE_STOP                   0x0020 == ADS_RIGHT_DS_WRITE_PROP     == SDDL_WRITE_PROPERTY  ==  "WP"
SERVICE_PAUSE_CONTINUE         0x0040 == ADS_RIGHT_DS_DELETE_TREE    == SDDL_DELETE_TREE     ==  "DT"
SERVICE_INTERROGATE            0x0080 == ADS_RIGHT_DS_LIST_OBJECT    == SDDL_LIST_OBJECT     ==  "LO"
SERVICE_USER_DEFINED_CONTROL   0x0100 == ADS_RIGHT_DS_CONTROL_ACCESS == SDDL_CONTROL_ACCESS  ==  "CR"

...然后默认 SSDL 扩展为:

    (A;;CC LC SW RP WP DT LO CR RC;;;SY)
        Allow "LOCAL SYSTEM" (SY):
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

    (A;;CC DC LC SW RP WP DT LO CR SD RC WD WO;;;BA)
        Allow "Built-in Administrators" (BA)
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            SD = SDDL_STANDARD_DELETE
            RC = SDDL_READ_CONTROL
            WD = SDDL_WRITE_DAC
            WO = SDDL_WRITE_OWNER

    (A;;CC LC SW LO CR RC;;;IU)
        Allow "Interactive Users" (IU)
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

    (A;;CC LC SW LO CR RC;;;SU)
        Allow a process with "Service" token (see "SECURITY_SERVICE_RID")
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

我们将 SU 规则更改为:

    (A;;CC LC SW RP WP DT LO CR RC;;;SU)
        SECURITY_SERVICE_RID
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

因此,您可以从提升的进程(例如您的安装程序或服务安装程序):

sc sdset YourServiceName "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)((A;;CCLCSWRPWPDTLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

...这意味着您的服务可以运行 Process.Start( "cmd.exe", "/c RestartService.cmd" )。


这就是我的 RestartService.cmd 的样子:(

感谢此处发布的 @js2010 的答案

sc stop YourServiceName
:loop
sc query YourServiceName | find "STOPPED"
if errorlevel 1 (
  timeout /t 2
  goto loop
)

sc start YourServiceName

Using Process.Start to run sc stop OwnServiceName followed by sc start OwnServiceName only works when the service-process has permission to control itself - which they invariably don't.

...and even if the service-process does have permission, simply running cmd.exe /c sc stop Self && sc start Self isn't going to work because sc stop returns immediately without waiting for the service to stop (while the older net stop command does wait, it doesn't wait indefinitely). A better approach is to put this multi-step logic in a .cmd batch file and run that with Process.Start( "cmd.exe", "/c RestartService.cmd" ).


As for ensuring the Service has sufficient permission to restart itself:

If you used WIX MSI to install the Windows Service, you can use WIX's util:PermissionEx element:

<Component Id="cmpYourServiceHostExe" Directory="INSTALLDIR" Guid="*">
    <File Id="fleYourServiceHostExe" KeyPath="yes" Source="YourServiceHost.exe">
        <netfx:NativeImage Id="Ngen_fleYourServiceHostExe" Platform="32bit" Priority="0" AppBaseDirectory="INSTALLDIR"/>
    </File>

    <ServiceInstall
        Id="srvYourService"
        Name="YourService"
        Account= "NT AUTHORITY\LocalService"
        Type= "ownProcess"
    >
        <ServiceConfig
            DelayedAutoStart="yes"
            FailureActionsWhen="failedToStopOrReturnedError"
                
            OnInstall="yes"
            OnUninstall="no"
            OnReinstall="yes"
        />
        <util:ServiceConfig
            FirstFailureActionType="restart"
            SecondFailureActionType="restart"
            ThirdFailureActionType="restart"
            ResetPeriodInDays="1"
        />

        <util:PermissionEx
            User                       = "NT AUTHORITY\LocalService"
            ServiceEnumerateDependents = "yes"
            ServiceInterrogate         = "yes"
            ServicePauseContinue       = "yes"
            ServiceQueryConfig         = "yes"
            ServiceQueryStatus         = "yes"
            ServiceStart               = "yes"
            ServiceStop                = "yes"
            ServiceUserDefinedControl  = "yes"
        />

    </ServiceInstall>

</Component>

If you're manually installing your service - or using some other technique, then you can set service permissions by running sc sdset, which requires familiarizing yourself with Windows' SDDL syntax and how it relates to Windows Service security.

The default SDDL for a Windows Service seems to be this:

D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

...using these definitions:

winsvc.h Service Access Right         == Iads.h ADS_RIGHT name       == Sddl.h               == SDDL String
--------------------------------------------------------------------------------------------------------
SERVICE_QUERY_CONFIG           0x0001 == ADS_RIGHT_DS_CREATE_CHILD   == SDDL_CREATE_CHILD    ==  "CC"
SERVICE_CHANGE_CONFIG          0x0002 == ADS_RIGHT_DS_DELETE_CHILD   == SDDL_DELETE_CHILD    ==  "DC"
SERVICE_QUERY_STATUS           0x0004 == ADS_RIGHT_ACTRL_DS_LIST     == SDDL_LIST_CHILDREN   ==  "LC"
SERVICE_ENUMERATE_DEPENDENTS   0x0008 == ADS_RIGHT_DS_SELF           == SDDL_SELF_WRITE      ==  "SW"
SERVICE_START                  0x0010 == ADS_RIGHT_DS_READ_PROP      == SDDL_READ_PROPERTY   ==  "RP"
SERVICE_STOP                   0x0020 == ADS_RIGHT_DS_WRITE_PROP     == SDDL_WRITE_PROPERTY  ==  "WP"
SERVICE_PAUSE_CONTINUE         0x0040 == ADS_RIGHT_DS_DELETE_TREE    == SDDL_DELETE_TREE     ==  "DT"
SERVICE_INTERROGATE            0x0080 == ADS_RIGHT_DS_LIST_OBJECT    == SDDL_LIST_OBJECT     ==  "LO"
SERVICE_USER_DEFINED_CONTROL   0x0100 == ADS_RIGHT_DS_CONTROL_ACCESS == SDDL_CONTROL_ACCESS  ==  "CR"

...then the default SSDL expands to this:

    (A;;CC LC SW RP WP DT LO CR RC;;;SY)
        Allow "LOCAL SYSTEM" (SY):
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

    (A;;CC DC LC SW RP WP DT LO CR SD RC WD WO;;;BA)
        Allow "Built-in Administrators" (BA)
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            SD = SDDL_STANDARD_DELETE
            RC = SDDL_READ_CONTROL
            WD = SDDL_WRITE_DAC
            WO = SDDL_WRITE_OWNER

    (A;;CC LC SW LO CR RC;;;IU)
        Allow "Interactive Users" (IU)
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

    (A;;CC LC SW LO CR RC;;;SU)
        Allow a process with "Service" token (see "SECURITY_SERVICE_RID")
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

We change the SU rule to this:

    (A;;CC LC SW RP WP DT LO CR RC;;;SU)
        SECURITY_SERVICE_RID
            CC = SERVICE_QUERY_CONFIG
            LC = SERVICE_QUERY_STATUS
            SW = SERVICE_ENUMERATE_DEPENDENTS
            RP = SERVICE_START
            WP = SERVICE_STOP
            DT = SERVICE_PAUSE_CONTINUE
            LO = SERVICE_INTERROGATE
            CR = SERVICE_USER_DEFINED_CONTROL
            RC = SDDL_READ_CONTROL

So you run this from an elevated process (e.g. your setup program or service-installer):

sc sdset YourServiceName "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)((A;;CCLCSWRPWPDTLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

...which then means your service can run Process.Start( "cmd.exe", "/c RestartService.cmd" ).


This is what my RestartService.cmd looks like:

(With acknowledgement to @js2010's answer posted here)

sc stop YourServiceName
:loop
sc query YourServiceName | find "STOPPED"
if errorlevel 1 (
  timeout /t 2
  goto loop
)

sc start YourServiceName
夜还是长夜 2024-07-14 18:59:57

更好的方法可能是利用 NT 服务作为应用程序的包装器。 当 NT 服务启动时,您的应用程序可以以“空闲”模式启动,等待命令启动(或配置为自动启动)。

想象一辆汽车,当它启动时,它开始处于空闲状态,等待您的前进或后退命令。 这还带来了其他好处,例如更好的远程管理,因为您可以选择如何公开您的应用程序。

The better approach may be to utilize the NT Service as a wrapper for your application. When the NT Service is started, your application can start in an "idle" mode waiting for the command to start (or be configured to start automatically).

Think of a car, when it's started it begins in an idle state, waiting for your command to go forward or reverse. This also allows for other benefits, such as better remote administration as you can choose how to expose your application.

作死小能手 2024-07-14 18:59:57

最简单的方法是有一个批处理文件:

net stop
net start

并将文件添加到您所需的时间间隔的调度程序中

The easiest way is to have a batch file with:

net stop
net start

and add the file to the scheduler with your desired time interval

笑,眼淚并存 2024-07-14 18:59:57
private static void  RestartService(string serviceName)
    {
        using (var controller = new ServiceController(serviceName))
        {
            controller.Stop();
            int counter = 0;
            while (controller.Status != ServiceControllerStatus.Stopped)
            {
                Thread.Sleep(100);
                controller.Refresh();
                counter++;
                if (counter > 1000)
                {
                    throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
                }
            }

            controller.Start();
        }
    }
private static void  RestartService(string serviceName)
    {
        using (var controller = new ServiceController(serviceName))
        {
            controller.Stop();
            int counter = 0;
            while (controller.Status != ServiceControllerStatus.Stopped)
            {
                Thread.Sleep(100);
                controller.Refresh();
                counter++;
                if (counter > 1000)
                {
                    throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
                }
            }

            controller.Start();
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文