MyITGuy
9/13/2019 - 1:36 PM

ConvertFrom-OfficeProductCode

Decodes Microsoft Office ProductCode

#region ConvertFrom-OfficeProductCode
function ConvertFrom-OfficeProductCode {
    [CmdletBinding()]
    PARAM(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]
        $ProductCode
    )

    begin {
        Write-Verbose $MyInvocation.MyCommand
        function Get-LCIDToLocaleName {
            $signature = @"
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int LCIDToLocaleName(uint localeID, System.Text.StringBuilder localeName, int localeNameSize, int flags);
"@
            Add-Type -MemberDefinition $signature -Name "Win32LCIDToLocaleNameDllName" -Namespace Win32Functions -PassThru
        }
    }

    process {
        try {
    
            $Properties = [ordered]@{
                ProductCode    = $ProductCode
                ReleaseBuildID = $null
                ReleaseTypeID  = $null
                MajorVersion   = $null
                MinorVersion   = $null
                ProductID      = $null
                LanguageID     = $null
                BitnessID      = $null
                Reserved       = $null
                DebugID        = $null
                OfficeFamilyID = $null

                SKU            = $null
                Version        = $null
                Bitness        = $null
                Release        = $null
                ReleaseType    = $null
                Language       = $null
                Debug          = $null
            }
            $ProductCodeArray = ([System.Guid]$Properties.ProductCode).ToString('D') -split '-'

            $Properties.ReleaseBuildID = (($ProductCodeArray)[0]).ToUpper().Substring(0, 1)
            $Properties.ReleaseTypeID = (($ProductCodeArray)[0]).ToUpper().Substring(1, 1)
            $Properties.MajorVersion = (($ProductCodeArray)[0]).ToUpper().Substring(2, 2)
            $Properties.MinorVersion = (($ProductCodeArray)[0]).ToUpper().Substring(4, 4)
            $Properties.ProductID = (($ProductCodeArray)[1]).ToUpper()
            $Properties.LanguageID = (($ProductCodeArray)[2]).ToUpper()
            $Properties.BitnessID = (($ProductCodeArray)[3]).ToUpper().Substring(0, 1)
            $Properties.Reserved = (($ProductCodeArray)[3]).ToUpper().Substring(1, 3)
            $Properties.DebugID = (($ProductCodeArray)[4]).ToUpper().Substring(0, 1)
            $Properties.OfficeFamilyID = (($ProductCodeArray)[4]).ToUpper().Substring(1, 11)

            # Description of the numbering scheme for product code GUIDs in Office 2016
            # https://support.microsoft.com/en-us/help/3120274/description-of-the-numbering-scheme-for-product-code-guids-in-office-2
            
            # Description of the numbering scheme for product code GUIDs in Office 2013
            # https://support.microsoft.com/en-us/help/2786054/description-of-the-numbering-scheme-for-product-code-guids-in-office-2
            $Properties.Release = switch ($Properties.ReleaseBuildID) {
                ('0') { "Alpha" }
                ('1') { "Beta 1" }
                ('2') { "Beta 2" }
                ('3') { "Release Candidate 0 (RC0)" }
                ('4') { "Release Candidate 1 (RC1)" }
                ('9') { "Release To Manufacturer (RTM)" }
                ('A') { "Service Pack 1 (SP1)" }
                ('B') { "Service Pack 2 (SP2)" }
                ('C') { "Service Pack 3 (SP3)" }
                default { "Reserved" }
            }

            $Properties.ReleaseType = switch ($Properties.ReleaseTypeID) {
                ('0') { "Volume License" }
                ('1') { "Retail/OEM" }
                ('2') { "Trial" }
                ('5') { "Download" }
            }

            $Properties.SKU = switch ($Properties.ProductID) {
                ('000F') { "Microsoft Office Mondo" }
                ('0011') { "Microsoft Office Professional Plus" }
                ('0012') { "Microsoft Office Standard" }
                ('0015') { "Microsoft Access" }
                ('0016') { "Microsoft Excel" }
                ('0018') { "Microsoft PowerPoint" }
                ('0019') { "Microsoft Publisher" }
				('001A') { "Microsoft Outlook" }
                ('001B') { "Microsoft Word" }
                ('001C') { "Microsoft Access Runtime" }
                ('001F') { "Microsoft Office Proofing Tools" }
                ('002A') { "Microsoft Office Components" }
                ('002C') { "Microsoft Office Proofing Tools" }
                ('003A') { "Microsoft Project Standard" }
                ('003B') { "Microsoft Project Professional" }
                ('0051') { "Microsoft Visio Professional" }
				('0053') { "Microsoft Visio Standard" }
                ('006E') { "Microsoft Office Shared MUI" }
                ('008C') { "Click-to-Run Localization Component" }
                ('008F') { "Click-to-Run Licensing Component" }
                ('00A1') { "Microsoft OneNote" }
				('00BA') { "Microsoft Office OneDrive for Business" }
                ('00B4') { "Microsoft Project MUI" }
				('110D') { "Microsoft Office SharePoint Server" }
                ('0115') { "Microsoft Office Shared Setup Metadata MUI" }
                ('0116') { "Microsoft Office Shared Setup Metadata MUI" }
                ('012B') { "Microsoft Skype for Business" }
            }
            
            # https://en.wikipedia.org/wiki/History_of_Microsoft_Office
            $Properties.Version = switch ($Properties.MajorVersion) {
                (7) { "95" }
                (8) { "97" }
                (9) { "2000" }
                (10) { "XP" }
                (11) { "2003" }
                (12) { "2007" }
                (14) { "2010" }
                (15) { "2013" }
                (16) { "2016" }
                (19) { "2019" }
            }

            # Language Identifier Constants and Strings
            # https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings

            # https://www.autoitscript.com/autoit3/docs/appendix/OSLangCodes.htm
            $LanguageIDDec = ([uint64]([String]::Format('{0:0x0000}', [uint64]$Properties.LanguageID)))
            $sb = (New-Object System.Text.StringBuilder([int]85)) # 85 = Native.LOCALE_NAME_MAX_LENGTH
            (Get-LCIDToLocaleName)::LCIDToLocaleName($LanguageIDDec, $sb, $sb.Capacity, 0) | Out-Null
            $Properties.Language = $sb.ToString()

            $Properties.Bitness = switch ($Properties.BitnessID) {
                (0) { "x86" }
                (1) { "x64" }
            }

            $Properties.Debug = switch ($Properties.DebugID) {
                (0) { "Ship" }
                (1) { "Debug" }
            }

            $obj = New-Object -TypeName PSObject -Property $Properties
            Write-Output -InputObject $obj
        }
        catch {
            Throw $_
        }
    }

    end {
    }
}
#endregion ConvertFrom-OfficeProductCode