{"id":534749,"date":"2025-09-30T18:14:58","date_gmt":"2025-09-30T18:14:58","guid":{"rendered":"https:\/\/www.ninjaone.com\/?post_type=script_hub&#038;p=534749"},"modified":"2025-09-30T18:14:58","modified_gmt":"2025-09-30T18:14:58","slug":"rapports-sur-l-indice-de-fiabilite-windows-avec-powershell","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/fr\/script-hub\/rapports-sur-l-indice-de-fiabilite-windows-avec-powershell\/","title":{"rendered":"Comment g\u00e9n\u00e9rer des rapports sur l&rsquo;indice de fiabilit\u00e9 Windows avec PowerShell"},"content":{"rendered":"<p>Pour les professionnels de l&rsquo;informatique et les fournisseurs de services g\u00e9r\u00e9s (MSP), il est essentiel de conna\u00eetre la stabilit\u00e9 des syst\u00e8mes. Le suivi de la fiabilit\u00e9 au fil du temps permet une maintenance proactive du syst\u00e8me, une analyse des tendances et de meilleurs r\u00e9sultats en mati\u00e8re d&rsquo;assistance. Un outil sous-utilis\u00e9 mais puissant \u00e0 cet effet est l&rsquo;indice de fiabilit\u00e9 de Windows, qui fournit un score de stabilit\u00e9 quantifiable bas\u00e9 sur les journaux d&rsquo;\u00e9v\u00e9nements. Cet article explique comment cr\u00e9er un <strong>rapport sur l&rsquo;indice de fiabilit\u00e9 Windows avec PowerShell<\/strong>, ce qui vous permet d&rsquo;\u00e9valuer, d&rsquo;enregistrer et m\u00eame de publier ces scores par le biais de champs personnalis\u00e9s dans une plateforme telle que NinjaOne.<\/p>\n<h2>Contexte<\/h2>\n<p>L&rsquo;indice de fiabilit\u00e9 de Windows existe depuis Windows Vista et continue d&rsquo;\u00eatre une mesure utile pour d\u00e9terminer <a href=\"https:\/\/www.ninjaone.com\/fr\/blog\/rapport-de-diagnostic-pc\/\">l&rsquo;\u00e9tat g\u00e9n\u00e9ral du syst\u00e8me<\/a>. Il analyse les \u00e9v\u00e9nements critiques tels que les pannes d&rsquo;application, les d\u00e9faillances mat\u00e9rielles et les mises \u00e0 jour de Windows, et attribue une note de stabilit\u00e9 quotidienne allant de 1 (instable) \u00e0 10 (tr\u00e8s stable).<\/p>\n<p>Malgr\u00e9 son utilit\u00e9, il n&rsquo;existe pas d&rsquo;automatisation int\u00e9gr\u00e9e permettant de r\u00e9cup\u00e9rer et d&rsquo;afficher ces valeurs dans un format de rapport convivial, surtout s&rsquo;il est int\u00e9gr\u00e9 \u00e0 une plateforme de gestion des terminaux. C&rsquo;est l\u00e0 que ce script intervient. Con\u00e7u pour les environnements utilisant <strong>PowerShell 5.1 et NinjaOne<\/strong>, le script automatise la r\u00e9cup\u00e9ration, le formatage et la publication optionnelle des donn\u00e9es de l&rsquo;indice de fiabilit\u00e9 dans des champs personnalis\u00e9s, offrant ainsi une visibilit\u00e9 imm\u00e9diate et un suivi \u00e0 long terme.<\/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    Returns the last score and a daily average report of the Windows Reliability Index.\r\n.DESCRIPTION\r\n    Returns the last score and a daily average report of the Windows Reliability Index.\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.EXAMPLE\r\n    (No Parameters)\r\n\r\n    [Info] Retrieving reliability index information for SRV19-TEST.\r\n    [Info] Successfully retrieved reliability index information!\r\n\r\n    [Info] Latest reliability index score for SRV19-TEST:\r\n    2\/19\/2025 1:00:00 PM | 6.835\r\n\r\n    [Info] Table of daily averages:\r\n\r\n    Date      Average Reliability Index\r\n    ----      -------------------------\r\n    2\/19\/2025                      8.26\r\n    2\/18\/2025                        10\r\n    2\/17\/2025                        10\r\n    2\/16\/2025                        10\r\n    2\/15\/2025                        10\r\n    2\/14\/2025                        10\r\n    2\/13\/2025                        10\r\n    2\/12\/2025                        10\r\n    2\/11\/2025                        10\r\n    2\/10\/2025                        10\r\n    2\/9\/2025                         10\r\n    2\/8\/2025                         10\r\n    2\/7\/2025                         10\r\n    2\/6\/2025                         10\r\n    2\/5\/2025                         10\r\n    2\/4\/2025                         10\r\n    2\/3\/2025                         10\r\n    2\/2\/2025                         10\r\n    2\/1\/2025                         10\r\n    1\/31\/2025                        10\r\n    1\/30\/2025                        10\r\n    1\/29\/2025                        10\r\n    1\/28\/2025                        10\r\n    1\/27\/2025                        10\r\n    1\/26\/2025                        10\r\n    1\/25\/2025                        10\r\n    1\/24\/2025                        10\r\n    1\/23\/2025                        10\r\n    1\/22\/2025                        10\r\n    1\/21\/2025                        10\r\n    1\/20\/2025                        10\r\n    1\/19\/2025                        10\r\n\r\n.PARAMETER -WYSIWYGCustomFieldName \"ReplaceMeWithAnyWYSIWYGCustomField\"\r\n    Name of the WYSIWYG custom field to populate with the report.\r\n\r\n.EXAMPLE\r\n    -WYSIWYGCustomFieldName \"ExampleInput\"\r\n\r\n    [Info] Retrieving reliability index information for SRV19-TEST.\r\n    [Info] Successfully retrieved reliability index information!\r\n\r\n    [Info] Retrieving current value of WYSIWYG Custom Field 'WYSIWYG'.\r\n    [Info] Successfully retrieved the current value of 'WYSIWYG'.\r\n\r\n    [Info] Publishing Reliability Index daily average table to WYSIWYG Custom Field 'WYSIWYG'.\r\n    [Info] Successfully set 'WYSIWYG' Custom Field!\r\n\r\n    [Info] Latest reliability index score for SRV19-TEST:\r\n    2\/19\/2025 1:00:00 PM | 6.835\r\n\r\n    [Info] Table of daily averages:\r\n\r\n    Date      Average Reliability Index\r\n    ----      -------------------------\r\n    2\/19\/2025                      8.26\r\n    2\/18\/2025                        10\r\n    2\/17\/2025                        10\r\n    2\/16\/2025                        10\r\n    2\/15\/2025                        10\r\n    2\/14\/2025                        10\r\n    2\/13\/2025                        10\r\n    2\/12\/2025                        10\r\n    2\/11\/2025                        10\r\n    2\/10\/2025                        10\r\n    2\/9\/2025                         10\r\n    2\/8\/2025                         10\r\n    2\/7\/2025                         10\r\n    2\/6\/2025                         10\r\n    2\/5\/2025                         10\r\n    2\/4\/2025                         10\r\n    2\/3\/2025                         10\r\n    2\/2\/2025                         10\r\n    2\/1\/2025                         10\r\n    1\/31\/2025                        10\r\n    1\/30\/2025                        10\r\n    1\/29\/2025                        10\r\n    1\/28\/2025                        10\r\n    1\/27\/2025                        10\r\n    1\/26\/2025                        10\r\n    1\/25\/2025                        10\r\n    1\/24\/2025                        10\r\n    1\/23\/2025                        10\r\n    1\/22\/2025                        10\r\n    1\/21\/2025                        10\r\n    1\/20\/2025                        10\r\n    1\/19\/2025                        10\r\n\r\n.PARAMETER -TextCustomFieldName \"ReplaceMeWithAnyTextCustomField\"\r\n    Name of the Text custom field to populate with the most recent reliability index score.\r\n    \r\n.EXAMPLE\r\n    -TextCustomFieldName \"ReplaceMeWithAnyMultilineCustomField\"\r\n\r\n    [Info] Retrieving reliability index information for SRV19-TEST.\r\n    [Info] Successfully retrieved reliability index information!\r\n\r\n    [Info] Retrieving current value of Text Custom Field 'Text'.\r\n    [Info] Successfully retrieved the current value of 'Text'.\r\n\r\n    [Info] Publishing the latest reliability index score to Text Custom Field 'Text'.\r\n    [Info] Successfully set 'Text' Custom Field to value '2\/19\/2025 1:00:00 PM | 6.835'!\r\n\r\n    [Info] Latest reliability index score for SRV19-TEST:\r\n    2\/19\/2025 1:00:00 PM | 6.835\r\n\r\n    [Info] Table of daily averages:\r\n\r\n    Date      Average Reliability Index\r\n    ----      -------------------------\r\n    2\/19\/2025                      8.26\r\n    2\/18\/2025                        10\r\n    2\/17\/2025                        10\r\n    2\/16\/2025                        10\r\n    2\/15\/2025                        10\r\n    2\/14\/2025                        10\r\n    2\/13\/2025                        10\r\n    2\/12\/2025                        10\r\n    2\/11\/2025                        10\r\n    2\/10\/2025                        10\r\n    2\/9\/2025                         10\r\n    2\/8\/2025                         10\r\n    2\/7\/2025                         10\r\n    2\/6\/2025                         10\r\n    2\/5\/2025                         10\r\n    2\/4\/2025                         10\r\n    2\/3\/2025                         10\r\n    2\/2\/2025                         10\r\n    2\/1\/2025                         10\r\n    1\/31\/2025                        10\r\n    1\/30\/2025                        10\r\n    1\/29\/2025                        10\r\n    1\/28\/2025                        10\r\n    1\/27\/2025                        10\r\n    1\/26\/2025                        10\r\n    1\/25\/2025                        10\r\n    1\/24\/2025                        10\r\n    1\/23\/2025                        10\r\n    1\/22\/2025                        10\r\n    1\/21\/2025                        10\r\n    1\/20\/2025                        10\r\n    1\/19\/2025                        10\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    [Parameter()]\r\n    [string]$WYSIWYGCustomFieldName,\r\n\r\n    [Parameter()]\r\n    [string]$TextCustomFieldName\r\n)\r\n\r\nbegin {\r\n\r\n    if ($env:WYSIWYGCustomFieldName){\r\n        $WYSIWYGCustomFieldName = $env:WYSIWYGCustomFieldName\r\n    }\r\n\r\n    if ($env:TextCustomFieldName){\r\n        $TextCustomFieldName = $env:TextCustomFieldName\r\n    }\r\n\r\n    # if custom field input is only spaces or a blank string, set it to null\r\n    # otherwise, trim any whitespace on the ends\r\n    if ([string]::IsNullOrWhiteSpace($WYSIWYGCustomFieldName)){\r\n        $WYSIWYGCustomFieldName = $null\r\n    }\r\n    else{\r\n        $WYSIWYGCustomFieldName = $WYSIWYGCustomFieldName.Trim()\r\n    }\r\n\r\n    if ([string]::IsNullOrWhiteSpace($TextCustomFieldName)){\r\n        $TextCustomFieldName = $null\r\n    }\r\n    else{\r\n        $TextCustomFieldName = $TextCustomFieldName.Trim()\r\n    }\r\n\r\n    # test custom field for invalid characters\r\n    if ($WYSIWYGCustomFieldName -match \"[^0-9A-Z]\"){\r\n        Write-Host \"[Error] WYSIWYG Custom Field Name contains invalid character(s). Writing to the WYSIWYG Custom Field will be skipped.\"\r\n        Write-Host \"[Error] https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/360060920631-Custom-Field-Setup\"\r\n        $WYSIWYGCustomFieldName = $null\r\n        $ExitCode = 1\r\n        Write-Host \"\"\r\n    }\r\n\r\n    if ($TextCustomFieldName -match \"[^0-9A-Z]\"){\r\n        Write-Host \"[Error] Text Custom Field Name contains invalid character(s). Writing to the Text Custom Field will be skipped.\"\r\n        Write-Host \"[Error] https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/360060920631-Custom-Field-Setup\"\r\n        $TextCustomFieldName = $null\r\n        $ExitCode = 1\r\n        Write-Host \"\"\r\n    }\r\n\r\n    function Get-CustomField {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n        \r\n        # Initialize a hashtable for 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 types that require options to be retrieved\r\n        $NeedsOptions = \"DropDown\", \"MultiSelect\"\r\n        \r\n        # If a document name is provided, retrieve the property value from the document\r\n        if ($DocumentName) {\r\n            # Throw an error if the type is \"Secure\", as it's not a valid type in this context\r\n            if ($Type -Like \"Secure\") { throw [System.ArgumentOutOfRangeException]::New(\"$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            # Notify the user that the value is being retrieved from a Ninja document\r\n            Write-Host \"Retrieving value from Ninja Document...\"\r\n            $NinjaPropertyValue = Ninja-Property-Docs-Get -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n        \r\n            # If the property type requires options, retrieve them\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 no document name is provided, retrieve the property value directly\r\n            $NinjaPropertyValue = Ninja-Property-Get -Name $Name 2&gt;&amp;1\r\n    \r\n            # If the property type requires options, retrieve them\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 exception if there was an error retrieving the property value or options\r\n        if ($NinjaPropertyValue.Exception) { throw $NinjaPropertyValue }\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # Handle the property value based on its type\r\n        switch ($Type) {\r\n            \"Attachment\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Checkbox\" {\r\n                # Convert the value to a boolean\r\n                [System.Convert]::ToBoolean([int]$NinjaPropertyValue)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Convert a Unix timestamp to local date and time\r\n                $UnixTimeStamp = $NinjaPropertyValue\r\n                $UTC = (Get-Date \"1970-01-01 00:00:00\").AddSeconds($UnixTimeStamp)\r\n                $TimeZone = [TimeZoneInfo]::Local\r\n                [TimeZoneInfo]::ConvertTimeFromUtc($UTC, $TimeZone)\r\n            }\r\n            \"Decimal\" {\r\n                # Convert the value to a double (floating-point number)\r\n                [double]$NinjaPropertyValue\r\n            }\r\n            \"Device Dropdown\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Device MultiSelect\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Dropdown\" {\r\n                # Convert options to a CSV format and match the GUID to retrieve the display name\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Options | Where-Object { $_.GUID -eq $NinjaPropertyValue } | Select-Object -ExpandProperty Name\r\n            }\r\n            \"Integer\" {\r\n                # Convert the value to an integer\r\n                [int]$NinjaPropertyValue\r\n            }\r\n            \"MultiSelect\" {\r\n                # Convert options to a CSV format, then match and return selected items\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = ($NinjaPropertyValue -split ',').trim()\r\n        \r\n                foreach ($Item in $Selection) {\r\n                    $Options | Where-Object { $_.GUID -eq $Item } | Select-Object -ExpandProperty Name\r\n                }\r\n            }\r\n            \"Organization Dropdown\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Organization Location Dropdown\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Organization Location MultiSelect\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Organization MultiSelect\" {\r\n                # Convert JSON formatted property value to a PowerShell object\r\n                $NinjaPropertyValue | ConvertFrom-Json\r\n            }\r\n            \"Time\" {\r\n                # Convert the value from seconds to a time format in the local timezone\r\n                $Seconds = $NinjaPropertyValue\r\n                $UTC = ([timespan]::fromseconds($Seconds)).ToString(\"hh\\:mm\\:ss\")\r\n                $TimeZone = [TimeZoneInfo]::Local\r\n                $ConvertedTime = [TimeZoneInfo]::ConvertTimeFromUtc($UTC, $TimeZone)\r\n        \r\n                Get-Date $ConvertedTime -DisplayHint Time\r\n            }\r\n            default {\r\n                # For any other types, return the raw value\r\n                $NinjaPropertyValue\r\n            }\r\n        }\r\n    }\r\n\r\n    function Set-CustomField {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$DocumentName,\r\n            [Parameter()]\r\n            [Switch]$Piped\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        # 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 = \"Attachment\", \"Checkbox\", \"Date\", \"Date or Date Time\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \"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\"\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                $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            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                Write-Host -Object \"[Error] Failed to set custom field.\"\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 Test-IsElevated {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)\r\n    }\r\n}\r\nprocess {\r\n    if (-not (Test-IsElevated)) {\r\n        Write-Host -Object \"[Error] Access Denied. Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    $ExitCode = 0\r\n\r\n    # retrieve reliability index metrics\r\n    try{\r\n        Write-Host \"[Info] Retrieving reliability index information for $env:computername.\"\r\n        $reliabilityMetrics = Get-CimInstance Win32_ReliabilityStabilityMetrics | Sort-Object TimeGenerated -Descending\r\n        Write-Host \"[Info] Successfully retrieved reliability index information!`n\"\r\n    }\r\n    catch{\r\n        Write-Host \"[Error] Error retrieving reliability index information.\"\r\n        Write-Host \"[Error] $($_.Exception.Message)\"\r\n        exit 1\r\n    }\r\n\r\n    # if any metrics are present, continue with script\r\n    # otherwise, error out with a message that no information is available\r\n    if ($reliabilityMetrics){\r\n        # get unique dates from the metrics\r\n        $dates = $reliabilityMetrics | Group-Object {$_.TimeGenerated.ToShortDateString()}\r\n\r\n        # create table with averages of each dates' score, sorted by date (most recent to oldest)\r\n        $reliabilityIndexTable = $(foreach ($currentDate in $dates){\r\n            [PSCustomObject]@{\r\n                Date = $currentDate.Name\r\n                \"Average Reliability Index\" = [Math]::Round(($currentDate.Group.SystemStabilityIndex | Measure-Object -Average).Average,2)\r\n            }\r\n        }) | Sort-Object {[datetime]::Parse($_.Date)} -Descending\r\n\r\n        # get the most recent time and score\r\n        $currentIndexDate = ($reliabilityMetrics | Select-Object -First 1).EndMeasurementDate.ToString()\r\n        $currentIndexScore = ($reliabilityMetrics | Select-Object -First 1).SystemStabilityIndex\r\n\r\n        # above values will be written to the Text Custom Field and output to the activity feed using the below formatted string\r\n        $latestIndexInfo = \"$currentIndexDate | $currentIndexScore\"\r\n\r\n        # write to WYSIWYG Custom Field if provided\r\n        if ($WYSIWYGCustomFieldName){\r\n            # convert report to HTML table\r\n            $report = $reliabilityIndexTable | ConvertTo-HTML -Fragment\r\n\r\n            # attempt to get the current value of the field, to determine if it already matches the report\r\n            try{\r\n                Write-Host \"[Info] Retrieving current value of WYSIWYG Custom Field '$WYSIWYGCustomFieldName'.\"\r\n                # output will be in JSON format for this type of field, need to first convert it to an object, and we want to compare the HTML so that is extracted into the variable\r\n                $currentValue = (Get-CustomField $WYSIWYGCustomFieldName | ConvertFrom-JSON).HTML\r\n                Write-Host \"[Info] Successfully retrieved the current value of '$WYSIWYGCustomFieldName'.`n\"\r\n            }\r\n            catch{\r\n                Write-Host \"[Error] Error retrieving current value of '$WYSIWYGCustomFieldName'.\"\r\n                Write-Host \"[Error] $($_.Exception.Message)`n\"\r\n                # an error occurred while getting the current value of the custom field, so we will skip writing to it\r\n                $skipWYSIWYGCFWrite = $true\r\n                $ExitCode = 1\r\n            }\r\n\r\n            # check if the current value of the field is the same as the report. if so, output a message and do not try to write to the field again\r\n            if ($currentValue -eq $report){\r\n                Write-Host \"[Info] WYSIWYG Custom Field '$WYSIWYGCustomFieldName' already has the latest information.`n\"\r\n            }\r\n            # otherwise, continue with writing to the custom field unless there was an error retrieving the current value above\r\n            elseif (-not ($skipWYSIWYGCFWrite)){\r\n                try{\r\n                    Write-Host \"[Info] Publishing Reliability Index daily average table to WYSIWYG Custom Field '$WYSIWYGCustomFieldName'.\"\r\n                    Set-CustomField -Name $WYSIWYGCustomFieldName -Value $report -Type \"WYSIWYG\"\r\n                    Write-Host \"[Info] Successfully set '$WYSIWYGCustomFieldName' Custom Field!`n\"\r\n                }\r\n                catch{\r\n                    Write-Host \"[Error] Error setting '$WYSIWYGCustomFieldName'.\"\r\n                    Write-Host \"[Error] $($_.Exception.Message)`n\"\r\n                    $ExitCode = 1\r\n                }\r\n            }\r\n        }\r\n\r\n        # write to Text custom field if provided\r\n        if ($TextCustomFieldName){\r\n            # attempt to retrieve current value of the text custom field\r\n            try{\r\n                Write-Host \"[Info] Retrieving current value of Text Custom Field '$TextCustomFieldName'.\"\r\n                $currentValue = Get-CustomField $TextCustomFieldName\r\n                Write-Host \"[Info] Successfully retrieved the current value of '$TextCustomFieldName'.`n\"\r\n            }\r\n            catch{\r\n                Write-Host \"[Error] Error retrieving current value of '$TextCustomFieldName'.\"\r\n                Write-Host \"[Error] $($_.Exception.Message)`n\"\r\n                # an error occurred while getting the current value of the custom field, so we will skip writing to it\r\n                $skipTextCFWrite = $true\r\n                $ExitCode = 1\r\n            }\r\n\r\n            if ($currentValue -eq $latestIndexInfo){\r\n                Write-Host \"[Info] Text Custom Field '$TextCustomFieldName' already has the latest information.`n\"\r\n            }\r\n            elseif (-not ($skipTextCFWrite)){\r\n                try{\r\n                    Write-Host \"[Info] Publishing the latest reliability index score to Text Custom Field '$TextCustomFieldName'.\"\r\n                    Set-CustomField -Name $TextCustomFieldName -Value $latestIndexInfo -Type \"Text\"\r\n                    Write-Host \"[Info] Successfully set '$TextCustomFieldName' Custom Field to value '$latestIndexInfo'!`n\"\r\n                }\r\n                catch{\r\n                    Write-Host \"[Error] Error setting '$TextCustomFieldName' to value '$latestIndexInfo'.\"\r\n                    Write-Host \"[Error] $($_.Exception.Message)`n\"\r\n                    $ExitCode = 1\r\n                }\r\n            }\r\n        }\r\n\r\n        # output information to the activity feed\r\n        Write-Host \"[Info] Latest reliability index score for $env:computername`:\"\r\n        $latestIndexInfo | Out-Host\r\n        Write-Host \"`n[Info] Table of daily averages:\"\r\n        $reliabilityIndexTable | Out-Host\r\n    }\r\n    else{\r\n        Write-Host \"[Error] Reliability index information could not be found on this machine.\"\r\n        exit 1\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>Voici comment fonctionne le script, \u00e9tape par \u00e9tape :<\/p>\n<ol>\n<li><strong>Traitement des param\u00e8tres<\/strong>\u00a0:\n<ul>\n<li>Accepte deux param\u00e8tres facultatifs : <code>-WYSIWYGCustomFieldName<\/code> et <code>-TextCustomFieldName<\/code>.<\/li>\n<li>Ils d\u00e9terminent si les r\u00e9sultats doivent \u00eatre publi\u00e9s dans les champs personnalis\u00e9s WYSIWYG (format HTML) ou Texte de NinjaOne.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Gestion des variables d&rsquo;environnement<\/strong> :\n<ul>\n<li>Si ces param\u00e8tres sont transmis en tant que variables d&rsquo;environnement (ce qui est courant dans les scripts de t\u00e2ches RMM), ils sont captur\u00e9s et valid\u00e9s.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Logique de validation<\/strong>:\n<ul>\n<li>Permet de s&rsquo;assurer que les noms des champs personnalis\u00e9s ne contiennent que des caract\u00e8res valides.<\/li>\n<li>Il supprime les espaces blancs et ignore les entr\u00e9es non valides.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Recherche d&rsquo;indices de fiabilit\u00e9<\/strong>:\n<ul>\n<li>Utilise <code>Get-CimInstance<\/code> pour interroger <code>Win32_ReliabilityStabilityMetrics<\/code>.<\/li>\n<li>Agr\u00e9ge les mesures dans un tableau de moyennes journali\u00e8res, tri\u00e9es avec les plus r\u00e9centes en haut.<\/li>\n<li>Extrait le dernier score enregistr\u00e9 et l&rsquo;horodatage.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Logique d&rsquo;\u00e9dition<\/strong>:\n<ul>\n<li>Si un champ WYSIWYG est sp\u00e9cifi\u00e9 :\n<ul>\n<li>Convertit le tableau en fragment HTML.<\/li>\n<li>Compare le contenu actuel et le nouveau contenu avant la mise \u00e0 jour afin d&rsquo;\u00e9viter les \u00e9critures redondantes.<\/li>\n<\/ul>\n<\/li>\n<li>Si un champ Text est sp\u00e9cifi\u00e9 :\n<ul>\n<li>Publie le score le plus r\u00e9cent sous forme de cha\u00eene de caract\u00e8res (par exemple, <code>2\/19\/2025 1:00:00 PM | 6.835<\/code>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Journalisation et sortie<\/strong>:\n<ul>\n<li>Des messages <code>[Info]<\/code> et <code>[Error]<\/code> d\u00e9taill\u00e9s sont fournis \u00e0 des fins de transparence et de d\u00e9pannage.<\/li>\n<li>Affiche le score actuel et l&rsquo;historique de fiabilit\u00e9 dans le flux d&rsquo;activit\u00e9.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2>Cas d&rsquo;utilisation potentiels<\/h2>\n<h3>\u00c9tude de cas\u00a0: Jane, ing\u00e9nieur syst\u00e8me chez MSP<\/h3>\n<p>Jane g\u00e8re plus de 500 <a href=\"https:\/\/www.ninjaone.com\/blog\/endpoint-devices-explained-with-examples\/\">terminaux<\/a> dans divers environnements clients. Pour identifier de mani\u00e8re proactive les machines pr\u00e9sentant des probl\u00e8mes de stabilit\u00e9, elle d\u00e9ploie ce script PowerShell via le module d&rsquo;automatisation de NinjaOne :<\/p>\n<ul>\n<li>Les syst\u00e8mes qui obtiennent un score inf\u00e9rieur \u00e0 8 pendant plusieurs jours cons\u00e9cutifs d\u00e9clenchent l&rsquo;envoi d&rsquo;un ticket via les webhooks.<\/li>\n<li>Les champs WYSIWYG contiennent des rapports format\u00e9s pour les r\u00e9sum\u00e9s ex\u00e9cutifs.<\/li>\n<li>Les champs de texte permettent de saisir le dernier score, qui s&rsquo;int\u00e8gre aux tableaux de bord.<\/li>\n<\/ul>\n<p>Cette approche permet \u00e0 Jane de d\u00e9tecter les tendances \u00e0 la baisse de la stabilit\u00e9 avant qu&rsquo;elles n&rsquo;affectent les utilisateurs, am\u00e9liorant ainsi la conformit\u00e9 aux accords de niveau de service (SLA) et la satisfaction des clients.<\/p>\n<h2>Comparaisons<\/h2>\n<table>\n<tbody>\n<tr>\n<td><strong>M\u00e9thode<\/strong><\/td>\n<td><strong>Avantages<\/strong><\/td>\n<td><strong>Inconv\u00e9nients<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Utilisation manuelle de l&rsquo;interface graphique du moniteur de fiabilit\u00e9<\/td>\n<td>Simple, aucune connaissance en mati\u00e8re de script n&rsquo;est requise<\/td>\n<td>Chronophage, pas d&rsquo;exportation ni d&rsquo;automatisation<\/td>\n<\/tr>\n<tr>\n<td>Filtrage du journal des \u00e9v\u00e9nements<\/td>\n<td>Contr\u00f4le granulaire<\/td>\n<td>Complexe et non synth\u00e9tique<\/td>\n<\/tr>\n<tr>\n<td><strong>Ce script PowerShell<\/strong><\/td>\n<td>Automatis\u00e9, convivial, int\u00e9gr\u00e9 \u00e0 NinjaOne<\/td>\n<td>N\u00e9cessite PowerShell 5.1+, droits d&rsquo;administrateur<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Par rapport aux m\u00e9thodes traditionnelles, ce script offre une <strong>approche optimis\u00e9e, reproductible et int\u00e9gr\u00e9e<\/strong> pour contr\u00f4ler la fiabilit\u00e9 sur de nombreux terminaux.<\/p>\n<h2>Questions fr\u00e9quentes<\/h2>\n<p><strong>Q\u00a0: Sur quoi se base l&rsquo;indice de fiabilit\u00e9 de Windows ?<\/strong><strong><br \/>\n<\/strong>A\u00a0: Il regroupe les journaux d&rsquo;\u00e9v\u00e9nements Windows, les pannes, les mises \u00e0 jour et les erreurs mat\u00e9rielles.<\/p>\n<p><strong>Q\u00a0: Puis-je l&rsquo;utiliser sans NinjaOne ?<\/strong><strong><br \/>\n<\/strong>A\u00a0: Oui, le rapport de fiabilit\u00e9 sera toujours g\u00e9n\u00e9r\u00e9 et imprim\u00e9, mais la publication de champs personnalis\u00e9s est sp\u00e9cifique aux environnements NinjaOne.<\/p>\n<p><strong>Q\u00a0: \u00c0 quelle fr\u00e9quence ce script doit-il \u00eatre ex\u00e9cut\u00e9 ?<\/strong><strong><br \/>\n<\/strong>A\u00a0: Quotidiennement ou hebdomadairement, en fonction de la volatilit\u00e9 de votre environnement.<\/p>\n<p><strong>Q\u00a0: Que se passe-t-il si aucune donn\u00e9e de fiabilit\u00e9 n&rsquo;est trouv\u00e9e ?<\/strong><strong><br \/>\n<\/strong>A\u00a0: Le script se termine par un message d&rsquo;erreur indiquant qu&rsquo;aucune donn\u00e9e n&rsquo;est disponible.<\/p>\n<h2>Implications<\/h2>\n<p>En centralisant et en automatisant le suivi de la fiabilit\u00e9 des syst\u00e8mes, les professionnels de l&rsquo;informatique disposent d&rsquo;un <strong>syst\u00e8me d&rsquo;alerte pr\u00e9coce en cas de d\u00e9gradation du syst\u00e8me<\/strong>. Des scores constamment bas peuvent signaler des probl\u00e8mes plus importants, tels que des conflits de pilotes ou un mat\u00e9riel d\u00e9faillant, qui pourraient autrement passer inaper\u00e7us. Ce script favorise \u00e9galement la <strong>prise de d\u00e9cision fond\u00e9e sur des donn\u00e9es<\/strong>, en particulier lorsqu&rsquo;il est li\u00e9 \u00e0 des syst\u00e8mes de ticketing et d&rsquo;alerte.<\/p>\n<h2>Recommandations<\/h2>\n<ul>\n<li><strong>Programmez des ex\u00e9cutions r\u00e9guli\u00e8res<\/strong> via le <a href=\"https:\/\/www.ninjaone.com\/fr\/script-hub\/taches-planifiees-powershell\/\">planificateur de t\u00e2ches<\/a> ou l&rsquo;automatisation RMM afin de maintenir les enregistrements \u00e0 jour.<\/li>\n<li><strong>D\u00e9finissez des seuils<\/strong> pour d\u00e9clencher des alertes ou des actions d&rsquo;assistance.<\/li>\n<li><strong>Utilisez des conventions de d\u00e9nomination significatives<\/strong> pour vos champs personnalis\u00e9s afin d&rsquo;\u00e9viter les erreurs de configuration.<\/li>\n<li><strong>Testez sur quelques syst\u00e8mes<\/strong> avant de passer \u00e0 des environnements de production.<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>La cr\u00e9ation d&rsquo;un rapport sur l&rsquo;indice de fiabilit\u00e9 Windows avec PowerShell est un moyen efficace d&rsquo;obtenir une visibilit\u00e9 sur la stabilit\u00e9 des terminaux g\u00e9r\u00e9s. Ce script, associ\u00e9 \u00e0 NinjaOne, vous permet de <strong>stocker, de formater et de contr\u00f4ler les scores de fiabilit\u00e9<\/strong> d&rsquo;une mani\u00e8re qui s&rsquo;aligne sur les pratiques modernes d&rsquo;automatisation informatique. Pour les MSP qui souhaitent offrir un service proactif et de qualit\u00e9, cette solution ajoute \u00e0 leur bo\u00eete \u00e0 outils un outil de surveillance \u00e0 faible co\u00fbt et \u00e0 forte valeur ajout\u00e9e.<\/p>\n<p>En permettant la cr\u00e9ation de rapports de fiabilit\u00e9 automatis\u00e9s gr\u00e2ce \u00e0 des champs personnalis\u00e9s, NinjaOne aide les \u00e9quipes informatiques \u00e0 combler le manque de visibilit\u00e9 et \u00e0 am\u00e9liorer les r\u00e9sultats op\u00e9rationnels, le tout \u00e0 partir d&rsquo;un guichet unique.<\/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":[4281],"class_list":["post-534749","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows","use_cases-configuration-generale"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/script_hub\/534749","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=534749"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/media?parent=534749"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/operating_system?post=534749"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/fr\/wp-json\/wp\/v2\/use_cases?post=534749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}