{"id":530396,"date":"2025-09-22T01:56:00","date_gmt":"2025-09-22T01:56:00","guid":{"rendered":"https:\/\/www.ninjaone.com\/?post_type=script_hub&#038;p=530396"},"modified":"2025-09-22T01:56:00","modified_gmt":"2025-09-22T01:56:00","slug":"verifier-les-parametres-wsus-sur-windows-avec-powershell","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/fr\/script-hub\/verifier-les-parametres-wsus-sur-windows-avec-powershell\/","title":{"rendered":"Comment v\u00e9rifier les param\u00e8tres WSUS sur Windows avec un script PowerShell"},"content":{"rendered":"<p>Windows Server Update Services (WSUS) joue un r\u00f4le essentiel dans la gestion centralis\u00e9e des correctifs pour les environnements Windows. Pour les professionnels de l&rsquo;informatique et les <a href=\"https:\/\/www.ninjaone.com\/fr\/quest-ce-quun-msp\/\">fournisseurs de services g\u00e9r\u00e9s (MSP)<\/a>, il est essentiel de savoir si WSUS est activ\u00e9 (et si oui, comment il est configur\u00e9) pour maintenir la conformit\u00e9 du syst\u00e8me, la coh\u00e9rence des correctifs et l&rsquo;efficacit\u00e9 op\u00e9rationnelle. Ce script PowerShell est un outil complet d&rsquo;audit des param\u00e8tres WSUS, particuli\u00e8rement utile dans les environnements o\u00f9 les param\u00e8tres peuvent \u00eatre contr\u00f4l\u00e9s via des objets de strat\u00e9gie de groupe (GPO).<\/p>\n<h2>Contexte<\/h2>\n<p>WSUS permet aux administrateurs de g\u00e9rer la distribution des mises \u00e0 jour publi\u00e9es par Microsoft Update. Cependant, la visibilit\u00e9 de la configuration peut \u00eatre opaque, en particulier dans les environnements o\u00f9 les strat\u00e9gies de groupe sont r\u00e9parties entre plusieurs unit\u00e9s organisationnelles. L&rsquo;inspection manuelle des cl\u00e9s de registre et des chemins d&rsquo;acc\u00e8s aux strat\u00e9gies de groupe (GPO) est \u00e0 la fois inefficace et source d&rsquo;erreurs.<\/p>\n<p>Ce script PowerShell a \u00e9t\u00e9 con\u00e7u pour r\u00e9pondre \u00e0 cette complexit\u00e9. Il v\u00e9rifie non seulement si WSUS est activ\u00e9, mais d\u00e9termine \u00e9galement si la configuration provient de valeurs de registre ou de GPO. De plus, il offre la possibilit\u00e9 d&rsquo;enregistrer les r\u00e9sultats dans un champ personnalis\u00e9 NinjaOne, ce qui permet une visibilit\u00e9 au niveau de l&rsquo;actif dans les outils de surveillance et de gestion \u00e0 distance (RMM).<\/p>\n<h2>Le script<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 5.1\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Determines if Windows Server Update Services (WSUS) settings are configured in the registry and identifies if they are managed via Group Policy (GPO). You can also write the results to a text custom field.\r\n.DESCRIPTION\r\n    Determines if Windows Server Update Services (WSUS) settings are configured in the registry and identifies if they are managed via Group Policy (GPO). You can also write the results to a text custom field.\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n\r\n.PARAMETER CustomFieldName\r\n    The name of the custom field to set with WSUS settings information.\r\n\r\n.EXAMPLE\r\n    (No Parameters)\r\n\r\n    [Info] Updating group policies...\r\n    [Info] Group policy update completed successfully.\r\n\r\n    [Info] Checking the registry for WSUS settings...\r\n    [Info] WSUS Update Server detected in the registry: https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n    [Info] WSUS Statistics Server detected in the registry: https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n\r\n    [Info] Checking for GPOs that configure WSUS settings...\r\n    [Info] Found GPOs that affect WSUS settings.\r\n\r\n    ### Active WSUS settings: ###\r\n\r\n    WSUS Settings Source : GPO\r\n    WSUS Status          : Enabled\r\n    GPO Display Name     : A_WSUS_Settings\r\n    Update Server        : https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n    Statistics Server    : https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n\r\n.EXAMPLE\r\n    -CustomFieldName \"WSUSSettings\"\r\n\r\n    [Info] Updating group policies...\r\n    [Info] Group policy update completed successfully.\r\n\r\n    [Info] Checking the registry for WSUS settings...\r\n    [Info] WSUS Update Server detected in the registry: https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n    [Info] WSUS Statistics Server detected in the registry: https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n\r\n    [Info] Checking for GPOs that configure WSUS settings...\r\n    [Info] Found GPOs that affect WSUS settings.\r\n\r\n    ### Active WSUS settings: ###\r\n\r\n    WSUS Settings Source : GPO\r\n    WSUS Status          : Enabled\r\n    GPO Display Name     : A_WSUS_Settings\r\n    Update Server        : https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n    Statistics Server    : https:\/\/test.local.another.sub.domain\/test\/testagain:8562\r\n\r\n    [Info] Setting the custom field 'WSUSSettings' with the value:\r\n    WSUS Status: Enabled | Update and Statistics Server: https:\/\/test.local.another.sub.domain\/test\/testagain:8562 | GPO Name: A_WSUS_Settings\r\n    [Info] Successfully set the custom field 'WSUSSettings'.\r\n\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 10, Windows Server 2016\r\n    Release Notes: Initial release\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [string]$CustomFieldName\r\n)\r\nbegin {\r\n    # Import custom field from script variable\r\n    if ($env:textCustomFieldName) { $CustomFieldName = $env:textCustomFieldName }\r\n\r\n    # Validate the custom field name if provided\r\n    if ($CustomFieldName) {\r\n        # Trim the custom field name to remove any leading or trailing whitespace\r\n        $CustomFieldName = $CustomFieldName.Trim()\r\n\r\n        # Error if the custom field name is empty\r\n        if ([string]::IsNullOrWhiteSpace($CustomFieldName)) {\r\n            Write-Host -Object \"[Error] The value for 'Text Custom Field Name' cannot be empty.\"\r\n            Write-Host -Object \"[Error] Please provide a valid text custom field name to save the results, or leave it blank.\"\r\n            exit 1\r\n        }\r\n\r\n        # Validate that the field name contains only alphanumeric characters\r\n        if ($CustomFieldName -match \"[^0-9A-Z]\") {\r\n            Write-Host -Object \"[Error] The 'Text Custom Field Name' of '$CustomFieldName' is invalid as it contains invalid characters.\"\r\n            Write-Host -Object \"[Error] Please provide a valid text custom field name to save the results, or leave it blank.\"\r\n            Write-Host -Object \"[Error] https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/360060920631-Custom-Field-Setup\"\r\n            exit 1\r\n        }\r\n    }\r\n\r\n    # Function to set a custom field in NinjaOne\r\n    function Set-CustomField {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter()]\r\n            [String]$DocumentName,\r\n            [Parameter()]\r\n            [Switch]$Piped\r\n        )\r\n\r\n        if ($Type -eq \"Date Time\") { $Type = \"DateTime\" }\r\n        if ($Type -match \"[-]\") { $Type = $Type -replace '-' }\r\n        if ($Type -match \"[\/]\") { $Type = $Type -replace '\/' }\r\n\r\n        # Remove the non-breaking space character\r\n        if ($Type -eq \"WYSIWYG\") {\r\n            $Value = $Value -replace '\u00a0', '&amp;nbsp;'\r\n        }\r\n\r\n        if ($Type -eq \"DateTime\" -or $Type -eq \"Date\") {\r\n            $Type = \"Date or Date Time\"\r\n        }\r\n    \r\n        # Measure the number of characters in the provided value\r\n        $Characters = $Value | ConvertTo-Json | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n\r\n        # Throw an error if the value exceeds the character limit of 200,000 characters\r\n        if ($Piped -and $Characters -ge 200000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded: the value is greater than or equal to 200,000 characters.\")\r\n        }\r\n\r\n        if (!$Piped -and $Characters -ge 45000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded: the value is greater than or equal to 45,000 characters.\")\r\n        }\r\n    \r\n        # Initialize a hashtable for additional documentation parameters\r\n        $DocumentationParams = @{}\r\n\r\n        # If a document name is provided, add it to the documentation parameters\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n    \r\n        # Define a list of valid field types\r\n        $ValidFields = \"Checkbox\", \"Date\", \"Date or Date Time\", \"DateTime\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \r\n        \"MultiSelect\", \"Phone\", \"Secure\", \"Text\", \"Time\", \"URL\", \"WYSIWYG\"\r\n\r\n        # Warn the user if the provided type is not valid\r\n        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning \"$Type is an invalid type. Please check here for valid types: https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\" }\r\n    \r\n        # Define types that require options to be retrieved\r\n        $NeedsOptions = \"Dropdown\", \"MultiSelect\"\r\n\r\n        # If the property is being set in a document or field and the type needs options, retrieve them\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n    \r\n        # Throw an error if there was an issue retrieving the property options\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # Process the property value based on its type\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # Convert the value to a boolean for Checkbox type\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Convert the value to a Unix timestamp for Date or Date Time type\r\n                $Date = (Get-Date $Value).ToUniversalTime()\r\n                $TimeSpan = New-TimeSpan (Get-Date \"1970-01-01 00:00:00\") $Date\r\n                [long]$NinjaValue = $TimeSpan.TotalSeconds\r\n            }\r\n            \"Dropdown\" {\r\n                # Convert the dropdown value to its corresponding GUID\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID\r\n        \r\n                # Throw an error if the value is not present in the dropdown options\r\n                if (!($Selection)) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown options.\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            \"MultiSelect\" {\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selections = New-Object System.Collections.Generic.List[String]\r\n                if ($Value -match \"[,]\") {\r\n                    $Value = $Value -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }\r\n                }\r\n\r\n                $Value | ForEach-Object {\r\n                    $GivenValue = $_\r\n                    $Selection = $Options | Where-Object { $_.Name -eq $GivenValue } | Select-Object -ExpandProperty GUID\r\n\r\n                    # Throw an error if the value is not present in the dropdown options\r\n                    if (!($Selection)) {\r\n                        throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown options.\")\r\n                    }\r\n\r\n                    $Selections.Add($Selection)\r\n                }\r\n\r\n                $NinjaValue = $Selections -join \",\"\r\n            }\r\n            \"Time\" {\r\n                # Convert the value to a Unix timestamp for Date or Date Time type\r\n                $LocalTime = (Get-Date $Value)\r\n                $LocalTimeZone = [TimeZoneInfo]::Local\r\n                $UtcTime = [TimeZoneInfo]::ConvertTimeToUtc($LocalTime, $LocalTimeZone)\r\n\r\n                [long]$NinjaValue = ($UtcTime.TimeOfDay).TotalSeconds\r\n            }\r\n            default {\r\n                # For other types, use the value as is\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # Set the property value in the document if a document name is provided\r\n        if ($DocumentName) {\r\n            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2&gt;&amp;1\r\n        }\r\n        else {\r\n            try {\r\n                # Otherwise, set the standard property value\r\n                if ($Piped) {\r\n                    $CustomField = $NinjaValue | Ninja-Property-Set-Piped -Name $Name 2&gt;&amp;1\r\n                }\r\n                else {\r\n                    $CustomField = Ninja-Property-Set -Name $Name -Value $NinjaValue 2&gt;&amp;1\r\n                }\r\n            }\r\n            catch {\r\n                throw $_.Exception.Message\r\n            }\r\n        }\r\n        \r\n        # Throw an error if setting the property failed\r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n\r\n    # Function to test if a device is domain-joined\r\n    function Test-IsDomainJoined {\r\n        # Check the PowerShell version to determine the appropriate cmdlet to use\r\n        try {\r\n            if ($PSVersionTable.PSVersion.Major -lt 3) {\r\n                return $(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain\r\n            }\r\n            else {\r\n                return $(Get-CimInstance -Class Win32_ComputerSystem).PartOfDomain\r\n            }\r\n        }\r\n        catch {\r\n            Write-Host -Object \"[Error] Unable to validate whether or not this device is a part of a domain.\"\r\n            Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n            exit 1\r\n        }\r\n    }\r\n\r\n    # Function to test if the current device is a server or domain controller\r\n    function Test-IsServer {\r\n        [CmdletBinding()]\r\n        param()\r\n    \r\n        # Determine the method to retrieve the operating system information based on PowerShell version\r\n        $OS = if ($PSVersionTable.PSVersion.Major -lt 3) {\r\n            Get-WmiObject -Class Win32_OperatingSystem\r\n        }\r\n        else {\r\n            Get-CimInstance -ClassName Win32_OperatingSystem\r\n        }\r\n    \r\n        # Check if the ProductType is \"2\", which indicates that the system is a domain controller or is a server\r\n        if ($OS.ProductType -eq \"2\" -or $OS.ProductType -eq \"3\") {\r\n            return $true\r\n        }\r\n    }\r\n\r\n    # Function to test if the current session is running with Administrator privileges\r\n    function Test-IsElevated {\r\n        [CmdletBinding()]\r\n        param ()\r\n    \r\n        # Get the current Windows identity of the user running the script\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n    \r\n        # Create a WindowsPrincipal object based on the current identity\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n    \r\n        # Check if the current user is in the Administrator role\r\n        # The function returns $True if the user has administrative privileges, $False otherwise\r\n        # 544 is the value for the Built In Administrators role\r\n        # Reference: https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.security.principal.windowsbuiltinrole\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]'544')\r\n    }\r\n}\r\nprocess {\r\n    # Attempt to determine if the current session is running with Administrator privileges.\r\n    try {\r\n        $IsElevated = Test-IsElevated -ErrorAction Stop\r\n    } catch {\r\n        # Output error if unable to determine elevation status\r\n        Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n        Write-Host -Object \"[Error] Unable to determine if the account '$env:Username' is running with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    # Exit if not running as an administrator\r\n    if (!$IsElevated) {\r\n        Write-Host -Object \"[Error] Access Denied: Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    # Check if the device is domain-joined\r\n    $IsDomainJoined = Test-IsDomainJoined\r\n\r\n    # If domain-joined, do a group policy update\r\n    if ($IsDomainJoined) {\r\n        # Run gpupdate to ensure policy is refreshed\r\n        Write-Host -Object \"[Info] Updating group policies...\"\r\n\r\n        # Generate unique log file names for capturing the stdout and stderr of the 'gpupdate.exe' process.\r\n        $StandardOutLog = \"$env:TEMP\\$(Get-Random)_gpupdate_stdout.log\"\r\n\r\n        try {\r\n            # Start the group policy update process\r\n            $gpupdateProcess = Start-Process -FilePath \"$env:SystemRoot\\System32\\gpupdate.exe\" -ArgumentList \"\/force\" -Wait -NoNewWindow -PassThru -RedirectStandardOutput $StandardOutLog -ErrorAction Stop\r\n        } catch {\r\n            # If the 'gpupdate.exe' process fails to start, output an error message\r\n            Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n            Write-Host -Object \"[Error] Failed to start '$env:SystemRoot\\System32\\gpupdate.exe'.\"\r\n        }\r\n\r\n        # If the exit code is non-zero (indicating an error occurred), display an error message\r\n        if ($gpupdateProcess.ExitCode -ne 0) {\r\n            Write-Host -Object \"[Error] Failed to update group policy, exit code: $($gpupdateProcess.ExitCode)\"\r\n\r\n            # Check if the standard output log file exists.\r\n            if (Test-Path -Path $StandardOutLog -ErrorAction SilentlyContinue) {\r\n                # Retrieve the contents of the error log\r\n                $errorContent = Get-Content -Path $StandardOutLog -ErrorAction SilentlyContinue\r\n                \r\n                if ($ErrorContent) {\r\n                    # Remove blank lines and the header of the log\r\n                    $errorContent = $errorContent | Where-Object { $_ } | Select-Object -Skip 1 | Out-String\r\n\r\n                    # Add [Error] prefix to the beginning\r\n                    $errorContent = $errorContent.Trim() -replace \"^\", \"[Error] \"\r\n                    \r\n                    # Display the error content to the user\r\n                    $errorContent | Out-Host\r\n                }\r\n\r\n                try {\r\n                    # Attempt to delete the stdout log file after displaying its contents.\r\n                    Remove-Item -Path $StandardOutLog -ErrorAction Stop\r\n                } catch {\r\n                    Write-Host -Object \"[Error] Failed to remove standard output log at '$StandardOutLog'\"\r\n                }\r\n            }\r\n            Write-Host -Object \"\"\r\n            Write-Host -Object \"[Warning] Failed to update group policy. Results may not reflect the latest group policy settings.\"\r\n        } else {\r\n            Write-Host -Object \"[Info] Group policy update completed successfully.\"\r\n        }\r\n    }\r\n\r\n    # Initialize exit code and output object\r\n    $ExitCode = 0\r\n    $ActiveWSUSSettings = [PSCustomObject]::new()\r\n\r\n    # Define registry path for WSUS settings\r\n    $wsusRegPath = 'HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate'\r\n\r\n    # Check registry for WSUS settings\r\n    if ((Test-Path $wsusRegPath)) {\r\n        Write-Host -Object \"`n[Info] Checking the registry for WSUS settings...\"\r\n\r\n        try {\r\n            $useWUServer = (Get-ItemProperty -Path \"$wsusRegPath\\AU\" -ErrorAction Stop).UseWUServer\r\n        } catch {\r\n            Write-Host -Object \"`n[Error] Error retrieving WSUS settings from the registry.\"\r\n            Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n            exit 1\r\n        }\r\n\r\n        # Add registry as the source to the active settings object\r\n        $ActiveWSUSSettings | Add-Member -MemberType NoteProperty -Name \"WSUS Settings Source\" -Value \"Registry\"\r\n\r\n        # If the GPO setting is configured, the UseWUServer regkey will be present and populated\r\n        switch ($useWUServer) {\r\n            0 {\r\n                $checkForGPOs = $true\r\n                $WSUSStatus = \"Disabled\"\r\n            }\r\n            1 {\r\n                $checkForGPOs = $true\r\n                $WSUSStatus = \"Enabled\"\r\n            }\r\n            default {\r\n                # If the UseWUServer regkey is not present or is a different value, it means WSUS is not configured via GPO, so we can skip checking for GPOs\r\n                $checkForGPOs = $false\r\n                $WSUSStatus = \"Not Configured\"\r\n                Write-Host -Object \"[Info] WSUS is not enabled on this device.\"\r\n            }\r\n        }\r\n\r\n        # Add the WSUS status to the active settings object\r\n        $ActiveWSUSSettings | Add-Member -MemberType NoteProperty -Name \"WSUS Status\" -Value $WSUSStatus\r\n        \r\n        # Retrieve the WSUS server and statistics server from the registry\r\n        $wsusServerReg = Get-ItemProperty -Path \"$wsusRegPath\" -Name WUServer, WUStatusServer -ErrorAction SilentlyContinue\r\n        $wsusServerFromRegistry = $wsusServerReg.WUServer\r\n        $statisticsServerFromRegistry = $wsusServerReg.WUStatusServer\r\n        \r\n        # If either server is configured, add the servers to the active settings object and check for GPOs\r\n        if ($wsusServerFromRegistry -or $statisticsServerFromRegistry) {\r\n            $checkForGPOs = $true\r\n            $ActiveWSUSSettings.\"WSUS Settings Source\" = \"Registry\"\r\n\r\n            if ($wsusServerFromRegistry) {\r\n                Write-Host -Object \"[Info] WSUS Update Server detected in the registry: $wsusServerFromRegistry\"\r\n            } else {\r\n                $wsusServerFromRegistry = \"Not Configured\"\r\n                Write-Host -Object \"[Warning] The WSUS Update Server is not configured. The update server is required for WSUS to function correctly.\"\r\n            }\r\n\r\n            if ($statisticsServerFromRegistry) {\r\n                Write-Host -Object \"[Info] WSUS Statistics Server detected in the registry: $statisticsServerFromRegistry\"\r\n            } else {\r\n                $statisticsServerFromRegistry = \"Not Configured\"\r\n                Write-Host -Object \"[Warning] The WSUS Statistics Server is not configured. The statistics server is required for WSUS to function correctly.\"\r\n            }\r\n        } else {\r\n            # If neither server is configured, then WSUS is not configured via GPO and we can skip checking for GPOs\r\n            $checkForGPOs = $false\r\n            $wsusServerFromRegistry = \"Not Configured\"\r\n            $statisticsServerFromRegistry = \"Not Configured\"\r\n            Write-Host -Object \"[Warning] No WSUS servers were detected in the registry.\"\r\n        }\r\n\r\n        # Add the WSUS server and statistics server to the active settings object\r\n        $ActiveWSUSSettings | Add-Member -MemberType NoteProperty -Name \"Update Server\" -Value $wsusServerFromRegistry\r\n        $ActiveWSUSSettings | Add-Member -MemberType NoteProperty -Name \"Statistics Server\" -Value $statisticsServerFromRegistry\r\n    }\r\n    else {\r\n        $checkForGPOs = $false\r\n        Write-Host -Object \"`n[Info] The registry key '$wsusRegPath' was not found. WSUS is not configured on this device.`n\"\r\n    }\r\n\r\n    # Check for GPO setting the WSUS configuration\r\n    if ($IsDomainJoined -and $checkForGPOs) {\r\n        Write-Host -Object \"`n[Info] Checking for GPOs that configure WSUS settings...\"\r\n\r\n        # Define the WSUS registry path\r\n        $wsusRegistryPath = \"Software\\\\Policies\\\\Microsoft\\\\Windows\\\\WindowsUpdate\"\r\n\r\n        # Get the domain name\r\n        try {\r\n            $domainName = (Get-CimInstance -Class Win32_ComputerSystem -ErrorAction Stop).Domain\r\n        } catch {\r\n            Write-Host -Object \"[Error] Failed to retrieve the domain name.\"\r\n            Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n            exit 1\r\n        }\r\n\r\n        # Define the GPO paths to search for Registry.pol files\r\n        if (Test-IsServer) {\r\n            # If running on a server, the local group policy folders in System32 are not populated, so use the SYSVOL path instead\r\n            $gpoFolderPaths = @(\r\n                \"\\\\$domainName\\SYSVOL\\$domainName\\Policies\\\"\r\n            )\r\n        } else {\r\n            $gpoFolderPaths = @(\r\n                \"$env:windir\\System32\\GroupPolicy\\\"\r\n                \"$env:windir\\System32\\GroupPolicyUsers\\\"\r\n            )\r\n        }\r\n\r\n        # Search for WSUS settings in group policy Registry.pol files\r\n        $gposAffectingWSUS = foreach ($folderPath in $gpoFolderPaths) {\r\n            $registryPolFiles = Get-ChildItem -Path $folderPath -Filter \"Registry.pol\" -Recurse -File -ErrorAction SilentlyContinue -ErrorVariable registryPolFileErrors\r\n\r\n            foreach ($errorInstance in $registryPolFileErrors) {\r\n                Write-Host -Object \"[Error] Error encountered while retrieving Registry.pol files from '$folderPath'.\"\r\n                Write-Host -Object \"[Error] $($errorInstance.Exception.Message)\"\r\n                $ExitCode = 1\r\n            }\r\n\r\n            # For each Registry.pol file found, read its contents and check for WSUS settings\r\n            foreach ($polFile in $registryPolFiles) {\r\n                # Read the contents of the Registry.pol file, convert to string, and remove null characters\r\n                $polContent = (Get-Content -Path $polFile.FullName -ErrorAction SilentlyContinue | Out-String) -replace \"`0\"\r\n\r\n                # If the content of the Registry.pol file contains the WSUS registry path, extract the settings\r\n                if ($polContent -match $wsusRegistryPath) {\r\n                    # Extract the GPO ID from the file path\r\n                    $GPOId = $polFile.FullName -replace \".*\\\\Policies\\\\(.*)\\\\Machine\\\\Registry.pol\", '$1'\r\n\r\n                    # Continue to the next file if the GPO ID is not in the expected format\r\n                    if ($GPOId -notmatch \"{\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}}\") {\r\n                        Write-Host -Object \"[Error] Invalid GPO ID format found in $($polFile.FullName): $GPOId\"\r\n                        $ExitCode = 1\r\n                        continue\r\n                    }\r\n\r\n                    # Define a regex pattern for capturing the WSUS settings from the Registry.pol file\r\n                    $regexPattern = \"(?&lt;disable&gt;\\*\\*del\\.)?WUServer;(.+?;){2}(?&lt;UpdateServer&gt;.+?)].+?WUStatusServer;(.+?;){2}(?&lt;StatisticsServer&gt;.+?)]\"\r\n\r\n                    # Use regex to match the WSUS settings\r\n                    $regexMatches = [regex]::Match($polContent, $regexPattern)\r\n\r\n                    # Check if GPO is disabling or enabling WSUS\r\n                    if ($regexMatches.Groups['disable'].Value) {\r\n                        $GPOStatus = \"Disabled\"\r\n                    } else {\r\n                        $GPOStatus = \"Enabled\"\r\n                    }\r\n                    \r\n                    # Extract the servers\r\n                    $WUServer = $regexMatches.Groups['UpdateServer'].Value\r\n                    $WUStatisticsServer = $regexMatches.Groups['StatisticsServer'].Value                            \r\n\r\n                    # Create a custom object with the GPO ID and WSUS settings\r\n                    [PSCustomObject]@{\r\n                        Id               = $GPOId\r\n                        GPOStatus        = $GPOStatus\r\n                        UpdateServer     = $WUServer\r\n                        StatisticsServer = $WUStatisticsServer\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        \r\n        # If GPOs were found that affect WSUS settings, filter them to only include those that are active\r\n        if ($gposAffectingWSUS) {\r\n            # Define the registry path to currently applied GPOs that use Administrative Templates\r\n            $gpoHistoryPath = \"HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History\\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}\"\r\n            \r\n            # Retrieve active GPOs on this device from the registry path\r\n            try {\r\n                $activeGPOs = Get-ChildItem -Path $gpoHistoryPath -ErrorAction Stop | ForEach-Object { Get-ItemProperty -Path $_.PSPath -Name DisplayName, GPOName -ErrorAction Stop }\r\n            } catch {\r\n                Write-Host -Object \"[Error] Failed to retrieve active GPOs from the registry.\"\r\n                Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n                exit 1\r\n            }\r\n\r\n            # Filter the GPOs that affect WSUS settings to only include those that are active\r\n            $gposAffectingWSUS = $gposAffectingWSUS | Where-Object { $_.Id -in $activeGPOs.GPOName }\r\n        }\r\n\r\n        # If any active GPOs are found that affect WSUS settings, find their display names and add them to the objects\r\n        if ($gposAffectingWSUS) {\r\n            Write-Host -Object \"[Info] Found GPOs that affect WSUS settings.\"\r\n            $gposAffectingWSUS = $gposAffectingWSUS | ForEach-Object {\r\n                $gpoId = $_.Id\r\n                $gpoDisplayName = $activeGPOs | Where-Object { $_.GPOName -eq $gpoId } | Select-Object -ExpandProperty DisplayName\r\n\r\n                [PSCustomObject]@{\r\n                    \"WSUS Settings Source\" = \"GPO\"\r\n                    \"WSUS Status\"          = $_.GPOStatus\r\n                    \"GPO Display Name\"     = $gpoDisplayName\r\n                    \"Update Server\"        = $_.UpdateServer\r\n                    \"Statistics Server\"    = $_.StatisticsServer\r\n                }\r\n            }\r\n\r\n            # Find the active WSUS settings based on the registry and GPOs\r\n            $ActiveWSUSSettings = $gposAffectingWSUS | Where-Object { $_.\"WSUS Status\" -eq $WSUSStatus }\r\n            \r\n            # If the registry settings are configured, filter the active settings to only include those that match the registry settings\r\n            if ($wsusServerFromRegistry -ne \"Not Configured\") {\r\n                $ActiveWSUSSettings = $ActiveWSUSSettings | Where-Object { $_.\"Update Server\" -eq $wsusServerFromRegistry }\r\n            }\r\n\r\n            if ($statisticsServerFromRegistry -ne \"Not Configured\") {\r\n                $ActiveWSUSSettings = $ActiveWSUSSettings | Where-Object { $_.\"Update Server\" -eq $statisticsServerFromRegistry }\r\n            }\r\n        } else {\r\n            Write-Host -Object \"[Info] No GPOs that affect WSUS settings were found.\"\r\n        }\r\n\r\n        # Validate the WSUS servers in the GPOs against the registry settings\r\n        $gposAffectingWSUS | ForEach-Object {\r\n            $UpdateServer = $_.\"Update Server\"\r\n            $StatisticsServer = $_.\"Statistics Server\"\r\n\r\n            # If both servers are empty, skip the validation\r\n            if ([string]::IsNullOrWhiteSpace($UpdateServer) -and [string]::IsNullOrWhiteSpace($StatisticsServer)) {\r\n                return\r\n            }\r\n\r\n            $displayName = $_.\"GPO Display Name\"\r\n\r\n            if (-not [string]::IsNullOrWhiteSpace($UpdateServer) -and $UpdateServer -ne $wsusServerFromRegistry) {\r\n                Write-Host -Object \"[Warning] The WSUS update server in the GPO '$DisplayName' ($UpdateServer) does not match the server in the registry ($wsusServerFromRegistry).\"\r\n            }\r\n            \r\n            if (-not [string]::IsNullOrWhiteSpace($StatisticsServer) -and $StatisticsServer -ne $statisticsServerFromRegistry) {\r\n                Write-Host -Object \"[Warning] The WSUS statistics server in the GPO '$DisplayName' ($StatisticsServer) does not match the server in the registry ($statisticsServerFromRegistry).\"\r\n            }\r\n        }\r\n    }\r\n\r\n    # Output all GPOs to the host if there are more than one\r\n    if ($gposAffectingWSUS.Count -gt 1) {\r\n        Write-Host \"`n### All GPOs affecting WSUS settings: ###`n\"\r\n        ($gposAffectingWSUS | Format-List | Out-String).Trim() | Out-Host\r\n    }\r\n\r\n    # Write output object to the activity feed\r\n    if (-not [string]::IsNullOrWhiteSpace($ActiveWSUSSettings)) {\r\n        Write-Host \"`n### Active WSUS settings: ###`n\"\r\n        ($ActiveWSUSSettings | Format-List | Out-String).Trim() | Out-Host\r\n    }\r\n\r\n    # If a custom field was specified, write to it\r\n    if ($CustomFieldName) {\r\n        # Initiate the custom field value\r\n        $customFieldValue = [System.Text.StringBuilder]::new()\r\n\r\n        # If active settings are present, format the custom field value based on the WSUS settings\r\n        if (-not [string]::IsNullOrWhiteSpace($ActiveWSUSSettings)) {\r\n            # Add the status to the custom field value\r\n            $customFieldValue.Append(\"WSUS Status: $WSUSStatus\")\r\n\r\n            # Add the servers to the custom field value\r\n            if ($wsusServerFromRegistry -eq $statisticsServerFromRegistry) {\r\n                [void]$customFieldValue.Append(\" | Update and Statistics Server: $wsusServerFromRegistry\")\r\n            } else {\r\n                [void]$customFieldValue.Append(\" | Update Server: $wsusServerFromRegistry | Statistics Server: $statisticsServerFromRegistry\")\r\n            }\r\n            \r\n            # If there are active WSUS settings from GPOs, add them to the custom field value\r\n            if ($ActiveWSUSSettings.\"WSUS Settings Source\" -eq \"GPO\") {\r\n                $gpoName = $ActiveWSUSSettings.\"GPO Display Name\"\r\n                [void]$customFieldValue.Append(\" | GPO Name: $gpoName\")\r\n            }\r\n        } else {\r\n            [void]$customFieldValue.Append(\"WSUS Status: Not Configured\")\r\n        }\r\n    \r\n        # Set the custom field\r\n        try {\r\n            $customFieldValue = $customFieldValue.ToString()\r\n            Write-Host -Object \"[Info] Setting the custom field '$CustomFieldName' with the value:`n$customFieldValue\"\r\n            Set-CustomField -Name $CustomFieldName -Value $customFieldValue -Type \"Text\" -ErrorAction Stop\r\n            Write-Host -Object \"[Info] Successfully set the custom field '$CustomFieldName'.\"\r\n        } catch {\r\n            Write-Host -Object \"[Error] Error setting the custom field '$CustomFieldName'\"\r\n            Write-Host -Object \"[Error] $($_.Exception.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    exit $ExitCode\r\n}\r\nend {\r\n    \r\n    \r\n    \r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<h2>Description d\u00e9taill\u00e9e<\/h2>\n<p>\u00c0 un niveau \u00e9lev\u00e9, le script remplit les fonctions suivantes :<\/p>\n<ol>\n<li>\n<h3>Validation et contr\u00f4le des privil\u00e8ges<\/h3>\n<ul style=\"list-style-type: disc;\">\n<li>Assure que le script est ex\u00e9cut\u00e9 avec des privil\u00e8ges d&rsquo;administrateur.<\/li>\n<li>Confirme que l&rsquo;appareil est reli\u00e9 \u00e0 un domaine pour prendre en charge les v\u00e9rifications des GPO.<\/li>\n<li>Valide le nom du champ personnalis\u00e9 s&rsquo;il est fourni.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Actualisation de la strat\u00e9gie de groupe<\/h3>\n<ul style=\"list-style-type: disc;\">\n<li>Si le domaine est joint, invoque <strong>gpupdate.exe \/force<\/strong> pour actualiser la strat\u00e9gie locale.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Inspection du registre<\/h3>\n<ul style=\"list-style-type: disc;\">\n<li>V\u00e9rifier la cl\u00e9 <strong>HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate<\/strong>.<\/li>\n<li>R\u00e9cup\u00e8re les valeurs de <strong>WUServer<\/strong>et <strong>WUStatusServer<\/strong>.<\/li>\n<li>D\u00e9termine l&rsquo;\u00e9tat de <strong>UseWUServer<\/strong> pour conclure si WSUS est activ\u00e9, d\u00e9sactiv\u00e9 ou non configur\u00e9.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Analyse de GPO<\/h3>\n<ul style=\"list-style-type: disc;\">\n<li>Examine les fichiers <strong>Registry.pol<\/strong> locaux et stock\u00e9s dans SYSVOL pour y trouver des configurations li\u00e9es \u00e0 WSUS.<\/li>\n<li>Extrait les identifiants de GPO et les compare aux GPO r\u00e9pertori\u00e9s dans le registre Windows.<\/li>\n<li>Valide les configurations GPO par rapport aux entr\u00e9es de registre et signale les divergences.<\/li>\n<\/ul>\n<\/li>\n<li>\n<h3>Rapports et sorties optionnelles<\/h3>\n<ul style=\"list-style-type: disc;\">\n<li>Formate les r\u00e9sultats dans un objet structur\u00e9.<\/li>\n<li>\u00c9crit \u00e9ventuellement les r\u00e9sultats dans un champ personnalis\u00e9 de texte NinjaOne, si <strong>-CustomFieldName<\/strong> est fourni.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2>Cas d&rsquo;utilisation potentiels<\/h2>\n<p>Imaginez une entreprise MSP qui supervise la conformit\u00e9 des correctifs pour 300 terminaux dans plusieurs domaines. Lors d&rsquo;un audit, des divergences apparaissent entre les configurations WSUS rapport\u00e9es et le comportement r\u00e9el des mises \u00e0 jour. En d\u00e9ployant ce script via <a href=\"https:\/\/www.ninjaone.com\/fr\/\">NinjaOne<\/a>, l&rsquo;entreprise MSP peut instantan\u00e9ment v\u00e9rifier :<\/p>\n<ul>\n<li>Quelles sont les machines pour lesquelles WSUS est activ\u00e9.<\/li>\n<li>Si la source de configuration est un GPO ou une modification manuelle du registre.<\/li>\n<li>S&rsquo;il y a une incoh\u00e9rence dans les URL WSUS attendues.<\/li>\n<\/ul>\n<p>Les r\u00e9sultats des champs personnalis\u00e9s peuvent \u00eatre compil\u00e9s dans un tableau de bord ou un rapport afin d&rsquo;identifier les syst\u00e8mes non conformes et d&rsquo;\u00e9tablir des priorit\u00e9s en mati\u00e8re de rem\u00e9diation.<\/p>\n<h2>Comparaisons<\/h2>\n<p>D&rsquo;autres m\u00e9thodes permettent d&rsquo;auditer les param\u00e8tres WSUS :<\/p>\n<ul>\n<li><strong>Inspection manuelle du registre<\/strong>\u00a0via <strong>regedit<\/strong> ou <strong>reg query<\/strong>.<\/li>\n<li><strong>GPMC (Group Policy Management Console)<\/strong>\u00a0pour la r\u00e9vision des GPO appliqu\u00e9s.<\/li>\n<li><strong>RSOP (Resultant Set of Policy)<\/strong>\u00a0ou <strong>gpresult<\/strong> pour le suivi des strat\u00e9gies.<\/li>\n<\/ul>\n<p>Ces approches prennent du temps, manquent d&rsquo;automatisation et ne s&rsquo;adaptent pas bien \u00e0 l&rsquo;ensemble des terminaux. En revanche, ce script PowerShell est :<\/p>\n<ul>\n<li>Enti\u00e8rement automatisable via NinjaOne.<\/li>\n<li>Capable de combiner des informations sur le registre et les GPO.<\/li>\n<li>Con\u00e7u pour fonctionner dans des environnements autonomes ou reli\u00e9s \u00e0 un domaine.<\/li>\n<\/ul>\n<h2>Questions fr\u00e9quentes<\/h2>\n<h3>Dois-je ex\u00e9cuter ce script en tant qu&rsquo;administrateur ?<\/h3>\n<p>Oui, il v\u00e9rifie l&rsquo;\u00e9l\u00e9vation et s&rsquo;arr\u00eate s&rsquo;il n&rsquo;est pas ex\u00e9cut\u00e9 avec les privil\u00e8ges appropri\u00e9s.<\/p>\n<h3>Que faire si mes param\u00e8tres WSUS ne sont pas appliqu\u00e9s via une strat\u00e9gie de groupe ?<\/h3>\n<p>Le script d\u00e9tectera toujours les configurations bas\u00e9es sur le registre et les signalera en cons\u00e9quence.<\/p>\n<h3>Puis-je l&rsquo;utiliser sans NinjaOne ?<\/h3>\n<p>Oui, bien que l&rsquo;\u00e9criture de champs personnalis\u00e9s soit optionnelle et sp\u00e9cifique \u00e0 NinjaOne, les fonctions de d\u00e9tection fonctionnent ind\u00e9pendamment.<\/p>\n<h3>Cela fonctionnera-t-il sur Windows 10 et Windows Server 2016+ ?<\/h3>\n<p>Oui. Le script cible ces syst\u00e8mes et les syst\u00e8mes sup\u00e9rieurs.<\/p>\n<h2>Implications<\/h2>\n<p>Une mauvaise configuration de WSUS peut avoir de graves cons\u00e9quences :<\/p>\n<ul>\n<li><strong>Risques pour la s\u00e9curit\u00e9 :<\/strong>\u00a0Les machines obsol\u00e8tes sont plus vuln\u00e9rables aux exploits.<\/li>\n<li><strong>Violations de la conformit\u00e9 :<\/strong>\u00a0\u00c9chec des audits en raison d&rsquo;une application irr\u00e9guli\u00e8re des correctifs.<\/li>\n<li><strong>Frais g\u00e9n\u00e9raux d&rsquo;exploitation :<\/strong>\u00a0Les v\u00e9rifications manuelles consomment un temps pr\u00e9cieux pour les \u00e9quipes informatiques.<\/li>\n<\/ul>\n<p>En faisant appara\u00eetre la source et l&rsquo;\u00e9tat des param\u00e8tres WSUS, le script att\u00e9nue ces risques et favorise une gestion proactive de l&rsquo;infrastructure.<\/p>\n<h2>Recommandations<\/h2>\n<ul>\n<li><strong>Ex\u00e9cutez p\u00e9riodiquement via l&rsquo;automatisation RMM<\/strong>\u00a0pour garantir une conformit\u00e9 continue.<\/li>\n<li><strong>D\u00e9finissez le nom du champ personnalis\u00e9 explicitement<\/strong>\u00a0pour maintenir un rapport uniforme.<\/li>\n<li><strong>Validez les conflits de GPO<\/strong>\u00a0en utilisant les avertissements g\u00e9n\u00e9r\u00e9s par le script.<\/li>\n<li><strong>Incluez dans votre script dans l&rsquo;onboarding<\/strong>\u00a0pour les nouvelles machines.<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>WSUS joue un r\u00f4le central dans toute strat\u00e9gie de <a href=\"https:\/\/www.ninjaone.com\/fr\/blog\/qu-est-ce-que-la-gestion-des-correctifs-patch-management\/\">gestion des correctifs<\/a>, mais s&rsquo;assurer qu&rsquo;il est configur\u00e9 correctement n\u00e9cessite une visibilit\u00e9 plus approfondie que celle qu&rsquo;offrent souvent les outils natifs. Ce script PowerShell fournit une solution compl\u00e8te et \u00e9volutive pour auditer les configurations WSUS sur l&rsquo;ensemble de votre parc informatique.<\/p>\n<p>Pour les MSP et les administrateurs informatiques qui utilisent NinjaOne, l&rsquo;int\u00e9gration de ce script dans leur bo\u00eete \u00e0 outils d&rsquo;automatisation apporte une valeur ajout\u00e9e imm\u00e9diate. Il transforme un contr\u00f4le manuel fastidieux en une action optimis\u00e9e, pouvant faire l&rsquo;objet d&rsquo;un rapport, ce qui renforce \u00e0 la fois la conformit\u00e9 et la confiance dans vos pratiques de gestion de l&rsquo;infrastructure.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"no","_lmt_disable":""},"operating_system":[4212],"use_cases":[4287],"class_list":["post-530396","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/script_hub\/530396","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/comments?post=530396"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/media?parent=530396"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/operating_system?post=530396"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/use_cases?post=530396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}