解決Win8.1 / Win Server 2012 r2 下安裝 Visual Studio 時一直要求重新啟動的問題(原創)


注:本文為作者原創文章,轉載於引用請注明出處,謝謝。

今天在x64的英文版Windows Server 2012 r2上安裝最新版的 Visual Studio 2015 Exterprise 時,提示需要重新啟動:

 

於是我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 ,同樣刪除之;

沒有重啟的情況下嘗試重新安裝,成功進入安裝環節!

 

 

 吁~忙了一下午,終於搞定!

此時聯想到之前裝完系統更新時提示要重啟,可后來重啟過后還是要求重啟,當時也沒注意,沒想到又給碰上了,真是緣分!

到此為止,事情可遠遠沒有結束,明天用VS調試CEC2014程序導致MATLAB調用func19~30崩潰的問題,估計又得一整天了……還有POWELL法和DE的結合測試,想着就頭皮發麻……自己選的路,喊着淚也得走下去哇

最后,原此篇文章能幫到更多的人!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM