Dear @Dark Vador , I updated your script a bit, automated a lot of the work but there are still some missing parts. ☺️ Is there a way to permanently activate Office products with the zerocid method using this script with a Retail or MAK product key? I just couldn't figure it out ☺️ Features: LibTSforge.dll Integration: The script loads the LibTSforge.dll file, which is Base64 encoded, into memory. If the file is present, it will be loaded; otherwise, it will be decompressed from Base64 and loaded into memory. Random KMS IP Address Setting: For KMS or Volume licensed products, the script generates a random KMS IP address and sets it in the Windows registry. This helps prevent the "Genuine" license warning. Activation for Different License Types: KMS (Key Management Service) licenses for activation. VIRTUAL MACHINE ACTIVITY for AVMA (Automatic Virtual Machine Activation). MAK, RETAIL, and OEM licenses for activation. Retail Office Products: The script detects retail (consumer) Office products, but it does not perform automatic activation for them. Product Selection and Activation: The script provides a user interface (Out-GridView) for selecting Windows and Office products for activation. Users can choose products and start the activation process. Product Information Retrieval: The script detects the license status of installed Windows and Office products on the system. Version Detection: The script uses the LibTSforge library to detect the current version of the product, and based on this, it performs the appropriate activation. Key Generation: The script generates random product keys and applies them to the corresponding products. Supported Versions: Windows: Windows 10 and later versions (supports zerocid activation). Office: Office 2013 and later versions, particularly for KMS licenses. Compatible with Office 2016 and later versions. (supports KMS activation). User Input: -w: Selects only Windows products for activation. -o: Selects only Office products for activation. When these parameters are used, the script activates only Windows or Office products. If both are selected, it activates both Windows and Office. If no parameters are provided, the user is prompted with a selection screen to choose the products to activate. Special Cases: VIRTUAL_MACHINE_ACTIVATION license type: Works only on Windows Server Datacenter editions and requires Hyper-V or QEMU virtualization environments. While the script indicates success, real activation status may be verified through the slmgr.vbs -dlv command, which might show the actual activation state.
So now you want to install list of massive amount of mak license's, wmi command will be very very slowly In case of rtool, I remove all license, and reinstall vol & mak license And client* and pkeyconfig* license^s * But for a specific product
Got an idea, do query of all office license * specific vol Search for mak same product Not found, search for mak license Install them, than re load license list
TSF Activation updated Thansk @Dark Vador and @Windows_Addict https://github.com/abdullah-erturk/tsf_activation
Kms host key "csvlk" working with tsforge or massgrave ( but error with dark vador scripts ) 1 use dark vador to activate server 2022 standard with kms4k If you choose with dark vador script kms ws22 channel "csvlk" / kms4k are used she need to edit to use zerocid for ws22 channel If you use this script + regular kms aka gvlk os are activated fines ( but kms server features aka csvlk no works ) @Dark Vador You need to edit script ! If channel csvlk aka kms host are selected WS12_R2,WS16,WS19,WS22,WS25,WS10 => ZeroCID
if ($desc -match 'KMSCLIENT') { [LibTSforge.Activators.KMS4k]::Activate($ver, $prod, $id) } elseif ($desc -match 'VIRTUAL_MACHINE_ACTIVATION') { [LibTSforge.Activators.AVMA4K]::Activate($ver, $prod, $id) } elseif ($desc -match 'MAK|RETAIL|OEM|KMS_R2|WS12|WS12_R2|WS16|WS19|WS22|WS25') { [LibTSforge.Activators.ZeroCID]::Activate($ver, $prod, $id) } else { Write-Warning "Unknown license type: $desc" } } change $_.Description -notmatch 'DEMO|MSDN|PIN|FREE|TIMEBASED|GRACE|W10|WS12|WS12R2|WS16|WS19|WS22|WS25' to $_.Description -notmatch 'DEMO|MSDN|PIN|FREE|TIMEBASED|GRACE|W10'
$_.Description -notmatch 'DEMO|MSDN|PIN|FREE|TIMEBASED|GRACE|W10|WS12|WS12R2|WS16|WS19|WS22|WS25' so, it include or exclude what about the rest products ? w?
$_.Description -notmatch 'DEMO|MSDN|PIN|FREE|TIMEBASED|GRACE|W10' @Dark Vador https://www.mediafire.com/file/dsqh3vgwqnmh3d3/TSForge-LicenseTool.ps1/file add Server 2008 R2 / 2012 / 2012R2 / 2016 /2019 / 2022 / 2025 KMS HOST Support ! ( Windows 10 / 11 KMS Host no working )
https://www.mediafire.com/file/afki9r5mk7duz8c/TSForge-ohook-LicenseTool.ps1/file tsforge + embedded ohook to keep office click to run ( office 2013 UP TO 2024 ) activated , after windows upgrade eg: 23H2 TO 24H2 in same script if os are lower than windows 8 ohook are ignored @Dark Vador
@pm67310 so, you want install oHook & use ZeroCid\kms4k in same time ? or maybe give user a choice, with GUI, instead ? also, this is x64 ohook only what about the part of - install key's ?
@Dark Vador so, you want install oHook & use ZeroCid\kms4k in same time ? => Yes because features upgrade resist what about the part of - install key's ? => use generated key 32bits os ? useless
Interesting, and about the x86 version? In my logic, you can just copy paste it After first activation end And I need to also encode x86 dll too
and about the x86 version? => tsforge only @Dark Vador Code: Function GetRandomKey([String] $ProductID) { try { $guid = [Guid]::Parse($ProductID) $pkc = [LibTSforge.SPP.PKeyConfig]::new() try { $pkc.LoadConfig($guid) | Out-Null } catch { $pkc.LoadAllConfigs([LibTSforge.SPP.SLApi]::GetAppId($guid)) | Out-Null } $config = [LibTSforge.SPP.ProductConfig]::new() $refConfig = [ref] $config $pkc.Products.TryGetValue($guid, $refConfig) | Out-Null return $config.GetRandomKey().ToString() } catch { Write-Warning "Failed to retrieve key for Product ID: $ProductID" return $null } } function Invoke-IfOfficeClickToRunExists { param ( [ScriptBlock]$Action ) # Get OS version $osVersion = [System.Environment]::OSVersion.Version # Check if the OS is Windows 8.0 (6.2) or higher $isSupportedOS = ($osVersion.Major -gt 6) -or ($osVersion.Major -eq 6 -and $osVersion.Minor -ge 2) if (-not $isSupportedOS) { Write-Host "ohook need windows 8.0 or up. Skipping action..." return } # Check if the Office Click-to-Run service exists $clickToRunService = Get-Service -Name "ClickToRunSvc" -ErrorAction SilentlyContinue if ($clickToRunService) { Write-Host "Office Click-to-Run detected. Executing action..." & $Action } else { Write-Host "Office Click-to-Run not detected. Skipping ohook action..." } } # Example usage: Invoke-IfOfficeClickToRunExists { $base64 = @' H4sIAAAAAAAEAO1aW2wcVxn+15ckbuxcIGnTNmk2wUmctFns1AGnoak3u3Z26TreeH1pkqbxZPd4PfV6ZjIz69oVSKUhgOtaiuAFVaoKohVCQqIPRUQkSFaDGngIBZknHkBqkUiUSg0CHlAEy3dmznhnZ/YSgdKoyMf+Zs75/ss5/z9nz5zZ2b4TF6ieiBqAQoHoItmlm2qXl4A1W3++ht5purbtYiBxbdvguGwENV3N6tJkMC0pimoGz7CgnleCshKM9qeCk2qGhVpa7msVPpI9RJlvrCT18C3m+L1Foe2r6+r2UB0aj9jcP9fhwEHf7uC0Va+zx83LCsf4gh2M8hoXjwaIgja/zlFY52mLapJonlc0VAN2cNM8Me1ErfS/l2/Bb1cVechk0yaJvkVsS8GJEiQaDekZyZREVEGht6JUrxv/Ic3Ws8beLvRWldGbdvnrFnr3ldFjtp6VI+SKPgM0l9GTbT0rDk34e8SntxDSDT1NIscviViDfn+0XO5qScXOfdTdsdDD/38dm422dsXm+QG1Nl7r5LVgFIfOxHzjb9YSXb8Bs9hcAkpzW06NEp1fyO+IznHV+Y0/g0Jh48ioo3F+wWwqLF7kk+FmQ2GxYyF27pfdJ6+Eh8KDQyPDvPOujkJi7set/GObmHuz9bv8PJtrDcZmryVmM61t118GM/seOjkUPvhVMrpiE39qi89taI0F/nDuxXVkbo/N3ri+v1AoQOX+eP3mVnRyNbKOdxmbjWwCgrHC1Zvvzt5C310nnzt9Kvxs+NQVa0xXLhR2vHYai8aFtVu/buXD337eahd2nLDPojj587Y/beUoSTRJfOk9QjrqaWI1bZbL/1HBej7F1/Ru+8zvs6u67XMB2Nx9b4e3XO5uCTTWUaMeaA80r6TmM6vaV46u0BqTDQt1v4XsXg9uuXwixdl7vzdgX/OIQBv2eZ3HsDSAfx/4GGhMEe0GTgHfB24ADwwS7QeywOvAh8DeISIJeANYBFqGiQ4CZ4GfAO8Dt4ftNefYCMYAvAEsAuufIeoDVOAt4BrQeJwoDEwCPwQuAbeBAyeI+oE88DqwCKw8SfQkIANvAR8CLc9CF5gFfgesP0V0HPgB8Ffg4edwBwS+CVwC/gI8ijv+SeCnwE1g1yjiBj5AHv4FPITYe4GXgV8B9Yh7N3AMOA9cAVYj9i8D54DLwN+AXYj7OPAd4F3gOvAg4u4A0sArwGXgH8A+xC4B88Bl4CNgJ+I+AcwD7wB/BLYg7iMAA14FLgG3gB2IfRh4BbgK3AZ2Iv4M8Dbwd6AL8X8NuAY0Ie5O4HngTeD3QDNi7wXmgEWgGTnoAaZH+awJYItfj+17Ix5DVuIRowmPD6vxaNBCa2gtbi/r8ajwWdpAG+l+eoA20YP0ED1Mm2kLHgu2Ysu/jbbT5/CcsoN20i5qo920hx6lx2gvhejzeHTpoH30OHXSfvoCfRHPUAfoCTpIX6In6RA9hdtWmA6ToWnpUCaXo1QyGUmFUomIlMulmD7FdCptOPKcajBaOjusqhj5STYgZ8dN8jaFTpRpqiGbfTKecU1ZVQ7n1DNUiS616R8by8kKg9sxWZ+01OIZqiW+Ax890zW8cIVSPylT1dmgOsEUKssJ7V5ZZz1TTOHpcNWF9IhkjjPdm4qybGULa/AVeMeKKQwCJmKLK4aJS1pMYA35nXixR1FLY8mTGU6b8hRLyGmmGFAcU6kS7bLRtJyctt1BJK4OVZWVtU6qqM34DB3aZZNHWhVTyAeYkc+ZVEVStOxR0vqMZrJMMh4VufFxRW0kLm8lzBNVOb5oJfILf7qayafNp9lMPGNQVVnRWiSZShs+ea+cY2KSeCmfrm/81XlZyaZMycwbFeJLWoOmkrpH6nXsI1361tX1W/jpKjbRkf6BaAVDIXNZ26lPTeT9vZYXFW1TiXg0IRtithVbLg2syEijz3U5XliJSVG88l6iVA+DVMf6x5J5PT0uufV9gqp21vSvLHJsDTHZE2paytk2PkroJlQp4/3cyozP/IoSYdmvWQu2fRJckukGclveYTVhqf3AYCopzeQwgH7cKXU5w6iqTFgPsLA+SUvnJTYLM6Y79w5P26OVzOWzskJ+QuilvOtVlH/HWJEvWkXyug5pcQ2hSnTRpuxaVoEXVkOK7J2Zfsqr65+dlUVLtrmKM6eKbMla91wVH+PTXLoyfkroaq4rwESOBuX0BDNxU9FUOxt3ouT4O4x+lBKdQV1SDCktLkUtBcdPJMck3bofi7tqkr+XYAZPVjWhYy82RVH1BSXHpliupEeqreDxY+2rij26k1NLw/HkbE88ipFxfqNUspav2jpFb86UFvs2H+PXtBYyKke5dMWMD6fP5mWEJXY0VF3osu9LJeVM6cevPO22kdLjGMzQkaF4lMpRLl1Pao5g8piuEVYWOz7iYSFmYgWh8uSSviEWnDKbmigbk7D1spemO9Z0PEOaxqQd7kvKGutDTbJnQXnesUqJfWqZz0VFkWM7qMvZLNPFTXpE1SesR6wKvGM1nCiTMT+5XD7xktSK9eBZ+z3luItrB/c9tKddXBTc2662uywI/gOv/Gxps9nT/m/t6mpuyAPVdqx0vd5awHp1xuhYIGXq+D8aH7HfXQL8mwXD+mqBaAPaT/cMHO1JPL5PUNSm8XdoiZFwMu5Qn+ISsF49b7LfyJbw/HvB9jJ8UwNRDLVnINlcX5Rsru/EcZhSdBrHHhpALU79dBTtOI69qPPyi4aP/839NAq7xtIOqAF/dR7uK3XcIkUm6SSTQll4kylHDJ4VGiOVj8fSaadO4IB17iE+ohdpL/gIdCZxeSXoz7jegRGFwXCZBH8q5cmgIHpS4dWkF8Dq0AtSFEcT4P2r1nsz06opkEUsRvPwvByi1ejbGSv3YVDa8qGV6Kk0Dqg0YfWdxF/E4ttplct+2OrfcNm1U4j2A+0WiPYgmwErJ/ZYFSuqYrQG+tUobdm+iuwEKAE+a2nxKDTkho8ui/HwxflHGM8+eN4H3eBdzNQT1ISx9Iu+ZTFuJ27FN/4QZSCxP3uP0QrYJmGrgs1DapZc32JuCVGs8ul6s+rNadSa9cNWfP5Zx39vwX/IMGhFpMBPzjMHmhr+7PlVx70t/wHxf5zsACQAAA== '@ # Decode the Base64 string back into a byte array $compressedDllBytes = [Convert]::FromBase64String($base64) # Step 2: Create a MemoryStream from the byte array $compressedStream = [System.IO.MemoryStream]::new($compressedDllBytes) # Step 3: Decompress the byte array using GZip $gzipStream = New-Object System.IO.Compression.GZipStream($compressedStream, [System.IO.Compression.CompressionMode]::Decompress) $decompressedStream = New-Object System.IO.MemoryStream # Copy the decompressed data to a new MemoryStream $gzipStream.CopyTo($decompressedStream) $gzipStream.Close() # Step 4: Get the decompressed byte array $decompressedDllBytes = $decompressedStream.ToArray() # Define the output file path with ProgramFiles environment variable $sppc = [System.IO.Path]::Combine($env:ProgramFiles, "Microsoft Office\root\vfs\System\sppc.dll") # Define paths for symbolic link and target $sppcs = [System.IO.Path]::Combine($env:ProgramFiles, "Microsoft Office\root\vfs\System\sppcs.dll") $System32 = [System.IO.Path]::Combine($env:windir, "System32\sppc.dll") # Step 1: Check if the symbolic link exists and remove it if necessary if (Test-Path -Path $sppcs) { Write-Host "Symbolic link already exists at $sppcs. Attempting to remove..." try { # Remove the existing symbolic link Remove-Item -Path $sppcs -Force Write-Host "Existing symbolic link removed successfully." } catch { Write-Host "Failed to remove existing symbolic link: $_" } } else { Write-Host "No symbolic link found at $sppcs." } try { # Attempt to write byte array to the file [System.IO.File]::WriteAllBytes($sppc, $decompressedDllBytes) Write-Host "Byte array written successfully to $sppc." } catch { Write-Host "Failed to write byte array to ${sppc}: $_" # Inner try-catch to handle the case where the file is in use try { Write-Host "File is in use or locked. Attempting to move it to a temp file..." # Generate a random name for the temporary file in the temp folder $tempDir = [System.IO.Path]::GetTempPath() $tempFileName = [System.IO.Path]::Combine($tempDir, [System.Guid]::NewGuid().ToString() + ".bak") # Move the file to the temp location with a random name Move-Item -Path $sppc -Destination $tempFileName -Force Write-Host "Moved file to temporary location: $tempFileName" # Retry the write operation after moving the file [System.IO.File]::WriteAllBytes($sppc, $decompressedDllBytes) Write-Host "Byte array written successfully to $sppc after moving the file." } catch { Write-Host "Failed to move the file or retry the write operation: $_" } } # Step 3: Check if the symbolic link exists and create it if necessary try { if (-not (Test-Path -Path $sppcs)) { # Create symbolic link only if it doesn't already exist New-Item -Path $sppcs -ItemType SymbolicLink -Target $System32 | Out-Null Write-Host "Symbolic link created successfully at $sppcs." } else { Write-Host "Symbolic link already exists at $sppcs." } } catch { Write-Host "Failed to create symbolic link at ${sppcs}: $_" } } Function Main { $selected = $null $ver = [LibTSforge.Utils]::DetectVersion()