Windows 服务中 OnShutdown() 事件的奇怪行为

Weird behavior with OnShutdown() event in a Windows Service

我在vb.net(VS2017,目标.net Framework 4.5)中开发了windows服务
windows 服务自动执行 sql- 服务器备份(基于计时器),删除旧的备份文件,读写 .ini 文件并在某些情况下发送电子邮件和 - 诅咒 - 写入事件日志.该服务必须在 windows 服务器 2019(标准)上 运行。
一切都按预期工作 - 除了 OnShutdown() 事件的处理,这让我发疯,因为它是一个“移动目标”
如果服务器关闭(正常情况应该是“重启”),我想:

我的代码zu OnShutdown():

Protected Overrides Sub OnShutdown()
  cModul = "OnShutdown()"
  ProtokollSchreiben("Der Server wird heruntergefahren...", Typ_Warning)
 '
  DebugProtokollSchreiben("Timer stoppen und anhalten...", Typ_Warning)
  MyTimer.Stop()
  MyTimer.Enabled = False
  DebugProtokollSchreiben("Timer gestoppt und angehalten...", Typ_Warning)
  DebugProtokollSchreiben("Der Server wird heruntergefahren...", Typ_Warning)
  DebugProtokollSchreiben("Vor schreiben .ini...", Typ_Warning)
  cIniFile.WriteInteger("WindowsService", "ServerWurdeGebooted", 1)
  DebugProtokollSchreiben("Nach schreiben .ini...", Typ_Warning)
  DebugProtokollSchreiben("Vor MailversandServerReboot...", Typ_Warning)
  MailversandServerReboot()
 cModul = "OnShutdown()"
  DebugProtokollSchreiben("Nach MailversandServerReboot...", Typ_Warning)
 '
   MyBase.OnShutdown()' call “original event”
End Sub

备注:
我设置:

Me.CanShutdown = True

在设计器代码中,并在事件日志中写入启动时的实际值(CanShutdown 在 运行 时设置为真)。
在 ProtokollSchreiben() 和 DebugProtokollSchreiben() 中,仅写入日志条目。 在 MailversandServerReboot() 中,通过 SMTP 发送电子邮件(这在服务的其他部分没有问题)。

行为:

我已经在互联网上搜索并阅读了这个 SO-Links:
detect shutdown in window service
Windows Service does seem to do nothing OnShutdown()
Can a Windows Service take hours to shutdown gracefully?

据我所知,我应该有大约 20 秒的时间在 OnShutDown() 中做一些事情。
写入事件日志和 .ini 应该不会花费一秒钟....
也许,发送电子邮件(在函数“MailversandServerReboot()”中)可能需要更长的时间,或者当 OnShutdown() 被触发时,电子邮件可能无法发送,因为其他(需要的)服务已关闭...
但是,我不明白,事件有时会被调用,有时不会,如果它被调用,那么大多数条目“Nach schreiben .ini ...”不会写入事件日志。
感谢任何提示:-)

首先,感谢@craig 对我的打字错误的评论(在我的第一篇文章中,我使用 my.OnShutdown() 而不是 MyBase.OnShutDown()。我现在已经在我的文章中更正了这个(但这并不能解决我的问题)。也感谢@CoreTech 的评论。
看来,我现在已经找到了 my 需求的解决方法...
我进一步查询了互联网并做了很多“try-and-errors”。
我个人的发现(可能有误):
看起来,在 OnShutDown() 事件中几乎没有任何保证,因为系统(服务器和服务)以不明确定义的顺序.
下降 所以...也许可以写入事件日志中的条目,也许不能。 也许可以写入(自定义).ini 中的条目,也许不能。
通过我的尝试,我从未能够在 OnShutDown() 中使用 SMTP 发送电子邮件(通过 SMTP-server)。
这可以解释我奇怪的(不理解的)问题(“移动目标”)。
我只是想知道,当服务器关闭并发送电子邮件时,通知客户(和我们)(以及何时) 服务器已启动并且 windows 服务再次启动 运行.
并且仅当服务器 确实被启动时 (不是每次启动服务时都会启动:-)。
所以..我现在做什么(似乎有效 -> 测试了大约 20 次):

Protected Overrides Sub OnShutdown()
  cModul = "OnShutdown()"
' Write a Flag-File to the Server reboot including a timestamp
  Dim cZeitpunkt As String = System.DateTime.Now.ToShortDateString.ToString.ToString
  cZeitpunkt = cZeitpunkt + ", " + System.DateTime.Now.ToShortTimeString.ToString
  System.IO.File.WriteAllText(cFlagFileNameMitPfad, "Der Windows-Server zum SQL-Server 2019 (WPE) wurde heruntergefahren am: " + cZeitpunkt)
'
' Create an additional file in a sub directory to see, THAT the server was rebooted (also after the service was restarted an had deleted the file in the OnStart() event)
'
' Check if subdirectory exists -> if not -> create it
  If Not System.IO.Directory.Exists(cSaveFlagVerzeichnis) Then
    System.IO.Directory.CreateDirectory(cSaveFlagVerzeichnis)
  End If

‘ Generate DateTimeStamp for Filename (own function)
  Dim cFileTimeStamp As String = DateTime2StringFileName(System.DateTime.Now)
' Do some minor changes to the needed format (cut leading “_” and add it an the end)
  cFileTimeStamp = cFileTimeStamp.Substring(1, cFileTimeStamp.Length - 1) + "_"
  Dim cFlagFileNameSave As String = cSaveFlagVerzeichnis + "\" + cFileTimeStamp + cFlagFileName
' Write the additional file
 System.IO.File.WriteAllText(cFlagFileNameSave, "Der Windows-Server zum SQL-Server 2019 (WPE) wurde heruntergefahren am: " + cZeitpunkt)
'
' Write to the event log (note: it is not guaranteed, that the entries are written, but it’s only informative)
  ProtokollSchreiben("Der Server wird heruntergefahren, Flag-File wurde geschrieben..", Typ_Warning)
  DebugProtokollSchreiben("Der Server wird heruntergefahren, Flag-File wurde geschrieben..", Typ_Warning)
'
  MyBase.OnShutdown() ' Call original event
End Sub

备注:
在启动时,我得到启动路径(到服务)。 “主标志文件”被写入该目录。 “保存标志文件”写在该目录的子目录中(另请参见下面的屏幕截图)。

为了更好地理解: “根目录”是\prog\ ( 1 )。 在子目录 \SaveRebootFlags\ ( 2 ) 中,每次重启都会保留一个标志文件。
任何 文件 ( 3 ) 包含带有 服务器关闭 时间戳的文本(而不是 windows 服务重启) 在“根目录”\prog\ ( 1 )写了一个类似的flag文件,
但没有日期时间戳(仅 ( 4 ))...所以此文件名始终相同。
在服务的 OnStart() 中,我检查了标志文件是否存储在“根目录”\Prog\ ( 1 ) 中。
如果是,将发送一封电子邮件“服务器在 'timestamp in flag file' 关闭,windows 服务已重新启动并再次运行...”。
发送邮件后,“主标志文件”自动删除
注意:因为我们在 ( 2 ) 中也有文件,所以我们可以理解任何重启。
这不是我最初想要的,但它有效(至少对我而言;-)。
也许这对某些人有帮助,但也被一种奇怪的行为“绊倒”了……