解决Win8.1 / Win Server 2012 r2 下安装 Visual Studio 时一直要求重新启动的问题(原创)

时间:2022-12-28 18:44:20

注:本文为作者原创文章,转载于引用请注明出处,谢谢。

今天在x64的英文版Windows Server 2012 r2上安装最新版的 Visual Studio 2015 Exterprise 时,提示需要重新启动:

解决Win8.1 / Win Server 2012 r2 下安装 Visual Studio 时一直要求重新启动的问题(原创)

 

于是我restart了N次,可还是不行,在网上进行搜索,发现能在日志文件中找到原因,日志文件在C:\Users\%username%\AppData\Local\Temp中,或者直接在安装界面点“日志文件”进入。

参考日志文件的Condition(环境检查)部分:

   [0A60:1530][2015-07-10T18:48:07]i000: MUX:  Failed to download the update xml file from http://go.microsoft.com/fwlink/?LinkID=500683 Setup will not be updated.
[0A60:1530][2015-07-10T18:48:07]i052: Condition '(VersionNT = v6.3) AND (WindowsBuildNumber < 9600)' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition 'CompatibilityMode = 0' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition 'NOT((VersionNT > v6.1) OR (VersionNT = v6.1 AND ServicePackLevel >= 1))' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '(NOT IsLanguagePack) AND ( CurrentOperation = "Install" ) AND ( FLP_Version > v14.0.22823 )' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition 'RebootPending = 1' evaluates to true.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition 'NOT (IEsvcVersionExists) OR (IEsvcVersion < v10.0)' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '(VersionNT < v6.2) AND ((NetworkAvailable = 0) OR (DisableRootAutoUpdate = 1)) AND NOT ((MicrosoftRootCertificateAuthority2011RootExists OR MicrosoftRootCertificateAuthority2011AuthRootExists) AND (MicrosoftRootCertificateAuthority2010RootExists OR MicrosoftRootCertificateAuthority2010AuthRootExists))' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '( CurrentOperation = "Install" AND EnterpriseExists )' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '( CurrentOperation = "Install" AND UltimateExists )' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '( CurrentOperation = "Install" AND NOT EnterpriseExists AND ProfessionalExists)' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '(VersionNT = v6.3) AND (KB2919355_amd64_CurrentState <> 112 AND KB2919355_x86_CurrentState <> 112)' evaluates to false.
[0A60:
1530][2015-07-10T18:48:07]i052: Condition '(VersionNT = v6.3) AND (netfxfullredist_43_DetectKey < v4.5.22816)' evaluates to false.

 

发现当VS进行安装前的环境检查时,当结果为 false 时代表检查通过,结果为 true 时代表没有通过安装环境检查。

日志中显示没有通过检查的有:

[0A60:1530][2015-07-10T18:48:07]i052: Condition 'RebootPending = 1' evaluates to true.

这个'RebootPending = 1'代表系统需要重启,可问题是:我重启了之后RebootPending还是等于1,这就是问题之所在

于是,在网上寻找各种关于'RebootPending = 1'的解决方案,归结于以下几种:

  1. 重启直接选择 restart 而不是 shut down 再开机。
  2. 关闭系统的休眠功能:管理员模式运行命令行,输入powercfg.exe /hibernate off 进行关闭休眠。关闭休眠后等于关闭了 win8 及以上系统的快速启动功能,这样能使得系统能真正地重启,而不是休眠之后快速启动。
  3. 在注册表中将键值HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Updates\UpdateExeVolatile 设为0;将键 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations 删除。

在尝试以上方法之后,有可能解决一部分人的问题,可偏偏我就是另外一部分,特别是连键值HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Updates\UpdateExeVolatile 都找不到。

网上能找的都找了,花了好几个小时,没办法,只能换一种思路:

 


 思路:既然你要检查系统是否需要重新启动,那我是否能伪造一种不需要重新启动的状态给你看?

于是寻找目前检查系统重启状态的方法,发现如下方案:

https://blogs.technet.microsoft.com/heyscriptingguy/2014/10/15/use-powershell-dsc-to-check-pending-reboot/

以及它的参考:

https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542

其中使用的是 Windows power shell 对注册表进行读取、判断,从而确定 RebootPending 的值。代码如下:

Function Get-PendingReboot 
{
<
#
.SYNOPSIS
Gets the pending reboot status on a local or remote computer.

.DESCRIPTION
This
function will query the registry on a local or remote computer and determine if the
system is pending a reboot, from either Microsoft Patching or a Software Installation.
For Windows 2008+ the function will query the CBS registry key as another factor in determining
pending reboot state.
"PendingFileRenameOperations" and "Auto Update\RebootRequired" are observed
as being consistant across Windows Server
2003 & 2008.

CBServicing
= Component Based Servicing (Windows 2008)
WindowsUpdate
= Windows Update / Auto Update (Windows 2003 / 2008)
CCMClientSDK
= SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
PendFileRename
= PendingFileRenameOperations (Windows 2003 / 2008)

.PARAMETER ComputerName
A single Computer or an array of computer names. The
default is localhost ($env:COMPUTERNAME).

.PARAMETER ErrorLog
A single path to send error data to a log file.

.EXAMPLE
PS C:\
> Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize

Computer CBServicing WindowsUpdate CCMClientSDK PendFileRename PendFileRenVal RebootPending
-------- ----------- ------------- ------------ -------------- -------------- -------------
DC01
False False False False
DC02
False False False False
FS01
False False False False

This example will capture the contents of C:\ServerList.txt and query the pending reboot
information from the systems contained
in the file and display the output in a table. The
null values are by design, since these systems
do not have the SCCM 2012 client installed,
nor was the PendingFileRenameOperations value populated.

.EXAMPLE
PS C:\
> Get-PendingReboot

Computer : WKS01
CBServicing :
False
WindowsUpdate :
True
CCMClient :
False
PendComputerRename :
False
PendFileRename :
False
PendFileRenVal :
RebootPending :
True

This example will query the local machine
for pending reboot information.

.EXAMPLE
PS C:\
> $Servers = Get-Content C:\Servers.txt
PS C:\
> Get-PendingReboot -Computer $Servers | Export-Csv C:\PendingRebootReport.csv -NoTypeInformation

This example will create a report that contains pending reboot information.

.LINK
Component
-Based Servicing:
http:
//technet.microsoft.com/en-us/library/cc756291(v=WS.10).aspx

PendingFileRename
/Auto Update:
http:
//support.microsoft.com/kb/2723674
http:
//technet.microsoft.com/en-us/library/cc960241.aspx
http:
//blogs.msdn.com/b/hansr/archive/2006/02/17/patchreboot.aspx

SCCM
2012/CCM_ClientSDK:
http:
//msdn.microsoft.com/en-us/library/jj902723.aspx

.NOTES
Author: Brian Wilhite
Email: bcwilhite (at) live.com
Date: 29AUG2012
PSVer:
2.0/3.0/4.0/5.0
Updated: 01DEC2014
UpdNote: Added CCMClient property
- Used with SCCM 2012 Clients only
Added ValueFromPipelineByPropertyName
=$true to the ComputerName Parameter
Removed
$Data variable from the PSObject - it is not needed
Bug with the way CCMClientSDK returned null value
if it was false
Removed unneeded variables
Added PendFileRenVal
- Contents of the PendingFileRenameOperations Reg Entry
Removed .Net Registry connection, replaced with WMI StdRegProv
Added ComputerPendingRename
#>

[CmdletBinding()]
param(
[Parameter(Position
=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias(
"CN","Computer")]
[String[]]
$ComputerName="$env:COMPUTERNAME",
[String]
$ErrorLog
)

Begin { }## End Begin Script Block
Process {
Foreach ($Computer in $ComputerName) {
Try {
## Setting pending values to false to cut down on the number of else statements
$CompPendRen,$PendFileRename,$Pending,$SCCM = $false,$false,$false,$false

## Setting CBSRebootPend to null since not all versions of Windows has this value
$CBSRebootPend = $null

## Querying WMI for build version
$WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $Computer -ErrorAction Stop

## Making registry connection to the local/remote computer
$HKLM = [UInt32] "0x80000002"
$WMI_Reg = [WMIClass] "\\$Computer\root\default:StdRegProv"

## If Vista/2008 & Above query the CBS Reg Key
If ([Int32]$WMI_OS.BuildNumber -ge 6001) {
$RegSubKeysCBS = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\")
$CBSRebootPend = $RegSubKeysCBS.sNames -contains "RebootPending"
}

## Query WUAU from the registry
$RegWUAURebootReq = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
$WUAURebootReq = $RegWUAURebootReq.sNames -contains "RebootRequired"

## Query PendingFileRenameOperations from the registry
$RegSubKeySM = $WMI_Reg.GetMultiStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\","PendingFileRenameOperations")
$RegValuePFRO = $RegSubKeySM.sValue

## Query ComputerName and ActiveComputerName from the registry
$ActCompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\","ComputerName")
$CompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\","ComputerName")
If ($ActCompNm -ne $CompNm) {
$CompPendRen = $true
}

## If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
If ($RegValuePFRO) {
$PendFileRename = $true
}

## Determine SCCM 2012 Client Reboot Pending Status
## To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
$CCMClientSDK = $null
$CCMSplat = @{
NameSpace
='ROOT\ccm\ClientSDK'
Class
='CCM_ClientUtilities'
Name
='DetermineIfRebootPending'
ComputerName
=$Computer
ErrorAction
='Stop'
}
## Try CCMClientSDK
Try {
$CCMClientSDK = Invoke-WmiMethod @CCMSplat
} Catch [System.UnauthorizedAccessException] {
$CcmStatus = Get-Service -Name CcmExec -ComputerName $Computer -ErrorAction SilentlyContinue
If ($CcmStatus.Status -ne 'Running') {
Write
-Warning "$Computer`: Error - CcmExec service is not running."
$CCMClientSDK = $null
}
} Catch {
$CCMClientSDK = $null
}

If ($CCMClientSDK) {
If ($CCMClientSDK.ReturnValue -ne 0) {
Write
-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
}
If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) {
$SCCM = $true
}
}

Else {
$SCCM = $null
}

## Creating Custom PSObject and Select-Object Splat
$SelectSplat = @{
Property
=(
'Computer',
'CBServicing',
'WindowsUpdate',
'CCMClientSDK',
'PendComputerRename',
'PendFileRename',
'PendFileRenVal',
'RebootPending'
)}
New
-Object -TypeName PSObject -Property @{
Computer
=$WMI_OS.CSName
CBServicing
=$CBSRebootPend
WindowsUpdate
=$WUAURebootReq
CCMClientSDK
=$SCCM
PendComputerRename
=$CompPendRen
PendFileRename
=$PendFileRename
PendFileRenVal
=$RegValuePFRO
RebootPending
=($CompPendRen -or $CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename)
}
| Select-Object @SelectSplat

} Catch {
Write
-Warning "$Computer`: $_"
## If $ErrorLog, log the file to a user specified location/path
If ($ErrorLog) {
Out
-File -InputObject "$Computer`,$_" -FilePath $ErrorLog -Append
}
}
}
## End Foreach ($Computer in $ComputerName)
}## End Process

End { }## End End

}
## End Function Get-PendingReboot

发现其对一下几个主键进行读取:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\ComputerName 

 于是我开始寻找这些主键:

  • 第一个没找到,尝试删除之下的 SessionsPending ,被拒绝;
  • 找到了第二个对应的 RebootRequired ,里头有东西,备份后删除之;
  • 找到第三个对应的 PendingFileRenameOperations ,同样删除之;

没有重启的情况下尝试重新安装,成功进入安装环节!

 解决Win8.1 / Win Server 2012 r2 下安装 Visual Studio 时一直要求重新启动的问题(原创)

 

 吁~忙了一下午,终于搞定!

此时联想到之前装完系统更新时提示要重启,可后来重启过后还是要求重启,当时也没注意,没想到又给碰上了,真是缘分!

到此为止,事情可远远没有结束,明天用VS调试CEC2014程序导致MATLAB调用func19~30崩溃的问题,估计又得一整天了……还有POWELL法和DE的结合测试,想着就头皮发麻……自己选的路,喊着泪也得走下去哇解决Win8.1 / Win Server 2012 r2 下安装 Visual Studio 时一直要求重新启动的问题(原创)

最后,原此篇文章能帮到更多的人!解决Win8.1 / Win Server 2012 r2 下安装 Visual Studio 时一直要求重新启动的问题(原创)