Install Internet Explorer 11 with WSUS

Internet Explorer support/lifecycle: better safe than sorry

You should proably know that your browser should stay up-to-date not only because of security issues being fixed or any security or non-security related improvements introduced. Now, it will have to be aligned with the the lastest supported major version of Internet Explorer. The end-of-life of Internet Explorer on a per-OS basis has changed. Microsoft announced in August 2014 that:
IE11-support-changes
Source: http://blogs.msdn.com/b/ie/archive/2014/08/07/stay-up-to-date-with-internet-explorer.aspx

Any guidance available?

Let’s have a look at the guidance on how to deploy Internet Explorer 11 on Windows 7 with WSUS.

I found the following technet page but it’s not exactly what I was looking for:
Install Internet Explorer 11 (IE11) – Windows Server Update Services (WSUS)

You may not know but it’s recommended to uninstalll previous IE9 before installing Internet Explorer 11
Source: https://support2.microsoft.com/kb/2872074/en-us

This page shows how to uninstall Internet Explorer from the commandline.
IE11-IE9-uninstall

That’s it for the official guidance :-( If you’ve a better link – an official one pointing to Microsoft’s website – , please feel free to post it in the comments, I may update this article to share it :-)

Approve the Internet Explorer 11 on WSUS

Internet Explorer 11 is classified in the “Update Rollup” category. This category should be selected in the WSUS settings and the catalog should have been synchronised.

You cannot actually directly approve Internet Explorer 11 like any security update. If you try, you’ll get an error message saying:
“This Update has Microsoft Software License Terms that must be accepted before it can be deployed.”
W7-IE11-LicenseApprovalRequired

If I list all the properties of the Internet Explorer 11, we can that the license has not been approved yet:
W7-IE11-BeforeLicenseApproval

Fortunately, there’s a license approval method named ‘AcceptLicenseAgreement’ :-)
W7-IE11-LicenseApprovalMethod

Once the IE11 license has been approved, the properties are:
W7-IE11-AfterLicenseApproval

Here’s the piece of code I used to approve all required updates for Internet Explorer 11

(Get-WsusServer).SearchUpdates("Internet Explorer 11")| 
Where {
 -not($_.IsSuperseded) -and
 -not($_.isApproved)   -and 
 $_.Title -match "Windows\s7\sfor\sx64\-(based|Edition)" 
} | ForEach-Object {
 if($_.RequiresLicenseAgreementAcceptance) {
  $_.AcceptLicenseAgreement()
  Write-Verbose -Message "License accepted for $($_.Title)" -Verbose
 }
 $_.Approve(
  [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install,
  $targetgroup            
 )
}

Any post-installation updates required?
If you deploy Internet Explorer 11, you’ll have to apply post-installation security updates
Currently (on August 14) this is what is approved updates on WSUS

(Get-WsusServer).SearchUpdates("Internet Explorer 11")| ? {
    ($_.isApproved)   -and 
    $_.Title -match "Windows\s7\sfor\sx64\-(based|Edition)" 
} |
Select Title,isApproved,isSuperseded,SecurityBulletins,
@{l='Revision';e={$_.Id.RevisionNumber}},CreationDate,UpdateClassificationTitle | 
ft -AutoSize

W7-IE11-ApprovedUpdates

What’s the client ‘experience’?
On the Windows 7 client, some prerequisites updates have been approved and installed along with Internet Explorer 11:
W7-IE11-WUA-install

To confirm that Internet Explorer 11 was installed on the client, you can watch for the event ID 19.

$HT= @{
 LogName = 'System' ;
 ProviderName = 'Microsoft-Windows-WindowsUpdateClient';
}
Get-WinEvent -FilterHashtable $HT -MaxEvents 10

IE11-installed-event
Once Internet Explorer 11 has been installed and Windows 7 restarted, a bunch of post-installation updates are still required to be installed on the Windows 7 client
W7-IE11-PostInstallAfterReboot

Conclusion: When you deploy Internet Explorer 11 through WSUS, it’s fairly easy but it requires unfortunately 2 scans/installs + reboot to finally get a fully secured and up-to-date version of Internet Explorer 11 :-)
If it’s manually deployed, you can achieve the same thing with a single reboot. Thanks to DISM, you can chain the uninstallation of IE9, the installation of the prerequisites, IE11 itself plus its post-installation updates and reboot.

Bonus: Here are two useful links if you manage IE11 in a corporate environment

Windows Assessment and Deployment Kit (Windows ADK) 10 RTM available

ADK-screen

I’ve updated the script on github that downloads ADK files for Windows 10
https://github.com/p0w3rsh3ll/ADK/tree/master/v10.0.26624

I’ve also added a new file that contains the checksums of files.
If you’ve downloaded the files into C:\ADK\v10, you can use the following code to check the integrity of these files:

$uri = 'https://raw.githubusercontent.com/p0w3rsh3ll/ADK/master/v10.0.26624/SHA256SUMS.csv'
Invoke-WebRequest -URI $uri -OutFile ~/documents\SHA256SUMS.csv
Import-Csv  ~/documents\SHA256SUMS.csv -Delimiter ";" | Foreach-Object {
 if ( (Get-FileHash -Path (Join-Path -Path C:\ADK\v10 -ChildPath $($_.File))).Hash -eq $_.Hash) {
  Write-Verbose -Message "OK: $($_.File)" -Verbose
 } else {
  Write-Warning -Message "NOK: $($_.File)"
 }
}

NB: the installation log of the ADK says it’s verifying packages before installing themADK.setup.log.verified.packages

Enjoy :-D

Scripting Games 2015 event 2

The Scripting Games are back :-D, excellent!

The puzzle of August is live at http://powershell.org/wp/2015/08/01/august-2015-scripting-games-puzzle/
SG2015-August.00

First, you should copy/paste the URL proposed in the puzzle – http://www.telize.com/geoip – into a browser to see what it looks like.
SG2015-August.06

We can see a pretty straight-forward reply formatted in JSON. Nice! This allows PowerShell versions as of 3.0 to use the built-in Invoke-WebRequest cmdlet to get the content of this webpage and the built-in *-Json cmdlets to convert the JSON content into a PowerShell object.
This also allows to solve the puzzle with a simple one-liner:

(iwr "http://www.telize.com/geoip").Content|
ConvertFrom-Json|ft *tude,con*,t*

With all commands and parameter names spelled out:

(Invoke-WebRequest -URI "http://www.telize.com/geoip").Content|
ConvertFrom-Json|Format-Table -Property *tude,con*,t*

That’s fairly easy if you have a recent version of PowerShell, isn’t it. Now, let’s think 2 minutes what you’d have done if you only had PowerShell version 2.0.

Fun? Ugly? Having a recent PowerShell version saves you a lot of time.

SG201508-Wx
Bonus:
If you go to http://www.telize.com , you can read how to interact with the endpoint and that it offers a REST API, which means you can go down another route and use the built-in Invoke-RestMethod cmdlet.

Weird issues when msxml3.dll fails

  • Symptoms
  • I’ve recently had the following symptoms on a computer:

    • Clicking on ‘properties’ after right click on ‘computer’ in the start menu doesn’t do anything

      computer-properties

    • I cannot launch eventvwr.msc or eventvwr.exe without getting an error message although I can launch mmc.exe and load the snap-in successfully to read the eventlogs
      mmc-fail
    • Opening the Windows Update applet from the Control Panel doesn’t work
    • the AV UI fails
      AV-fails
    • The volume shadow copy service complains all the time
      Volume Shadow Copy Service error: Unexpected error calling routine CoCreateInstance. hr = 0x80040154, Class not registered

      VSS-2

    • The servicing stack is idle and running the System Update Readiness tool to fix Windows corruption errors fails with the following error message:
      Windows update could not be installed because of error 2147746132 “Class not registered”
      wusa-fails

      wusa-fails-2
      NB: I can still extract what’s in the Windows6.1-KB947821-v34-x64.msu file and run checksur.exe manually.

  • More clues
    • The WindowsUpdate.log file indicates:
      WU-log
    • The volume shadow copy service also reports
      VSS-1
    • and clicking “manage” after right-clicking ‘computer in the start menu ends with the following error message:
      msxml3.dll is either not designed to run on Windows or it contains an error
      msxml-error
  • What’s the problem
  • Everything says msxml3.dll has a problem. Right?

  • What’s the root cause
    • The msxml3.dll is actually empty:
      msxml-error-2
    • and the CBS logs says, it started applying a package supposed to replace msxml3.dll
      CBS-1
    • but 2 minutes later, it reported it cannot parse XML anymore
      CBS-2
    • What happened during these 2 minutes….is actually a power loss :-(
      loss-power
  • My fix
  • # Gather all msxml3.dll files under %windir%
    $all = dir C:\Windows\* -inc msxml3.dll -rec -for -ea 0
    # restore the most recent version from the component store
    robocopy ($all | Where { $_.FullName -match "amd64" } | sort lastwritetime | Select -Last 1).Directory C:\Windows\system32  msxml3.dll /B
    # register the dll
    regsvr32 C:\Windows\system32\msxml3.dll
    # if that fails, try with the n-1 version
    robocopy ($all |
    Where { $_.FullName -match "amd64" } |
    sort lastwritetime |
    Select -last 2)[0].Directory C:\Windows\system32  msxml3.dll /B
    regsvr32 C:\Windows\system32\msxml3.dll
    
  • Steps to reproduce the problem
  • # unregister the dll
    regsvr32 /u C:\Windows\system32\msxml3.dll
    # create an empty file
    New-Item C:\Windows\temp -Name msxml3.dll -ItemType File
    # stop services that lock msxml3.dll
    Stop-Service -Name WSearch,WinRM -Verbose
    # kill processes that lock msxml3.dll
    taskkill /im explorer* /f
    # restore the file (ab)using the backup privilege
    robocopy C:\Windows\temp c:\windows\system32 msxml3.dll /r:0 /B
    

    Trigger ConfigMgr client actions

    A few weeks ago, I came across the following article on refreshing the System Center Configuration Management client

    Whenever I see a script, I always wonder, could it be done with a oneliner ?
    sms_client-actions-01

    As long as the script doesn’t care about the order of the ConfigMgr actions to be performed, yes, it’s achievable this way:

    (New-Object -COM 'CPApplet.CPAppletMgr').GetClientActions() | 
    Where { 
        $_.Name -match "(\sPolicy$)|(Collection\sCycle$)|(Updates)"
    } | ForEach-Object {
        try {
            $_.PerformAction()
            Write-Verbose -Message "Successfully executed $($_.Name)" -Verbose
        } catch {
            Write-Warning -Message "Failed to execute $($_.Name)"
        }
    }
    

    I’ve even added some filtering on action names and error handling.

    sms_client-actions-02
    There’s always more than one way to skin a cat with PowerShell ;)

    How to use WDS to PXE Boot a Nano Server VHD with PowerShell

    Last week I was renewed as a Windows PowerShell MVP MVP-2015-award, my article about how to use WDS to PXE Boot a Nano Server VHD with PowerShell was published on PowerShell Magazine and even mentioned on the Nano Server blog. Awesome, isn’t it :-D
    I’d like to thank everyone who enjoys my work, reads my blog, supported me and helped me along the way. I wouldn’t have been awarded without you. Again, a big thank you! I’m very pleased and honoured to receive this award and be part of this amazing PowerShell community :)

    PowerShell oneliner contest

    The pipeline in PowerShell offers an avenue to solve many issues with oneliners.
    My fellow Windows PowerShell MVP Carlo Mancini proposed a very interesting and high quality oneliner contest. Perfect, challenge accepted :D
    After reading the rules twice, I jumped into trying to figure out what’s the best approach to get the shortest solution for each puzzle. I usually focus on the approach before trying to shorten my solution because when you started digging in a hole, it’s hard to get out of it and come with a brand new approach to solve the puzzle.

    • Task 1: get the absolute value of the highest double floating point in an array

    I noticed that the match operator with a regular expression allowed to filter out only double.

    $n = -1,-2,-5,-8.9,'b',-9.11,-6,-3,-2,-9.1,-1,-1.4,'a'
    
    # match with regular expression
    $n -match '\d\.'
    
    # vs. a more classic approach
    $n | ? { $_ -is [double] }
    

    There were only negative double numbers in the array. To get the shortest absolute value, I just multiplied by -1 instead of using the abs method of the [math] .Net class.

    # .Net abs approach
    [math]::abs(-1.4)
    
    # vs. me cheating ;)
    -1.4*-1
    

    After bringing all the pieces together, my shortest solution for task 1 is:

    # task 1
    ($n-match'\.'|sort)[-1]*-1
    

    posh-contest-task1

    • Task 2: display 12345 as a int32 without using digits

    To solve this task, my idea/approach was to use hexadecimal and do some substractions

    0xb-0xa -eq 1
    0xc-0xa -eq 2
    0xd-0xa -eq 3
    0xe-0xa -eq 4
    0xf-0xa -eq 5
    

    …except that I can’t use the leading 0.
    So, I wondered how do I get a hexadecimal without using the 0x notation.
    Well the answer is:

    # you can actually do 
    [char]'f' - [char]'a'
    

    My shortest solution for task 2 is:

    # task 2
    [int]-join('b','c','d','e','f'|%{([char]$_-[char]'a')})
    

    posh-contest-task2

    • Task 3: Display PowerShell from ‘X ‘

    When I saw this puzzle, I immediately thought, use only 1 occurrence of ‘X ‘, get rid of the whitespace behind X and use the ascii table to get P from X, o from X, w from X,…

    My shortest solution was:

    #task 3 split for readability
    -join(
    -8,23,31,13,26,-5,16,13,20,20|%{
    [char]($_+[int][char]('X '-replace' ',''))
    })
    

    posh-contest-task3

    PowerShell rocks 8-) and Bravo Carlo, I enjoyed this very nice contest :-)

    Bonus: my favourite PS golfer Bartek also proposed his solutions: https://becomelotr.wordpress.com/2015/07/04/the-only-golf-i-play/