Links for Microsoft Online services

Here are some of the great Azure AD tools needed once in a while, but you keep forgetting:

Account portals

Microsoft 365 portals

Azure portals

Health or Status portals

Other portals

If you are using these links in an organization with SSO enabled, you may need to use the links in an “InPrivate/Incognito ” session, to be able to use the correct user identity.

Source: Administrator Portals | Microsoft Portals (msportals.io)

LAPS password from computer in other domain (PS)

If you ever need to read a LAPS password on a device in another domain, you have to get a bit creative as the LAPS UI doesn’t support multi-domain in an easy fashion.

There is of course the use of “distinguishedName” attribute, but who can remember this and when you are in the Attribute Editor anyway – to copy this – you can read the LAPS password inhere.

But with PowerShell, you can do a simple query … or two …

With LAPS module

Import-Module AdmPwd.ps
Get-ADComputer -Filter 'Name -like "computername*"' -Server FQDN | Get-AdmPwdPassword
  • With the LAPS PS module you get the expirationTime formated in a readable format

No LAPS module

Get-ADComputer -Properties * -Filter 'Name -like "computername*"' -Server FQDN | Select-Object dNShostname, ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime, PwdLastSet
  • Without the LAPS PS module you need need to format the ExpirationTime timestamp yourself – or just do an educated guess

Remember, that the context of the PS session has to have read permission to the password attribute in the remote domain, otherwise you will get nothing.

Windows 10 Fonts and Fonts

With newer version of Windows 10 (1809 I think), users can now add Fonts them self. Thanks Microsoft!

This is where to look …

Per computer

  • Fonts located: C:\Windows\Fonts
  • Registry located: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts

Per user

  • Fonts located: %LocalAppData%\Microsoft\Windows\Fonts
  • Registry located: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts

Microsoft Office 365 Languages

A method to create and install the basic Office containing only the English language and the add more languages later through separate deployments.

<Configuration ID="GUID">
  <Add OfficeClientEdition="64" Channel="Broad">
    <Product ID="O365ProPlusRetail">
      <Language ID="en-us" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="OneDrive" />
    </Product>
  </Add>
  <Display Level="None" AcceptEULA="TRUE" />
  <Logging Level="Standard" Path="%TEMP%" />
</Configuration>

Below is an example of a language.xml file, here are some Scandinavian languages added.

<Configuration ID="GUID">
    <Add OfficeClientEdition="64" Channel="Broad">
        <Product ID="LanguagePack">
            <Language ID="sv-se" />
            <Language ID="da-dk" />
            <Language ID="nb-no" />
            <Language ID="fi-fi" />
            <Language ID="is-is" />
        </Product>
    </Add>
    <Display Level="None" AcceptEULA="TRUE" />
    <Logging Level="Standard" Path="%TEMP%" />
</Configuration>

It’s also possible to use the MatchOS parameter. This will install the same language for Office as running on the OS. Use the fallback or AllowCdnFallback if running in an multi-language environment to minimize the number of languages.

<Configuration ID="GUID">
    <Add OfficeClientEdition="64" Channel="Broad" AllowCdnFallback="True">
        <Product ID="LanguagePack">
            <Language ID="MatchOS" />
            <Fallback="en-us" />
        </Product>
    </Add>
    <Display Level="None" AcceptEULA="TRUE" />
    <Logging Level="Standard" Path="%TEMP%" />
</Configuration>

Dir /s (PS)

Ways to traverse directories in PowerShell, just like the old-skool “dir /s” command, with a little PowerShell spice on top.

Get-ChildItem -Recurse
Get-ChildItem -Recurse | Select-Object Name
Get-ChildItem -Filter *.png -Recurse
Get-ChildItem -Include *.txt, *.png -Recurse | Select-Object FullName

SysNative (CMD)

Today I’ve encountered something new in my work on the Windows x64 platform.

First:
On a 64 bit Windows 10 platform you have:

  • Program Files, for your x64 programs
  • Program Files (x86), for your x86 programs
  • System32, for your x64 system files
  • SysWOW64, for your x86 system files

Now:
In working with Quest Kace, I’ve discovered a new “folder”. Well it not a folder as such.

I’ve created a script where I need to reset the Windows Update Agent and force it to register with WSUS.
As soon as the script executed from Kace, if failed at the ‘wuauclt.exe’ command: ‘File not found’. I then added the full path to the file ‘C:\Windows\System32\wuauclt.exe’ – Still: ‘File not found’. I used PSexec and looked inside the ‘C:\Windows\System32’ folder, and to my surprise there were no ‘wuauclt.exe’ file, but I could see it in a regular CMD running as admin or as a regular user.

Then an old colleague told me about the ‘SysNative’ folder, as if the whole world knew what that was!

On a 64 bit platform, there is a new “folder” called ‘SysNative’, that points around the ‘File System Redirector’ and will give you access to the correct system folder, in my case ‘System32’.

So, I changed my script to use the new “folder” ‘%WinDir%\SysNative\wuauclt.exe’, and it worked like a charm.

Well, you learn something new everyday!

Set default file associations

In Windows 10, the way to set the a default program or a file association is done with a .xml file and a Group Policy setting, when the computer is joined a domain – otherwise you do it manually.

Export

On a reference computer, setup the program and file association as needed and then export the result:

DISM /Online /Export-DefaultAppAssociations:<path>\appAssoc.xml

Edit

Edit the .xml file to  contain the settings you wish to apply to your computer clients. It is not recommended that you use it “as-is”.

Below is my default appAssoc.xml file containing Outlook and Internet Explorer as default apps on a computer.

<?xml version="1.0" encoding="UTF-8"?>
<DefaultAssociations>
  <Association Identifier=".eml" ProgId="Outlook.File.eml.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".hol" ProgId="Outlook.File.hol.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".ics" ProgId="Outlook.File.ics.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".msg" ProgId="Outlook.File.msg.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".oft" ProgId="Outlook.File.oft.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".pst" ProgId="Outlook.File.pst.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".vcf" ProgId="Outlook.File.vcf.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".vcs" ProgId="Outlook.File.vcs.15" ApplicationName="Outlook 2016" />
  <Association Identifier="feed" ProgId="Outlook.URL.feed.15" ApplicationName="Outlook 2016" />
  <Association Identifier="feeds" ProgId="Outlook.URL.feed.15" ApplicationName="Outlook 2016" />
  <Association Identifier="mailto" ProgId="Outlook.URL.mailto.15" ApplicationName="Outlook 2016" />
  <Association Identifier="stssync" ProgId="Outlook.URL.stssync.15" ApplicationName="Outlook 2016" />
  <Association Identifier="webcal" ProgId="Outlook.URL.webcal.15" ApplicationName="Outlook 2016" />
  <Association Identifier="webcals" ProgId="Outlook.URL.webcal.15" ApplicationName="Outlook 2016" />
  <Association Identifier=".htm" ProgId="htmlfile" ApplicationName="Internet Explorer" />
  <Association Identifier=".html" ProgId="htmlfile" ApplicationName="Internet Explorer" />
  <Association Identifier=".mht" ProgId="IE.AssocFile.MHT" ApplicationName="Internet Explorer" />
  <Association Identifier=".mhtml" ProgId="IE.AssocFile.MHT" ApplicationName="Internet Explorer" />
  <Association Identifier=".partial" ProgId="IE.AssocFile.PARTIAL" ApplicationName="Internet Explorer" />
  <Association Identifier=".svg" ProgId="IE.AssocFile.SVG" ApplicationName="Internet Explorer" />
  <Association Identifier=".url" ProgId="IE.AssocFile.URL" ApplicationName="Internet Browser" />
  <Association Identifier=".website" ProgId="IE.AssocFile.WEBSITE" ApplicationName="Internet Explorer" />
  <Association Identifier=".xht" ProgId="IE.AssocFile.XHT" ApplicationName="Internet Explorer" />
  <Association Identifier=".xhtml" ProgId="IE.AssocFile.XHT" ApplicationName="Internet Explorer" />
  <Association Identifier="ftp" ProgId="IE.FTP" ApplicationName="Internet Explorer" />
  <Association Identifier="http" ProgId="IE.HTTP" ApplicationName="Internet Explorer" />
  <Association Identifier="https" ProgId="IE.HTTPS" ApplicationName="Internet Explorer" />
  <Association Identifier="mk" ProgId="IE.HTTP" ApplicationName="Internet Explorer" />
  <Association Identifier="res" ProgId="IE.HTTP" ApplicationName="Internet Explorer" />
</DefaultAssociations>

If you wish  to add an Adobe product as default PDF reader, Adobe has created a ‘how to’ guide … Read it here

Copy

Now copy the .xml file to a network location where all your computers can get a hold on the file, eg. %NETLOGON%\ClientApps\appAssoc.xml

Group Policy

In an relevant Group Policy, go to [Computer Configuration], [Administrative Templates], [Windows Components], [File Explore] and select the [Set a default associations configuration file] setting. Enable it and hereafter enter the path and file name, of the location of the .xml file.

At next reboot the new program and file association should be effective.

Query Computer for Pending Reboot State (PS)

Ever needed to know if a reboot is pending on your computer? Try this Microsoft/Scripting Guy PowerShell script, and you’ll know!

Copy the code below and save as .ps1 file, and execute at your convenience.

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

Source: Microsoft Script Center

WUAUCLT is dead (CMD)

Windows 10 has toombed yet another function within Windows, and now the ‘wuauclt’ command line tools is dead. To replace the old tool, Microsoft has created a brand new Windows Update tool called: ‘usoClient’.

The ‘usoClient’ is a part of the new Windows 10 Update Orchestrator family and is located in the System32 folder, and like ‘wuauclt’ the ‘usoClient’ can do a lot of cool Windows Update stuff.

Switch Description
StartScan Use this to Start Scan
StartDownload Use this to Start Download of Updates
StartInstall Use this to Install Downloaded Updates
RefreshSettings Use this to Refresh Settings if any changes were made
RestartDevice Use this to Restart the device to finish the installation of Updates
ScanInstallWait Use this to Combine Scan-Download-Install
ResumeUpdate Use this to Resume Update Installation On Boot

The ‘day-to-day’ Update Orchestrator actions are controlled from Task Scheduler -> Microsoft -> Windows -> UpdateOrchestrator

Happy updating.

Source: omgdebugging.com

Microsoft Office 365 Click-to-run – language.xml

Custom xml file for a Microsoft Office 365 Click-to-run additional language installation. This will add selected languages to an already existing Office 365 installation.

<Configuration>
    <Add OfficeClientEdition="32" Channel="Monthly">
        <Product ID="LanguagePack">
            <Language ID="sv-se" />
            <Language ID="fr-fr" />
            <Language ID="de-de" />
            <Language ID="pt-br" />
            <Language ID="da-dk" />
            <Language ID="nb-no" />
        </Product>
    </Add>
    <Display Level="None" AcceptEULA="TRUE" />
    <Logging Level="Standard" Path="%TEMP%" />
</Configuration>

Note: The first language in the list will be the language that the existing Office Start Menu items will be transformed into. In this example, the Start Menu shortcuts for Skype for Business, OneDrive for Business and the Tools folder will be translated into Swedish.

Microsoft Office 365 Click-to-run – add.xml

Custom download and install xml file for a Microsoft Office 365 Click-to-run installation. This is configured to use the new Microsoft Office update channel and is SCCM integrated and without OneDrive.

<Configuration>
    <Add OfficeClientEdition="32" Channel="Monthly" OfficeMgmtCOM="TRUE">
        <Product ID="O365ProPlusRetail">
            <Language ID="en-us" />
            <Language ID="de-de" />
            <ExcludeApp ID="OneDrive" />
        </Product>
    </Add>
    <Updates Channel="Monthly" Enabled="TRUE" />
    <Display Level="None" AcceptEULA="TRUE" />
    <Logging Level="Standard" Path="%TEMP%" />
    <Property Name="FORCEAPPSHUTDOWN" Value="FALSE" />
    <Property Name="SharedComputerLicensing" Value="0" />
    <Property Name="PinIconsToTaskbar" Value="FALSE" />
</Configuration>

Note: And as usual, the ability to pin the Office icons to the taskbar, is only available for the users that is running the installation.