Windows 关闭时 Windows 服务引发错误

Posted

技术标签:

【中文标题】Windows 关闭时 Windows 服务引发错误【英文标题】:Windows Service Throws Error when Windows is Shutting Down 【发布时间】:2021-08-20 11:25:39 【问题描述】:

我有一个使用 .NET 在 C# 中构建的 Windows 服务,每次用户注销、挂起、休眠、重置或关机时都会引发错误。在应用程序事件查看器中,它显示错误如下:-

Application: Service.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ComponentModel.Win32Exception

Exception Info: System.InvalidOperationException
   at System.ServiceProcess.ServiceController.GenerateNames()
   at System.ServiceProcess.ServiceController.get_ServiceName()
   at System.ServiceProcess.ServiceController.Stop()
   at WellformationDesktopService.Wellformation+<OnSessionChange>d__3.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_1(System.Object)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

似乎失败的操作是使用 System.Net.HTTP.HttpClient 将提交发送到远程 API。该代码在 Windows 有效关闭用户空间时以外的任何其他时间都有效。

我需要做些什么来强制我的服务在无法执行该操作之前触发该操作?

提前致谢。

【问题讨论】:

听 ***.com/questions/5202119/… docs.microsoft.com/en-us/dotnet/api/… 并在你的循环中处理它们(使用取消令牌等)。虽然对于挂起,在 Windows 实际挂起之前您不太可能足够快地处理事件,所以也许只是捕获异常 在这种情况下,最好定期读取windows事件日志并转发该信息,虽然这意味着我们在接收信息方面会有点落后(可能直到关机才能收到第二天)至少我们会捕捉到所有合适的事件? 是的,这是可能的。请注意您的服务在收到 204(或您为成功提交设置的任何返回)之前关闭并认为它失败的竞争条件,因此您的远程服务必须有办法处理它。 【参考方案1】:

您可以创建一个 .ps(powershell 脚本)来检查要停止的服务以及脚本强制运行您的 Windows 服务。

以下脚本将解决您的问题。

# start the following Windows services in the specified order:
[Array] $Services = 'Service1','Service2','Service3',...;

# loop through each service, if its running, start it
foreach($ServiceName in $Services)

    $arrService = Get-Service -Name $ServiceName
    write-host $ServiceName
    while ($arrService.Status -eq 'Stopped')
    
        Start-Service $ServiceName
        write-host $arrService.status
        write-host 'Service starting'
        Start-Sleep -seconds 60
        $arrService.Refresh()
        if ($arrService.Status -eq 'Running')
            
              Write-Host 'Service is now Running'
            
     
 

您可以随时通过Windows Task Scheduler 定期运行此脚本。

以及如何自动设置Windows服务启动类型。

Windows Service Start Automatically

【讨论】:

不幸的是,此应用程序需要在安全的用户环境中运行,我无法启动 PS 脚本,因为这需要提升权限,超出当前 Windows 服务所允许的权限。 @RichG windows服务管理等更多操作流程需要管理员权限。我不知道如何通过C#控制windows服务,但是你的系统管理员可以设置你的windows服务启动类型为 Automatically,它提供了当机器重新启动时您的 Windows 服务会自动运行。我在我的答案中添加了如何做的链接。【参考方案2】:

我们已根据上述@Martheen 的建议纠正了该问题,现在一切正常。我们忽略 Windows 关闭事件,但在启动时查找用户的最后一次注销并使用该时间结束他们的会话,并在下次使用机器时提交。

谢谢

【讨论】:

以上是关于Windows 关闭时 Windows 服务引发错误的主要内容,如果未能解决你的问题,请参考以下文章

如何检测 Windows 关闭或注销

.Net的UPnP库[关闭]

未关闭虚拟机直接关闭vmware引发的一系列问题——Windows下linux虚拟机

windows7 Server 服务启动不了 报错

如何使用 C# 中的 Windows 服务跟踪给定进程是不是引发异常

使用 fiddler 捕获 Windows 商店应用程序流量引发异常