【问题标题】:Weird Issue With Windows Service - Service Timing OutWindows 服务的奇怪问题 - 服务超时
【发布时间】:2020-07-23 11:44:18
【问题描述】:

您好,我有一段旧版 (VS2010) Windows 服务代码已导入 VS2017,这让我非常沮丧。这段代码在过去 6 年里运行良好,但是当我执行安装并尝试启动服务时,SCM 会返回超时错误。 OnStart 代码如下:

Protected Overrides Sub OnStart(ByVal args() As String)
    'Instaniate the timer for the service
    _serviceTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf Tick), Nothing, 60000, 60000)
End Sub

回调是:

Private Sub Tick(ByVal state As Object)

    'Switch off the timer event whilst the code executes
    _serviceTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite)

    If Not _started Then
        Startup()
        _started = True
    End If

    Call ServerProcess()

    'Re-enable the timer now that application code has completed
    _serviceTimer.Change(_longInterval, _longInterval)
End Sub

我最初在 OnStart 方法中有启动过程,但为了解决此问题而将其删除,但它没有任何区别。方法启动如下:

Public Sub Startup()

    Try
        'Source these settings from the local config file
        _appDataFolder = Utilities.GetSetting("AppDataRoot")
        _configPathMapped = _appDataFolder & Utilities.GetSetting("ConfigPathMapped")
        _logPath = _appDataFolder & "\" & utl.GetSetting("LogPath")

        'Instaniate the timer for the service - Commented out after moving startup code from OnStart method
        ' _serviceTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf Tick), Nothing, Timeout.Infinite, Timeout.Infinite)

        'Initialise logging architecture
        _logger = New aslLog.Logger(_configPathMapped & "nlog.config", _logPath, My.Application.Info.ProductName, My.Application.Info.Version.ToString)
        _logger.SendLog("Started PSALERTS Schedule Server Service", NLog.LogLevel.Info, _serviceTimer, _checkInterval, Nothing)

        'Determine if the cloned config files exists in the mapped config file folder
        'We clone these files to a writable destination to allow us to overcome write restrictions ot the C: drive on the SPEN PTI Desktop model
        If Not System.IO.File.Exists(_configPathMapped & "psaservermachine.config") Then
            'Clone the app.config file in the config folder as psaservermachine.config
            Utilities.CloneFile(_programFileLocation & "PSALERTSScheduleServer.exe.config", _configPathMapped & "psaservermachine.config")
        End If

        If Not System.IO.File.Exists(_configPathMapped & "nlog.config") Then
            'Clone the nlog.config file
            Utilities.CloneFile(_programFileLocation & "PSALERTSScheduleServer.exe.config", _configPathMapped & "nlog.config")
        End If

        'Determine the Oracle TNS Environment
        'Check for the existence of the environment variable 'TNS_ADMIN'
        If Environment.GetEnvironmentVariable("TNS_ADMIN") IsNot Nothing Then

            'If TNS_ADMIN exists then we can continue with the application session 

        Else
            Dim oraTnsPath As String = ""
            'If it doesn't exist then we need to determine the Oracle information from the PATH environment variable
            oraTnsPath = GetOraTnsPath()

            If oraTnsPath <> "" Then
                'Then create the TNS_ADMIN environment variable
                Environment.SetEnvironmentVariable("TNS_ADMIN", oraTnsPath)
            Else

                'If no oracle client information exists then raise an error to this effect and exit the app
                'informing the user that they need to install the Oracle client in order to use PSALERTS

                Beep()
                Throw New PSALERTSOracleConfigException(
                                                "PSALERTS Oracle Configuration Error. PSALERTS Did not find a valid Oracle Client." & vbCrLf & vbCrLf &
                                                "Please install a valid Oracle Client and try again." & vbCrLf & vbCrLf &
                                                "If a valid Oracle Client is installed then ensure that the PATH environment variable contains an entry for the Oracle Client." & vbCrLf & vbCrLf &
                                                "For example - TNS_ADMIN=C:\oracle\12.1.0\Client_lite\NETWORK\ADMIN"
                                                )

            End If

        End If

        'Register the application
        If Not Registered() Then
            'Register the application
            Register()

        End If


        If Registered() Then
            'Clean/close any stray Excel processes from previous debug session
            If _debugModeOn Then
                CleanUpRedundantProcesses("EXCEL", "PSALERTS")
            End If

            'instantiate fresh excel session
            _myXLApp = New Excel.Application

            'Get the timer interval settings
            _longInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "LongIntervalMillis"), Integer)
            _initInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "InitialIntervalMillis"), Integer)
            _refreshInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "InitialIntervalMillis"), Integer)

            'Re-start the timer with periodic signalling as per the specified check interval
            _serviceTimer.Change(_initInterval, _initInterval)

        Else
                _started = False
        End If
    Catch ex As Exception
        _logger.SendLog("PSALERTS Schedule Server startup failure.", NLog.LogLevel.Error, ex)
    Finally

    End Try
End Sub

我对许多类似的服务使用了类似的技术,它们运行良好。希望从那里的任何 Windows 服务专家那里获得一些见解。哦,我使用 WiX 进行安装,对于许多类似的此类应用程序来说,这又是一个陈旧的模板。

亲切的问候 保罗·J。

【问题讨论】:

  • 您是否尝试过将调试器附加到您的服务以准确找出超时的位置?您没有提到这是否发生在您的开发机器上,或者仅在生产部署之后发生。旧的 VS2010 服务是否在同一台机器上运行?您是否为您的服务提供了足够高的运行权限?
  • 不是服务大师,而是部署人员。首先要验证您是否在手动复制所有文件后尝试手动启动此服务,然后您也看到它失败了?当然,您也可以禁用 MSI 内的服务启动并安装 MSI,然后尝试通过服务小程序手动启动服务。
  • @Hursey - 无法附加调试器,就好像服务的 OnStart 方法没有启动一样。这是在开发机器上。当前的生产版本是以前的版本,尽管 OnStart 代码与正在开发的当前版本相同。生产代码在Win7机器上。
  • @Stein Asmul - 手动安装服务没有任何问题。我调试问题的第一种方法是禁用 product.wsx 文件中的服务控制元素。
  • 从您的描述中猜想捕获的日志没有发生?如果您将启动方法放在哪里并将其放入控制台应用程序中会发生什么。只是为了排除是代码问题还是服务问题

标签: vb.net visual-studio-2017 wix windows-services


【解决方案1】:

核心:最典型的错误:

  • 配置问题:连接字符串、错误路径等...
  • Boot startup problem(好列表 - 来自常见问题解答)
  • 密码错误 / 登录帐户 以具有密码的真实用户身份运行时。
  • 文件丢失运行时丢失
  • 权限问题(缺少 ACL / NT 权限)。

Maybe check this answer before the below.


更新Maybe have a look at this previous answer。服务启动时间问题。还可以在同一页面中查看我的临时答案。

调试器:除此之外 - 没有什么比使用调试器单步调试代码更好的了。我已经很久没有这样做了。部署调试二进制文件并尝试? Windows 10 现在隐藏来自服务的消息 - 不确定这对调试器有何影响:No more switching to Session 0


我不是服务专家,而是部署专家。我只会提供一些链接,看看是否有帮助。 Maybe I have not fully understood the whole problem. I tend to focus on the deployment side and not so much development side.

想法列表/调试检查列表:这些是一般应用程序可能出错的“想法列表” - 不仅仅是服务(前两个列表相似 -相隔一段时间创建):

  1. Crash on launch
  2. Desktop application won't launch
  3. General purpose WiX / MSI links

是的,这些列表非常通用 - 太大而无法消化。只需略读我认为的前两个即可。

调试工具:同时提醒最有用的服务调试工具:Event ViewerTask Manager strong>、Services.mscProcess Explorer(系统内部)、The NET commandSC.exe

良好服务常见问题解答https://www.coretechnologies.com/WindowsServices/FAQ.html

【讨论】:

  • 好的,作为解决问题的可能途径,我从使用 system.threading.timer 更改为 system.timers.timer。该服务现在响应本地计算机上的服务已启动然后停止。如果某些服务没有被其他服务或程序使用,它们会自动停止。
  • 抱歉使用评论传递新代码,无法弄清楚如何添加到原始帖子中。修改后的 OnStart 为: Protected Overrides Sub OnStart(ByVal args() As String) _serviceTimer = New System.Timers.Timer AddHandler _serviceTimer.Elapsed, New Timers.ElapsedEventHandler(AddressOf Tick) _serviceTimer.Interval = _longInterval _serviceTimer.Enabled = True '确保计时器不作为垃圾收集 GC.KeepAlive(_serviceTimer) End Sub 对 Startup 方法的调用发生在 Delegate Tick 中。
【解决方案2】:

您的启动方法应该启动一个后台工作程序并快速返回到它已启动的 SCM。系统范围的默认设置为 30 秒,但老实说,适当的服务应该在几秒钟内做出响应。

查看您的代码,您与数据库的连接可能是导致问题的长杆。

【讨论】:

  • 查看评论 @Stein Asmul - OnStart 方法现在只包含计时器对象的实例化。 SCM 现在马上回来了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多