ActivateAll.psm1

function Get-Answer
{
    [CmdletBinding()]
    [OutputType([boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]$question,
        [boolean]$answer
    )
    
    $YN = Read-Host -Prompt "$question`n(Y)es, ENTER - No"
    if ($YN -eq "Y")
    {
        [boolean]$answer = $true
    }
    else
    {
        [boolean]$answer = $false
    }
    [boolean]$answer
}

function Test-Admin
{
    [CmdletBinding()]
    [OutputType([boolean])]
    param ()
    
    return [boolean]([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

<#
        .SYNOPSIS
            Install Office (R) Tool module
         
        .DESCRIPTION
            Installs Office (R) Tool module and prompt to install Office (R) Tool
         
        .PARAMETER Force
            CAUTIOUS! This will skip if antivirus realtime protection is enabled !
         
        .EXAMPLE
            PS C:\> Install-OfficeRTool
            PS C:\> Install-OfficeRTool - Force # Install OfficeRTool module without antivirus check
         
        .NOTES
            By CHXOFT ©2025.
    #>

function Install-OfficeRTool
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [switch]$Force
    )
    
    if (!(Test-Admin -ErrorAction SilentlyContinue))
    { return Write-Error -Message "Need to open Powershell with Admin privileges." -Category PermissionDenied }
    
    if (!(Get-Module -Name "AntivirusProductsDetailedStatus" -ListAvailable -ErrorAction SilentlyContinue))
    { Install-Module -Name "AntivirusProductsDetailedStatus" -Force }
    
    $RTL = Get-Module -Name OfficeRTool -ListAvailable -ErrorAction SilentlyContinue
    if (!$RTL)
    {
        if (Get-Answer -question "Install Office ® Tool ?")
        {
            Install-Module -Name OfficeRTool -Force
            if (Get-RealTimeProtection)
            {
                Write-Output "`nAntivirus Realtime proteciton emabled.`nDisable antivirus first to install Office (R) Tool."
                return Start-Process -FilePath "windowsdefender://Threatsettings"
            }
            else { return Install-RTool }
        }
        else { return Write-Output -InputObject "`nSkipping Office ® Tool installation." }
    }
    elseif ($RTL.Version.Build -lt 2)
    {
        if (Get-RealTimeProtection)
        {
            Write-Output "`nAntivirus Realtime proteciton emabled.`nDisable antivirus first to update Office (R) Tool."
            Start-Process -FilePath "windowsdefender://Threatsettings"
        }
        else
        {
            Write-Output -InputObject "`nUpdating Office ® Tool module."
            Update-Module -Name "OfficeRTool" -Force
            Write-Output -InputObject "`nInstalling Office ® Tool."
            Install-RTool -IgnoreAntivirus
        }
    }
    
    if ($Force)
    { return Install-RTool -IgnoreAntivirus }
    elseif (Get-Answer -question "Activate Office ?")
    {
        Write-Output -InputObject "`nActivating Office permanently."
        & ([ScriptBlock]::Create((Invoke-RestMethod -Uri $uri))) /Ohook
    }
}

<#
        .SYNOPSIS
            Install dot NET 3.5 feature
         
        .DESCRIPTION
            A detailed description of the Install-dotNET3.5 function.
         
        .PARAMETER Force
            Skip check if dotNET 3.5 is already installed.
         
        .EXAMPLE
            PS C:\> Install-dotNET3.5
         
        .NOTES
            By CHXOFT ©2025.
    #>

function Install-dotNET3.5
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [switch]$Force
    )
    
    if (!(Test-Admin -ErrorAction SilentlyContinue))
    {
        return Write-Error -Message "Need to open Powershell with Admin privileges." -Category PermissionDenied
    }
    
    if ($pscmdlet.ShouldProcess("Target", "Operation"))
    {
        $dotNetName = "Windows feature .NET 3.5"
        $dotNet = (Get-WindowsOptionalFeature -FeatureName "NetFx3" -Online -ErrorAction SilentlyContinue).State
        
        if ($Force)
        {
            Write-Output "Installing optional $dotNetName package."
            Enable-WindowsOptionalFeature -Online -FeatureName "NetFx3" -All
        }
        elseif (![boolean]$dotNet)
        {
            Write-Output "Installing optional $dotNetName package."
            Enable-WindowsOptionalFeature -Online -FeatureName "NetFx3" -All
        }
        else
        { Write-Output "Optional $dotNetName already enabled." }
        
        if (![boolean]$dotNet)
        {
            Write-Error -Category NotEnabled -Message "$dotNetName failed to install, trying other installation method." -ErrorAction Continue
            $choco = Get-Command -Name "choco.exe" -ErrorAction SilentlyContinue
            
            if (![boolean]$choco)
            {
                [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
                return & ([ScriptBlock]::Create((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')))
            }
            else
            { Start-Process -FilePath "choco.exe" -ArgumentList "install dotnet3.5 -f -y" -NoNewWindow }
            
            if (![boolean]$choco)
            { Start-Process -FilePath "DISM" -ArgumentList "/Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:D:\sources\sxs" -NoNewWindow }
        }
    }
}

<#
    .SYNOPSIS
        Start online MAS script
     
    .DESCRIPTION
        Opens online Microsoft Activation Scripts.
     
    .PARAMETER Win
        Activate Windows with HWID permanently.
     
    .PARAMETER Office
        Activate Office.
     
    .PARAMETER alt
        Alternative url for online script.
     
    .PARAMETER all
        Activate Windows and Office.
     
    .PARAMETER Force
        Start MAS even the one or more is already running.
     
    .PARAMETER WinHWID
        Start Windows HWID activation.
     
    .PARAMETER OfficeOhook
        Start Office Ohook activation script.
     
    .EXAMPLE
        PS C:\> Start-MAS
        PS C:\> Start-MAS -all
     
    .NOTES
        By CHXOFT ©2025.
#>

function Start-MAS
{
    [CmdletBinding(ConfirmImpact = 'Medium',
                   SupportsShouldProcess = $true)]
    [OutputType([CmdletBinding])]
    param
    (
        [switch]$Win,
        [switch]$Office,
        [switch]$alt,
        [switch]$all,
        [switch]$Force
    )
    
    [string]$Arguments = $null
    [string]$ArgHWID = "/HWID"
    [string]$ArgOFFICE = "/Ohook"
    [string]$Job = 'MAS'
    [string]$name = 'Microsoft Activation Scripts'
    [uri]$uri = 'https://get.activated.win'
    [uri]$uriAlt = 'https://massgrave.dev/get'
    [scriptblock]$ScriptBlock = ([ScriptBlock]::Create((Invoke-RestMethod -Uri $uri)))
    $MASjob = Get-Job -Name $Job -ErrorAction SilentlyContinue
    
    if ($Force)
    { Remove-Job -Name $Job -Force -ErrorAction SilentlyContinue }
    
    if (!$MASjob -or !$MASjob.State.Contains("Running"))
    {
        Remove-Job -Name $Job -Force -ErrorAction SilentlyContinue
        if ($Win -and $Office -or $all)
        { $Arguments = "$ArgHWID $ArgOFFICE" }
        elseif ($Win)
        { $Arguments = "$ArgHWID" }
        elseif ($Office)
        { $Arguments = "$ArgOFFICE" }
        if ($alt)
        { $uri = $uriAlt }
        if ($pscmdlet.ShouldProcess("target", "action"))
        {
            [string]$info = "Starting online $name from $uri"
            if ($Arguments)
            { $info += "with switch $Arguments" }
            Write-Output -InputObject $info -NoEnumerate
            Start-Job -Name $Job -ScriptBlock $ScriptBlock -ArgumentList $Arguments -RunAs32 | Out-Null
        }
    }
    else
    { Write-Warning -Message "$name is already running !" }
}

<#
    .SYNOPSIS
        Set Date, time format, timezone, home location
     
    .DESCRIPTION
        Set Date, time format, timezone, home location by GeoID, if specific User is not defined it will set for all users, default set is: dd/MM/yyyy, H:MM, H:mm:ss, dddd,MMMM d,yyyy, AutoTimezone = ON, Time zone = Central Europe Standard Time, Home location GeoId = 271 (Serbia)
     
    .PARAMETER DateFormat
        Set date format.
     
    .PARAMETER TimeFormat
        Set time format.
     
    .PARAMETER LongTimeFormat
        Set long time format.
     
    .PARAMETER LongDateFormat
        Set long date format.
     
    .PARAMETER TimeZoneAuto
        Set time zone automatically ON ($true) or OFF ($false).
     
    .PARAMETER TimeZone
        Set time zone.
     
    .PARAMETER HomeLocation
        Set GeoId home loaction parameter. Find GeoId for your country.
     
    .PARAMETER SpecUser
        Specify user to format date and time only, rest settings will apply to all unles -DateTimeOnly witch is used.
     
    .PARAMETER DateTimeOnly
        Format date and time only.
     
    .PARAMETER User
        Select specific User on PC to set format. If not all Users will be set.
     
    .EXAMPLE
        PS C:\> Format-DateTimeRegion
        PS C:\> Format-DateTimeRegion -DateFormat dd.MM.yyyy -TimeFormat HH:mm -LongTimeFormat hh:mm:ss:tt -TimeZoneAuto $false -User "John"
        PS C:\> Format-DateTimeRegion -DateTimeOnly -SpecUser "username" -TimeFormat H:mm
     
    .NOTES
        Format Date, time, set home location, set time zone.
#>

function Format-DateTimeRegion
{
    [CmdletBinding()]
    param
    (
        [switch]$DateTimeOnly,
        [string]$SpecUser,
        [ValidateSet('dd/MM/yyyy', 'M/d/yyyy', 'M/d/yy', 'MM/dd/yy', 'MM/dd/yyyy', 'yy.MM.dd', 'yyyy-MM-dd', 'dd-MMM-yy', 'dd.MM.yyyy', 'M.d.yyyy', 'M.d.yy', 'MM.dd.yy', 'MM.dd.yyyy')]
        [string]$DateFormat = 'dd/MM/yyyy',
        [ValidateSet('H:mm', 'h:mm:tt', 'hh:mm:tt', 'HH:mm')]
        [string]$TimeFormat = 'H:mm',
        [ValidateSet('H:mm:ss', 'h:mm:ss:tt', 'hh:mm:ss:tt', 'HH:mm:ss')]
        [string]$LongTimeFormat = 'H:mm:ss',
        [ValidateSet('dddd, MMMM d, yyyy', 'MMMM d, yyyy', 'dddd, d MMMM, yyyy', 'd MMMM, yyyy')]
        [string]$LongDateFormat = 'dddd, MMMM d, yyyy',
        [boolean]$TimeZoneAuto = $true,
        [ValidateSet('Dateline Standard Time', 'UTC-11', 'Aleutian Standard Time', 'Hawaiian Standard Time', 'Marquesas Standard Time', 'Alaskan Standard Time', 'UTC-09', 'Pacific Standard Time (Mexico)', 'UTC-08', 'Pacific Standard Time', 'US Mountain Standard Time', 'Mountain Standard Time (Mexico)', 'Mountain Standard Time', 'Yukon Standard Time', 'Central America Standard Time', 'Central Standard Time', 'Easter Island Standard Time', 'Central Standard Time (Mexico)', 'Canada Central Standard Time', 'SA Pacific Standard Time', 'Eastern Standard Time (Mexico)', 'Eastern Standard Time', 'Haiti Standard Time', 'Cuba Standard Time', 'US Eastern Standard Time', 'Turks And Caicos Standard Time', 'Atlantic Standard Time', 'Venezuela Standard Time', 'Central Brazilian Standard Time', 'SA Western Standard Time', 'Pacific SA Standard Time', 'Newfoundland Standard Time', 'Tocantins Standard Time', 'Paraguay Standard Time', 'E. South America Standard Time', 'SA Eastern Standard Time', 'Argentina Standard Time', 'Montevideo Standard Time', 'Magallanes Standard Time', 'Saint Pierre Standard Time', 'Bahia Standard Time', 'UTC-02', 'Greenland Standard Time', 'Mid-Atlantic Standard Time', 'Azores Standard Time', 'Cape Verde Standard Time', 'UTC', 'GMT Standard Time', 'Greenwich Standard Time', 'Sao Tome Standard Time', 'Morocco Standard Time', 'W. Europe Standard Time', 'Central Europe Standard Time', 'Romance Standard Time', 'Central European Standard Time', 'W. Central Africa Standard Time', 'GTB Standard Time', 'Middle East Standard Time', 'Egypt Standard Time', 'E. Europe Standard Time', 'West Bank Standard Time', 'South Africa Standard Time', 'FLE Standard Time', 'Israel Standard Time', 'South Sudan Standard Time', 'Kaliningrad Standard Time', 'Sudan Standard Time', 'Libya Standard Time', 'Namibia Standard Time', 'Jordan Standard Time', 'Arabic Standard Time', 'Syria Standard Time', 'Turkey Standard Time', 'Arab Standard Time', 'Belarus Standard Time', 'Russian Standard Time', 'E. Africa Standard Time', 'Volgograd Standard Time', 'Iran Standard Time', 'Arabian Standard Time', 'Astrakhan Standard Time', 'Azerbaijan Standard Time', 'Russia Time Zone 3', 'Mauritius Standard Time', 'Saratov Standard Time', 'Georgian Standard Time', 'Caucasus Standard Time', 'Afghanistan Standard Time', 'West Asia Standard Time', 'Qyzylorda Standard Time', 'Ekaterinburg Standard Time', 'Pakistan Standard Time', 'India Standard Time', 'Sri Lanka Standard Time', 'Nepal Standard Time', 'Central Asia Standard Time', 'Bangladesh Standard Time', 'Omsk Standard Time', 'Myanmar Standard Time', 'SE Asia Standard Time', 'Altai Standard Time', 'W. Mongolia Standard Time', 'North Asia Standard Time', 'N. Central Asia Standard Time', 'Tomsk Standard Time', 'China Standard Time', 'North Asia East Standard Time', 'Singapore Standard Time', 'W. Australia Standard Time', 'Taipei Standard Time', 'Ulaanbaatar Standard Time', 'Aus Central W. Standard Time', 'Transbaikal Standard Time', 'Tokyo Standard Time', 'North Korea Standard Time', 'Korea Standard Time', 'Yakutsk Standard Time', 'Cen. Australia Standard Time', 'AUS Central Standard Time', 'E. Australia Standard Time', 'AUS Eastern Standard Time', 'West Pacific Standard Time', 'Tasmania Standard Time', 'Vladivostok Standard Time', 'Lord Howe Standard Time', 'Bougainville Standard Time', 'Russia Time Zone 10', 'Magadan Standard Time', 'Norfolk Standard Time', 'Sakhalin Standard Time', 'Central Pacific Standard Time', 'Russia Time Zone 11', 'New Zealand Standard Time', 'UTC+12', 'Fiji Standard Time', 'Kamchatka Standard Time', 'Chatham Islands Standard Time', 'UTC+13', 'Tonga Standard Time', 'Samoa Standard Time', 'Line Islands Standard Time')]
        [string]$TimeZone = 'Central Europe Standard Time',
        [ValidateSet('3', '3', '3', '4', '4', '5', '5', '5', '6', '7', '7', '10', '11', '11', '12', '14', '17', '19', '21', '21', '21', '22', '23', '24', '25', '25', '25', '25', '25', '25', '26', '26', '26', '27', '29', '32', '32', '34', '35', '35', '37', '37', '39', '39', '39', '39', '39', '39', '40', '42', '42', '44', '45', '45', '45', '45', '45', '46', '46', '49', '50', '51', '51', '54', '56', '59', '61', '65', '66', '66', '67', '68', '68', '70', '71', '72', '72', '73', '73', '73', '73', '75', '77', '77', '77', '77', '77', '77', '81', '81', '84', '84', '84', '84', '84', '84', '87', '88', '91', '93', '93', '94', '94', '94', '94', '98', '99', '99', '100', '103', '104', '104', '106', '108', '108', '109', '109', '110', '110', '111', '111', '111', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '113', '116', '117', '118', '118', '119', '121', '121', '122', '124', '126', '129', '130', '134', '134', '136', '137', '138', '138', '139', '139', '140', '140', '141', '141', '143', '143', '145', '147', '147', '147', '148', '151', '152', '152', '154', '154', '154', '157', '157', '158', '159', '159', '159', '159', '162', '163', '163', '164', '164', '165', '166', '167', '167', '167', '173', '175', '175', '175', '175', '175', '175', '175', '176', '176', '176', '177', '177', '177', '177', '177', '177', '178', '181', '182', '183', '183', '184', '185', '185', '187', '187', '190', '190', '190', '191', '191', '192', '192', '193', '193', '197', '198', '200', '200', '201', '201', '202', '203', '203', '203', '203', '203', '204', '204', '205', '205', '207', '209', '209', '209', '209', '209', '209', '209', '209', '209', '210', '210', '210', '212', '212', '213', '215', '215', '216', '216', '217', '217', '217', '217', '217', '217', '219', '221', '221', '221', '221', '221', '222', '222', '223', '223', '223', '223', '224', '224', '225', '225', '227', '227', '228', '232', '233', '234', '234', '235', '235', '237', '238', '240', '241', '242', '242', '242', '244', '244', '244', '244', '246', '247', '247', '247', '249', '249', '251', '252', '253', '261', '264', '270', '270', '271', '271', '307', '322', '332', '347', '19618', '19618', '39070', '10039880', '10039880', '10039880', '161832257')]
        [string]$HomeLocation = '271'
    )
    
    $admin = [boolean]([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    if (!$admin) { return Write-Error -Message "Must run in Admin console." -Category AuthenticationError }
    
    if (!$DateTimeOnly)
    {
        [int]$AutoTime = 3
        if (!$TimeZoneAuto)
        { [int]$AutoTime = $AutoTime + 1 }
        $HomeName = (Get-WinHomeLocation -InformationVariable $HomeLocation).HomeLocation
        $TZAutoSettingRegPath = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate"
    }
    
    [string]$line = "-----------------------------------------------------------------------------"
    Write-Output -InputObject $line
    if (!$DateTimeOnly)
    {
        Write-Output -InputObject "Set time zone automatically:`t$TimeZoneAuto"
        Write-Output -InputObject "Setting location to:`t`t$HomeName"
        Write-Output -InputObject "Setting Time Zone to:`t`t$TimeZone"
    }
    Write-Output -InputObject "Setting short time format to:`t$TimeFormat"
    Write-Output -InputObject "Setting short date format to:`t$DateFormat"
    Write-Output -InputObject "Setting long date format to:`t$LongDateFormat"
    Write-Output -InputObject "Setting long time format to:`t$LongTimeFormat"
    Write-Output -InputObject $line
    
    if (!$DateTimeOnly)
    {
        Set-WinHomeLocation -GeoId $HomeLocation
        Set-ItemProperty -Path $TZAutoSettingRegPath -Name "Start" -Value $AutoTime
        Set-TimeZone -Id $TimeZone
    }
    
    try
    {
        $status = New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS -ErrorAction SilentlyContinue
        if (!$status) { Write-Warning -Message "Cannot make registry value." }
        
        function Set-DateTimeFormat
        {
            [CmdletBinding(SupportsShouldProcess = $true)]
            param
            (
                [Parameter(Mandatory = $true)]
                [string]$sid
            )
            
            if (Test-Path -Path "HKU:\${sid}")
            {
                Set-ItemProperty -Path "HKU:\${sid}\Control Panel\International\" -name sShortDate -value $DateFormat
                Set-ItemProperty -Path "HKU:\${sid}\Control Panel\International\" -name sLongDate -value $LongDateFormat
                Set-ItemProperty -Path "HKU:\${sid}\Control Panel\International" -name sShortTime -value $TimeFormat
                Set-ItemProperty -Path "HKU:\${sid}\Control Panel\International" -name sTimeFormat -value $LongTimeFormat
            }
        }
        
        $userDetails = Get-CimInstance -Class win32_useraccount | Where-Object{ $_.status -eq 'ok' }
        
        if ($SpecUser)
        {
            if ($userDetails.Name -eq $SpecUser)
            {
                foreach ($user in $userDetails)
                {
                    if ($user.Name -eq $SpecUser)
                    {
                        $sid = $user.SID
                        Set-DateTimeFormat -sid $sid
                        Write-Output -InputObject "Updating date and time for:`t$SpecUser"
                        Write-Output -InputObject "User's $SpecUser SID:`t`t$sid"
                        if (!$DateTimeOnly)
                        {
                            Write-Output -InputObject "Rest settings will apply to:`tall users"
                        }
                    }
                }
            }
            else
            {
                return Write-Error -Message "$User does not exist." -Category ObjectNotFound
            }
        }
        else
        {
            [int]$count = 0
            foreach ($user in $userDetails)
            {
                $UserName = $userDetails.Name[$count]
                Write-Output -InputObject "Updating format for user:`t$UserName"
                $sid = $user.SID
                Set-DateTimeFormat -sid $sid
                $count = $count + 1
            }
        }
    }
    catch { Write-Error -Message "Error occured while setting Date format." -Exception "$_.Exception.Message" -Category WriteError }
    Write-Output -InputObject $line
}