Using the PowerShell MVP module

The renewal season is opened and it’s time to use the PowerShell module designed to interact with the Microsoft MVP website François-Xavier Cat and I released last year when the Microsoft MVP Rest API was made available.

François-Xavier already published some very useful posts and demoed how to use the MVP module for:

This year, I only used the module to insert and review my contributions.
To start using the module, you basically need to install the module, import it and set your subscription key with the Set-MVPConfiguration function. See first the following post from François-Xavier to achieve these steps.

Now I’d like to show you some code snippets I used along this contributions submission process.

First, I needed to find what contribution I submitted last year and filter out what PGI I attended.
To quickly do that I used:

Get-MVPContribution -Limit 100 | 
Where { $_.ContributionType.Name -notmatch 'PGI' } | 
Out-GridView -PassThru 

I first get the out-gridview window where I can list, search and select contribution(s):

If I select a previous one:

After I reviewed my old contribution, I gather updated numbers for the new period and prepare the following to submit an activity:

$splat = @{
 startdate ='2017/07/01'
 Title='Type your title here'
 Description = @'
Enter a full description about this activity
'@
 ReferenceUrl='https://reference.uri'
 AnnualQuantity='1'
 SecondAnnualQuantity='0'
 AnnualReach = '1000'
 Visibility = (
  Get-MVPContributionVisibility | 
  Out-GridView -Title 'Select visibility' -PassThru
 ).Description
 ContributionType = (
  Get-MVPContributionType | 
  Out-GridView -Title 'Select Contribution Type' -PassThru
 ).Name
 ContributionTechnology = (
  Get-MVPContributionArea -All | 
  Out-GridView -Title 'Select Contribution Area' -PassThru
 ).Name
}

# Review one more time
$splat

# Submit activity
New-MVPContribution @splat

Note that a new contribution ID is returned when it’s submitted using the New-MVPContribution function.
I take a note of its ID and use the following to be able to query this activity later on when/if needed.

Get-MVPContribution -ID 547174

After I entered all the activities, I use this code snippet to see what I submitted:

Get-MVPContribution -Limit 100 | 
Where { $_.ContributionType.Name -notin @(
 'Product Group Interaction (PGI)',
 'Forum Participation (Microsoft Forums)') } | 
ForEach-Object {
 $_ | 
 Add-Member -MemberType NoteProperty -Name Date -Value (Get-Date $_.StartDate) -PassThru
} | Where { 
 $_.Date -ge (Get-Date '2017-07-01T00:00:00') 
} | 
Sort -Property Date | 
Out-GridView
Advertisements

Tracking Office 365 versions

I’ve just started to work on Office 365 and I wondered how I could track the different versions, their release notes, what changed, when…
I’ve deployed a Semi-Annal Targeted version and got the following version.
I wondered where this info under Product Info come from when you click on File/Office Account:

I started to dig into the registry and the following key contains many info about the Office 365 branch that was installed.

Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration" | 
Select AudienceId,UpdateChannel,*Version*,CDNBaseUrl | fl

Then I found these two links:

These are very nice and let you know what changed but I wanted to avoid parsing a web page to be able to track Office 365 versions, branches… and I’d like to get the same nice chart:

Then I found the github page about deploying Office 365 although I knew about the XML editor.
It appears that it contained all what I needed 😀

So, I wrote a function to help you and me achieve the following:

# See examples provided in the help of the function
Get-Help Get-O365UpdateChannelReleaseHistory -Examples

# Example 1: Displays all branches and releases
Get-O365UpdateChannelReleaseHistory  -Verbose |
ft -AutoSize


Note that there’s a 0 behind the version because it’s a real [version] object and not a [string]. Having real version objects will allow you to do a successful comparison between versions. Idem for release dates.
Notice also that there’s already a Long-Term Servicing Channel (2019) branch in the xml data. Who knew that?

# Example 2: Displays all branches and 
# only displays the latest version of every branch
Get-O365UpdateChannelReleaseHistory -Verbose| 
Where { $_.Latest} | ft -AutoSize

The next examples will display the same branch by calling the function by name, by id, by displayname and by global unique identifier (guid):
Note that every parameter (name, id, displayname and guid) have completion because valid sets have been declared in the parameters block. Just press TAB after a parameter:

# Example 3: Using the name
Get-O365UpdateChannelReleaseHistory -Name FirstReleaseDeferred -Verbose|
ft -AutoSize
# Example 4: using the Id
Get-O365UpdateChannelReleaseHistory -Id Targeted -Verbose|
ft -AutoSize
# Example 5: Using the displayname
Get-O365UpdateChannelReleaseHistory -DisplayName 'Semi-Annual Channel (Targeted)' -Verbose | ft -AutoSize
# Example 6: using a GUID
Get-O365UpdateChannelReleaseHistory -Guid b8f9b850-328d-4355-9145-c59439a0c4cf -Verbose | ft -AutoSize

If the function was able to download at least once a file but then fails, it will use the previous file that was previously downloaded. The verbose stream displays the published date found in the downloaded xml file:

Enjoy 😎

About PowerShell Core 6.0 logging

I’ve seen in this interview that group policy templates (ADMX files) should be shipped soon and allow corporate admins to control PowerShell Core ScriptBlockLogging, Transcripts,.. all the security stuff the blue team .

Procmon reveals what registry path pwsh.exe is looking for:

It appears that the policy path for PowerShell Core 6.0 is different from Windows PowerShell 5.x:
Microsoft\Windows\PowerShell is replaced by Microsoft\PowerShellCore.

Using some google fu, I came across this pull request where there’s an interesting discussion, a sample powershell.config.json file. We also learn that:

On Windows, we first query GPO from registry, if the required policy is not defined, then we query policies from the configuration file.

Another very useful link is the help file about_Logging.md where you can read that:

Windows requires the event provider to be registered before logged events can appear in the event log. For PowerShell, this is accomplished by running the RegisterManifest.ps1 from an elevated PowerShell prompt.

When you’ve ScriptBlockLogging enabled by GPO and registered the ETW provider, you get the related events in this location

Get-WinEvent -ListProvider "PowerShellCore"
Get-WinEvent -LogName 'PowerShellCore/Operational' -MaxEvents 1

Last thing, let’s look how different is the transcript header:

PowerShell Core has its own learning curve 🙂

AutoRuns module compatible with PowerShell Core 6.0

I’ve glad to announce that my AutoRuns module is compatible with PowerShell Core 6.0 🙂

  • What changed? What was fixed?
    • The Get-FileHash function taken on PowerShell 4.0 wasn’t compatible with PowerShell Core. I’ve included a test on $PSVersionTable to fix this shortcoming.
    • The Get-WmiObject cmdlet was removed and replaced with Get-CimInstance by this commit (I’ve added a function to retrieve WMI namespaces recursively. I’ve also added a function to look for WMI providers)
    • There were some issues with the ImagePath property calculated from the raw value. Issues 5, 6, 7, 8, 9 were fixed.
    • I’ve added a template to report issue that I copied from this location. You can now submit an issue more easily.
  • What’s next?
  • What else?
  • Enjoy! PowerShell rocks! 😎

PowerShell Core 6.0: Generally Available (GA) and Supported

It’s like a Christmas present! Wow! PowerShell Core 6.0: Generally Available (GA) and Supported!

Congratulations to the PowerShell team and the PowerShell community who work hard to hit this milestone!

Yes, PowerShell Core 6.0 is *cross-platform* and it also means that
.
Microsoft ❤ Linux, we know that.
I hope that we see in the near future that Linux ❤ Microsoft and its community embraces this new #pwsh shell after realizing it’s not just another shell.

The above blog post announcing the release is a very good starting point and answers many questions.

I started to get binaries from https://github.com/PowerShell/PowerShell/releases/tag/v6.0.0. There are SHA256 hashes at the end of the page as well as release notes.
This link https://aka.ms/getps6-windows shows how to install it on Windows. This one is for Linux.

The main documentation is available at https://aka.ms/pscore6-docs

If you just do the following…

… you may notice that’s a big difference with “Windows PowerShell”.

Reading these pages is highly recommended:

I’ve followed the guidance about contributing and I’ve already opened an issue about digital signature of the content of zip and msi packages.

Find file names and URL of Windows 10 feature updates on WSUS

This question about how to find file names for Windows 10 feature updates on WSUS was raised this morning or last night on the PM.org list because Windows 10 1709 (CB = Current branch) was declared “CBB”, current branch for business (sorry, this is the old wording). In other words, the 1709 branch went from Semi-Annual Channel (Targeted) deployment state to a broader one called just “Semi-Annual Channel” (SAC)….

If I’m not clear, here’s the official release cadence, names and explanation:

… this question was raised because a 4th ISO is also expected…

and another list member asked how to get this info.

Abbodii replied the following:

If you are interested in these XML files as well, here are the links:

In a business environment, you’re more likely to find a WSUS server and it appears that you can also get the file names (ESD images) and their source location using PowerShell like this:

(Get-WsusServer).SearchUpdates(
'Feature update to Windows 10, version 1709, en-us'
) | 
ForEach-Object { 
 Write-Verbose "Looking at update id $($_.Id.UpdateId) revision: $($_.Id.RevisionNumber)" -Verbose
 $_.GetInstallableItems() | 
 ForEach-Object {
  $_.Files | 
  ForEach-Object {
   [PsCustomObject]@{
    URI = $_.OriginUri.OriginalString
    FileName = $_.OriginUri.Segments[-1]
   }
  }
 }
} | Select FileName

This also means that you can approve only one feature updates if you only have for example x64 based Windows 10 clients to target.
With the above code, you know the update id and you can now do:

$WXtargetgroup = (Get-WsusServer).GetComputerTargetGroups() |
Where Name -eq 'Windows 10 x64'

(Get-WsusServer).SearchUpdates(
'Feature update to Windows 10, version 1709, en-us'
) | Where-Object { 
 $_.Id.UpdateId -eq '7c803efa-be06-4481-9f8c-889afb34faf8' 
} | 
ForEach-Object -Process {
 Write-Verbose -Message "Approving $($_.Title)" -Verbose        
 $_.Approve(
  [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install,
  $WXtargetgroup
 )
}

About CPU bug aka #Meltdown / #Spectre

  • What are the vulnerabilities?
    • CVE-2017-5715 – (Spectre), branch target injection
    • CVE-2017-5753 – (Spectre), bounds check bypass
    • CVE-2017-5754 – (Meltdown), rogue data cache load, memory access permission check performed after kernel memory read
  • Where to start? What about reading the following posts?

This isn’t an exhaustive list of posts, it’s just a starting point. These vulnerabilities have the widest scope I’ve ever seen and show how fragile IT devices and software are is. I should probably start distributing stickers sayin ‘Human error inside’ 😉

  • What should I do? What’s the plan?

While it isn’t just a Microsoft issue, a PM.org list member (Mike) provided the following plan for Windows based computers:

Please note that you’ll need a microcode update or firmware update from your device manufacturer to be able to fully mitigate these vulnerabilities whatever OS and software you run.

If you run an Antivirus (AV) software (you should), please make sure it’s compatible with the security fixes released by software or OS vendors.

  • Where do I find the SpeculationControl PowerShell module provided by the MSRC?

The PowerShell gallery hosts the module: https://www.powershellgallery.com/packages/SpeculationControl

The MSRC also released a zip version of it that you’ll find on https://aka.ms/SpeculationControlPS

  • How do I use this module?

It may not be that easy and straightforward as you may think, when you’re supposed to start by installing the module with the following command

# Open a PowerShell prompt and type:
Install-Module SpeculationControl

Why? Because it depends on the version of PowerShell you run, if you run the console with elevated admin privileges, whether the Nuget provider has already been bootstraped or not… (see more on my Inside the Nuget bootstraping process post)

Here’s what I did on my Windows 10 (1709) where the Nuget provider wasn’t present:


# 1. Download the nuget provider dll
Invoke-WebRequest -Uri `
https://oneget.org/Microsoft.PackageManagement.NuGetProvider-2.8.5.207.dll `
-OutFile `
~/downloads/Microsoft.PackageManagement.NuGetProvider.dll

# 2. Check the integrity of the downloaded file 
(Get-FileHash ~/downloads/Microsoft.PackageManagement.NuGetProvider.dll -Algorithm SHA512 | Select -Expand Hash).ToLower() -eq 
'c68f9be28eb338abc0200e93a089188a734c6b13c59f3c0eb9bb79898e9bee8a5b50bf4b6e4eeaeee687d8cad927d5cfa8ec25e591de0d8ac745b19ae66ab006'

# 3. Create a destination folder
mkdir "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.207"

# 4. Copy the dll file to this folder
copy ~/downloads/Microsoft.PackageManagement.NuGetProvider.dll  `
-Destination "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.207"

# 5. Load the dll
Import-PackageProvider -Name Nuget -Verbose

# 6. Save the module from the powershellgallery.com
Save-Module -Name SpeculationControl -Repository  PsGallery -Verbose -Path ~/Downloads

# 7. Change the execution policy for the current console
Set-ExecutionPolicy  -Scope Process -ExecutionPolicy Bypass

# 8. Import the module (version 1.0.1 in my case)
Import-Module ~\Downloads\SpeculationControl\1.0.1\SpeculationControl.psd1 -Verbose

# 9. Use it 
Get-SpeculationControlSettings

  • How do I use the module against remote computers?

A fellow MVP Mike F. Robbins shows a nice way to achieve this on his blog:
Using PowerShell to Check Remote Windows Systems for CVE-2017-5754 (Meltdown) and CVE-2017-5715 (Spectre)

  • How do I follow the changes in the SpeculationControl module?

Well you can’t. The MSRC hasn’t indicated a ProjectURI in the metadata of the module 😦

I’ve saved all the versions from the PowerShell Gallery and pushed them into a github repo.

As of version 1.0.2, the module hosted on the PSGallery is digitally signed.

You can now check what changed using diff on the different commits: https://github.com/p0w3rsh3ll/MSRC-SpeculationControl/commits/master 🙂