随便聊聊:为什么打补丁要重启

网友投稿 2026 2022-09-16

随便聊聊:为什么打补丁要重启

随便聊聊:为什么打补丁要重启

随便聊聊:为什么打补丁要重启

引子

我有一个朋友,因为最近微软出了很多漏洞修复补丁,导致需要频繁的打补丁。在打补丁重启之后,有些机器出现了蓝屏等等一起奇怪的问题。所以问题来了,为什么给Windows打补丁要重启,不重启行不行。

结论

先说结论,不重启大部分情况下是没问题的。但是​​不建议​​

需要重启的理由

动态链接库

在分析原因之前,需要先聊一下,为什么需要重启。在聊重启之前,又要聊一下Windows的​​动态链接库 (DLL) ​​。

动态链接库相当于组成乐高的不同砖块。有些是铺在底下的砖头,如果要更换这些砖头,就需要把这块砖上关联的东西都铲了(停止),才能更换。比如要拆除下图左下角的砖,换一个别的颜色。除了把整个风车拆除,别无她法。

对于Windows,操作系统的很多功能都由 DLL 提供。 此外,当您在这些操作系统中的一个Windows程序时,该程序的很多功能可能由 DLL 提供。 例如,某些程序可能包含许多不同的模块,并且程序的每个模块包含在 DLL 中并分发。 使用 DLL 有助于促进代码的模块化、代码重用、高效的内存使用并减少磁盘空间。 因此,操作系统和程序加载速度更快,运行速度更快,并且占用了更少的磁盘空间。

为什么会重启

知道了最重要的原理,回到为什么会重启的问题:安装安全更新后,如果满足下列条件之一,系统可能会提示您重新启动计算机:

安全更新将更新一个 DLL,该 DLL 加载在由 Windows 所需的一个或多个进程中安全更新将更新.exe文件,该文件当前作为应用程序所需的进程Windows安全更新将更新当前使用的设备驱动程序,以及当前Windows。 使用此设备驱动程序时无法完成更新,但是,你无法卸载此设备驱动程序,除非你关闭Windows。安全更新对注册表进行更改。 这些更改要求您重新启动计算机。安全更新将更改在您启动计算机时只读的注册表项。

说了那么多点,在于更新的过程,可能(很大概率)会修改Windows的基石。如果细心观察,有的小伙伴可能会遇到系统提示​​当前无法安装补丁,会在下一次重启时安装​​。

重启的几种状态

在我们双击补丁程序之后,可能会发生以下几种情况

没有任何提示,系统不要求重启要求重启提示在下一次重启时进行安装。

打补丁为什么会打出新问题

微软的补丁有一个特色,就是可能会解决一些问题的同时,带来一些新问题。

事情的根因大约可以归于动态链接库机制。不同的应用、服务、角色之间有着千丝万缕的关联。Windows上可以安装各种各样的软件、功能、角色,在补丁发版之前很难说做到万全的测试。如果很不幸的撞到了没有测试的项目上,就算中招了。

再比如,安装完某个补丁后没有重启,然后开始安装新的补丁。这种场景测试人员也很难复现。

更为严重的是,如果打补丁出现问题,也不见得次次都能还原回去。

重启能解决什么问题

回到最初的问题,虽然问题是打补丁为什么要重启(打完补丁之后重启),但在打补丁之前,我们提前重启一次,可以避免很多问题。

当前系统安装完补丁还未重启当前系统安装完某个软件后未重启当前系统的某个功能或角色,配置完成后还未重启

如果在安装补丁之前,提前重启一次,以上问题带来的潜在风险都可以避免。

检查是否需要重启

在打补丁之前重启,是为了避免存在一些已经要重启了但是没重启的情况,但是这种状态可以提前查询么?答案是肯定的。当重新启动挂起时,Windows 会添加一些注册表值来显示这一点。所以要做的就是检查这些各种各样的注册表。

下面的这个脚本来自​​Adam Bertram​​​,作者是​​微软的在任MVP​​。直接照抄就可以了。

展示效果具体是这样的

PS51> Test-PendingReboot.ps1 -ComputerName localhostComputerName IsPendingReboot------------ ---------------localhost False

以下是测试代码。

function TestPendingreboot($ComputerName){ #功能来源: if ($ComputerName -match ";") { $ComputerName = $ComputerName.split(";") } $scriptBlock = { function Test-RegistryKey { [OutputType('bool')] [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Key ) $ErrorActionPreference = 'Stop' if (Get-Item -Path $Key -ErrorAction Ignore) { $true } } function Test-RegistryValue { [OutputType('bool')] [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Key, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Value ) $ErrorActionPreference = 'Stop' if (Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) { $true } } function Test-RegistryValueNotNull { [OutputType('bool')] [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Key, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Value ) $ErrorActionPreference = 'Stop' if (($regVal = Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) -and $regVal.($Value)) { $true } } # Added "test-path" to each test that did not leverage a custom function from above since # an exception is thrown when Get-ItemProperty or Get-ChildItem are passed a nonexistant key path $tests = @( { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' } { Test-RegistryKey -Key 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress' } { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' } { Test-RegistryKey -Key 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\PackagesPending' } { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting' } { Test-RegistryValueNotNull -Key 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Value 'PendingFileRenameOperations' } { Test-RegistryValueNotNull -Key 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Value 'PendingFileRenameOperations2' } { # Added test to check first if key exists, using "ErrorAction ignore" will incorrectly return $true 'HKLM:\SOFTWARE\Microsoft\Updates' | ?{ test-path $_ -PathType Container } | %{ (Get-ItemProperty -Path $_ -Name 'UpdateExeVolatile' | Select-Object -ExpandProperty UpdateExeVolatile) -ne 0 } } { Test-RegistryValue -Key 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' -Value 'DVDRebootSignal' } { Test-RegistryKey -Key 'HKLM:\SOFTWARE\Microsoft\ServerManager\CurrentRebootAttemps' } { Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon' -Value 'JoinDomain' } { Test-RegistryValue -Key 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon' -Value 'AvoidSpnSet' } { # Added test to check first if keys exists, if not each group will return $Null # May need to evaluate what it means if one or both of these keys do not exist ('HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName' | ?{ test-path $_ } | %{ (Get-ItemProperty -Path $_).ComputerName }) -ne ('HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName' | ?{ test-path $_ } | %{ (Get-ItemProperty -Path $_).ComputerName }) } { # Added test to check first if key exists 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending' | Where-Object { (Test-Path $_) -and (Get-ChildItem -Path $_) } | ForEach-Object { $true } } ) foreach ($test in $tests) { if (& $test) { $true break } } } foreach ($computer in $ComputerName) { $connParams = @{ 'ComputerName' = $computer } $output = @{ ComputerName = $computer IsPendingReboot = $false } $psRemotingSession = New-PSSession @connParams if (-not ($output.IsPendingReboot = Invoke-Command -Session $psRemotingSession -ScriptBlock $scriptBlock)) { $output.IsPendingReboot = $false } [pscustomobject]$output } }

总结

想一想,因为疫情的紧张,我们已经知道出门要戴口罩。

先说结论,不​​带口罩​​​大部分情况下是没问题的。但是​​不建议​​

同理,打补丁重启其实没什么可讨论的,当把它当做一个预防和保护措施的时候,能够节省很多麻烦。当然最重要的是,打补丁之前要做足够多的验证。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:FreeFileSync文件同步软件操作指引以及功能介绍#yyds干货盘点#
下一篇:C# 数据操作系列 - 16 SqlSugar 完结篇(cctv5)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~