{"id":238922,"date":"2024-04-19T05:29:32","date_gmt":"2024-04-19T05:29:32","guid":{"rendered":"https:\/\/www.ninjaone.com\/?post_type=script_hub&#038;p=238922"},"modified":"2024-04-19T05:34:24","modified_gmt":"2024-04-19T05:34:24","slug":"monitorare-il-tempo-di-attivita-in-windows","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaonesandbox.dev\/it\/script-hub\/monitorare-il-tempo-di-attivita-in-windows\/","title":{"rendered":"Massimizza l&#8217;efficienza dell\u2019IT: Guida approfondita allo script PowerShell per monitorare il tempo di attivit\u00e0 in Windows"},"content":{"rendered":"<h2>Punti chiave<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"1\"><strong>Monitoraggio automatico del tempo di attivit\u00e0<\/strong>: Lo script PowerShell automatizza il processo di monitoraggio del tempo di attivit\u00e0 dei dispositivi Windows, offrendo un&#8217;alternativa pi\u00f9 efficiente ai controlli manuali.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><strong>Reportistica dettagliata<\/strong>: Fornisce report approfonditi sulle percentuali del tempo di attivit\u00e0, sugli eventi di avvio e su intervalli di tempo specifici, favorendo un monitoraggio preciso del sistema.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><strong>Intervalli di tempo personalizzabili<\/strong>: Gli utenti possono specificare periodi di tempo personalizzati per l&#8217;analisi, migliorando la flessibilit\u00e0 dello script per le diverse esigenze di monitoraggio.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><strong>Capacit\u00e0 di integrazione<\/strong>: Lo script per monitorare il tempo di attivit\u00e0 in Windows supporta l&#8217;output in campi personalizzati, consentendo l&#8217;integrazione con strumenti di gestione IT come NinjaOne.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><strong>Manutenzione proattiva<\/strong>: L&#8217;uso regolare contribuisce alla manutenzione proattiva del sistema, identificando i potenziali problemi prima che si aggravino.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"1\"><strong>Sicurezza ed efficienza<\/strong>: Il monitoraggio dei trend del tempo di attivit\u00e0 \u00e8 fondamentale sia per la sicurezza informatica che per l&#8217;efficienza operativa.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"7\" data-aria-level=\"1\"><strong>Strumento complementare<\/strong>: Ideale per integrare le soluzioni di gestione IT esistenti e fornire una panoramica completa dell\u2019integrit\u00e0 del sistema.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"8\" data-aria-level=\"1\"><strong>Accessibilit\u00e0 e convenienza<\/strong>: Lo script \u00e8 accessibile a professionisti IT di diversi livelli di competenza e aggiunge convenienza ai controlli di routine del sistema.<\/li>\n<\/ul>\n<h2>Introduzione<\/h2>\n<p>La misurazione del <a href=\"https:\/\/www.ninjaonesandbox.dev\/it\/it-hub\/gestione-dei-servizi-it\/tempi-di-attivita-e-di-inattivita-uptime-downtime\/\">tempo di attivit\u00e0 di un dispositivo<\/a> \u00e8 fondamentale nel panorama IT. Sapere per quanto tempo i sistemi hanno funzionato senza essere riavviati pu\u00f2 aiutare a mantenere le prestazioni ottimali e a risolvere i problemi. Uno script PowerShell in grado di calcolare e riportare con precisione il tempo di attivit\u00e0 dei dispositivi Windows \u00e8 uno strumento di valore per i professionisti IT.<\/p>\n<h2>Background<\/h2>\n<p>Lo script in questione \u00e8 progettato per monitorare e riportare la percentuale del tempo di attivit\u00e0 di un dispositivo Windows, compresi i dettagli sugli eventi di avvio. Questo aspetto \u00e8 particolarmente importante per i professionisti IT e per i <a href=\"https:\/\/www.ninjaonesandbox.dev\/it\/cos-e-un-msp\">fornitori di servizi gestiti (MSP)<\/a>, in quanto contribuisce alla manutenzione proattiva e alla risposta rapida ai problemi del sistema. La capacit\u00e0 di determinare con precisione la disponibilit\u00e0 dei dispositivi in un periodo specifico \u00e8 essenziale in vari scenari, dai controlli di manutenzione ordinaria all&#8217;identificazione di potenziali guasti del sistema.<\/p>\n<h2>Lo script per monitorare il tempo di attivit\u00e0 in Windows:<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 4.0\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Get the Uptime percentage of a Windows device and show a list of boot events.\r\n.DESCRIPTION\r\n    Get the Uptime percentage of a Windows device and show a list of boot events.\r\n\r\n    Unexpected Shutdowns can skew results slightly.\r\n\r\n    Duration in results is in days.\r\n.Example\r\n    (No Parameters)\r\n\r\n    WARNING: No time frame specified. Checking uptime percentage for the last 30 days\r\n    Creating uptime entries based on event logs...\r\n    Uptime entries created!\r\n    WARNING: Estimating unexpected shutdown times. This will not be 100% accurate.\r\n\r\n    Oldest uptime record: 06\/29\/2023 22:24:01\r\n\r\n    Filtering uptime records to your time frame...\r\n    Calculating uptime during time frame...\r\n\r\n    ### Time Frame ###\r\n    Start Date: 12\/26\/2023 19:39:38\r\n    End Date: 01\/25\/2024 19:39:38\r\n\r\n    ### Statistics ###\r\n    Percentage Online: 3.93%\r\n    Total Time Frame: 30d\r\n    Total Uptime: 1d 4h 19m 14s\r\n\r\n    ### Uptime Entries ###\r\n\r\n    BootType     BootTime             ShutdownTime Duration     \r\n    --------     --------             ------------ --------     \r\n    Current Boot 1\/24\/2024 3:20:23 PM              1d 4h 19m 14s\r\n.EXAMPLE\r\n    -Days 30\r\n\r\n    WARNING: No time frame specified. Checking uptime percentage for the last 30 days\r\n    Creating uptime entries based on event logs...\r\n    Uptime entries created!\r\n    WARNING: Estimating unexpected shutdown times. This will not be 100% accurate.\r\n\r\n    Oldest uptime record: 06\/29\/2023 22:24:01\r\n\r\n    Filtering uptime records to your time frame...\r\n    Calculating uptime during time frame...\r\n\r\n    ### Time Frame ###\r\n    Start Date: 12\/26\/2023 19:39:38\r\n    End Date: 01\/25\/2024 19:39:38\r\n\r\n    ### Statistics ###\r\n    Percentage Online: 3.93%\r\n    Total Time Frame: 30d\r\n    Total Uptime: 1d 4h 19m 14s\r\n\r\n    ### Uptime Entries ###\r\n\r\n    BootType     BootTime             ShutdownTime Duration     \r\n    --------     --------             ------------ --------     \r\n    Current Boot 1\/24\/2024 3:20:23 PM              1d 4h 19m 14s\r\n.EXAMPLE\r\n    -StartDay \"2023-07-01T00:00:00.000-07:00\" -EndDay \"2023-07-31T00:00:00.000-07:00\"\r\n\r\n    Creating uptime entries based on event logs...\r\n    Uptime entries created!\r\n    WARNING: Estimating unexpected shutdown times. This will not be 100% accurate.\r\n\r\n    Oldest uptime record: 06\/29\/2023 22:24:01\r\n\r\n    Filtering uptime records to your time frame...\r\n    Calculating uptime during time frame...\r\n\r\n    ### Time Frame ###\r\n    Start Date: 07\/01\/2023 00:00:00\r\n    End Date: 07\/31\/2023 00:00:00\r\n\r\n    ### Statistics ###\r\n    Percentage Online: 89%\r\n    Total Time Frame: 30d\r\n    Total Uptime: 26d 16h 49m 17s\r\n\r\n    ### Uptime Entries ###\r\n\r\n    BootType            BootTime              ShutdownTime           Duration       \r\n    --------            --------              ------------           --------       \r\n    Normal              7\/26\/2023 12:16:34 PM 12\/21\/2023 11:24:17 AM 147d 23h 7m 42s\r\n    Normal              7\/26\/2023 11:52:47 AM 7\/26\/2023 12:16:26 PM  23m 39s        \r\n    Normal              7\/26\/2023 11:22:46 AM 7\/26\/2023 11:52:40 AM  29m 53s        \r\n    Normal              7\/26\/2023 10:55:08 AM 7\/26\/2023 11:22:38 AM  27m 29s        \r\n    Unexpected Shutdown 7\/26\/2023 10:42:45 AM 7\/26\/2023 10:53:16 AM  10m 30s        \r\n    Normal              7\/24\/2023 11:09:01 AM 7\/24\/2023 11:35:43 AM  26m 42s        \r\n    Normal              7\/24\/2023 10:45:38 AM 7\/24\/2023 11:08:53 AM  23m 15s        \r\n    Normal              7\/24\/2023 9:50:52 AM  7\/24\/2023 9:58:47 AM   7m 54s         \r\n    Normal              7\/24\/2023 8:08:34 AM  7\/24\/2023 8:10:16 AM   1m 41s         \r\n    Normal              7\/20\/2023 5:26:15 PM  7\/24\/2023 8:08:26 AM   3d 14h 42m 11s \r\n    Normal              7\/20\/2023 5:21:09 PM  7\/20\/2023 5:26:08 PM   4m 59s         \r\n    Normal              7\/20\/2023 4:08:28 PM  7\/20\/2023 5:21:02 PM   1h 12m 33s     \r\n    Unexpected Shutdown 6\/29\/2023 10:41:23 PM 7\/19\/2023 10:35:01 AM  19d 11h 53m 38s\r\n\r\nPARAMETER: -Days \"replaceMeWithANumber\"\r\n    Gets the uptime for the past X days.\r\n\r\nPARAMETER: -StartDay \"2023-07-01T00:00:00.000-07:00\"\r\n    Gets the uptime starting from the specified day.\r\n\r\nPARAMETER: -EndDay \"2023-07-31T00:00:00.000-07:00\"\r\n    Gets the uptime ending on the specified day.\r\n\r\nPARAMETER: -WysiwygCustomField \"The name of your selected custom field.\"\r\n    Outputs the results to a WYSIWYG custom field.\r\n\r\nPARAMETER: -PercentageCustomField \"The name of a text custom field\"\r\n    Outputs the results to a text custom field.\r\n\r\nPARAMETER: -EstimateUnexpectedShutdown\r\n    Tells the script to estimate the shutdown time and date using the last known eventlog for that range.\r\n.OUTPUTS\r\n    PSObject\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 8, Windows Server 2012\r\n    Release Notes: Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaonesandbox.dev\/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#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [Parameter()]\r\n    [int]$Days,\r\n    [Parameter()]\r\n    $StartDay,\r\n    [Parameter()]\r\n    $EndDay,\r\n    [Parameter()]\r\n    [string]$WysiwygCustomField,\r\n    [Parameter()]\r\n    [String]$PercentageCustomField,\r\n    [Parameter()]\r\n    [Switch]$EstimateUnexpectedShutdown = [System.Convert]::ToBoolean($env:estimateUnexpectedShutdownTime)\r\n)\r\n\r\nbegin {\r\n    if ($env:uptimeForThePastXDays -and $env:uptimeForThePastXDays -notlike \"null\") { $Days = $env:uptimeForThePastXDays }\r\n    if ($env:startDay -and $env:startDay -notlike \"null\") { $StartDay = $env:startDay }\r\n    if ($env:endDay -and $env:endDay -notlike \"null\") { $EndDay = $env:endDay }\r\n    if ($env:wysiwygCustomFieldName -and $env:wysiwygCustomFieldName -notlike \"null\") { $WysiwygCustomField = $env:wysiwygCustomFieldName }\r\n    if ($env:percentageCustomFieldName -and $env:percentageCustomFieldName -notlike \"null\") { $PercentageCustomField = $env:percentageCustomFieldName }\r\n\r\n    if ($StartDay -and $EndDay) {\r\n        $StartDay = Get-Date -Date $StartDay\r\n        $EndDay = Get-Date -Date $EndDay\r\n    }\r\n\r\n    if ($Days -and ($StartDay -or $EndDay)) { Write-Host \"[Error] You cannot use 'The Past X Days' and 'Start Day' or 'End Day' at the same time\"; exit 1 }\r\n    if (-not $Days -and -not $StartDay -and -not $EndDay) { Write-Warning \"No time frame specified. Checking uptime percentage for the last 30 days\"; $Days = 30 }\r\n    if (($StartDay -and -not $EndDay) -or ($EndDay -and -not $StartDay)) { Write-Host \"[Error] Start Day must be used with End Day.\"; exit 1 }\r\n    if ($StartDay -and $StartDay -ge $EndDay) { Write-Host \"[Error] Start Day must be before End Day\"; exit 1 }\r\n\r\n    if ($Days) {\r\n        $StartDay = (Get-Date).AddDays(-$Days)\r\n        $EndDay = Get-Date\r\n    }\r\n\r\n    function ConvertFrom-TimeSpan {\r\n        [CmdletBinding()]\r\n        [OutputType([string[]])]\r\n        param(\r\n            [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]\r\n            [TimeSpan[]]$TimeSpan\r\n        )\r\n        process {\r\n            $Days = if ($($_.Days)) { \"$($_.Days)d\" }else { \"\" }\r\n            $Hours = if ($($_.Hours)) { \"$($_.Hours)h\" }else { \"\" }\r\n            $Minutes = if ($($_.Minutes)) { \"$($_.Minutes)m\" }else { \"\" }\r\n            $Seconds = if ($($_.Seconds)) { \"$($_.Seconds)s\" }else { \"\" }\r\n            \"$($(@($Days, $Hours, $Minutes, $Seconds) | Select-Object -Unique) -join ' ')\".Trim()\r\n        }\r\n    }\r\n\r\n    function Set-NinjaProperty {\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        )\r\n    \r\n        $Characters = $Value | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n        if ($Characters -ge 10000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded, value is greater than 10,000 characters.\")\r\n        }\r\n        \r\n        # If we're requested to set the field value for a Ninja document we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n        \r\n        # This is a list of valid fields that can be set. If no type is given, it will be assumed that the input doesn't need to be changed.\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        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        # The field below requires additional information to be set\r\n        $NeedsOptions = \"Dropdown\"\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\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        # If an error is received it will have an exception property, the function will exit with that error information.\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # The below type's require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # While it's highly likely we were given a value like \"True\" or a boolean datatype it's better to be safe than sorry.\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Ninjarmm-cli expects the GUID of the option to be selected. Therefore, the given value will be matched with a GUID.\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                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a 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                if (-not $Selection) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            default {\r\n                # All the other types shouldn't require additional work on the input.\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.\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            $CustomField = Ninja-Property-Set -Name $Name -Value $NinjaValue 2&gt;&amp;1\r\n        }\r\n        \r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n    $ExitCode = 0\r\n}\r\nprocess {\r\n    if (\r\n        $PSCmdlet.ParameterSetName -like \"StartEndDays\" -and $StartDay -ge $EndDay -or\r\n        $($StartDay -and $EndDay -and $StartDay -ge $EndDay)\r\n    ) {\r\n        Write-Error \"StartDay must be less than EndDay.\"\r\n        exit 1\r\n    }\r\n    \r\n    # Gathers all the event logs pertaining to startup and shutdowns\r\n    $eventFilter = @{\r\n        LogName      = 'System'\r\n        ProviderName = @('Microsoft-Windows-Kernel-General', 'Microsoft-Windows-Eventlog')\r\n        ID           = 12, 13, 6008\r\n    }\r\n    $Events = Get-WinEvent -FilterHashtable $eventFilter\r\n\r\n    $BootEntries = New-Object System.Collections.Generic.List[object]\r\n    $i = 0\r\n    $BootTime = $null\r\n    $ShutdownTime = $null\r\n\r\n    Write-Host \"Creating uptime entries based on event logs...\"\r\n    $Events | ForEach-Object {\r\n        # If this is the first event it is for our current boot\r\n        if ($i -eq 0) {\r\n            $BootEntries.Add(\r\n                [PSCustomObject]@{\r\n                    BootType     = \"Current Boot\"\r\n                    BootTime     = $_.TimeCreated\r\n                    ShutdownTime = $null\r\n                    Duration     = if ((((Get-Date) - $EndDay).TotalDays -lt 1)) { New-TimeSpan -Start $_.TimeCreated -End $EndDay }else { (New-TimeSpan -Start $_.TimeCreated -End $(Get-Date)) }\r\n                }\r\n            )\r\n            $i++\r\n            return\r\n        }\r\n\r\n        # Check to see if the next event is either an Unexpected Shutdown or a Startup Entry\r\n        if ($_.Id -eq 13 -and ($Events[$($i + 1)].Id -eq 12 -or $Events[$($i + 1)].Id -eq 6008)) {\r\n            $ShutdownTime = $_.TimeCreated\r\n            $BootTime = $Events[$($i + 1)].TimeCreated\r\n        }\r\n\r\n        # Check to see if the previous entry was something other than shutdown and the next event is a shutdown event.\r\n        if ($_.Id -eq 12 -and ($Events[$($i - 1)].Id -ne 13) -and ($Events[$($i + 1)].Id -eq 13)) {\r\n            # There's no end record for unexpected shutdowns so we'll need to record that\r\n            $BootEntries.Add(\r\n                [PSCustomObject]@{\r\n                    BootType     = \"Unexpected Shutdown\"\r\n                    BootTime     = $_.TimeCreated\r\n                    ShutdownTime = $null\r\n                    Duration     = $null\r\n                }\r\n            )\r\n        }\r\n\r\n        # If there are no special cases record the information\r\n        if ($BootTime -and $ShutdownTime) {\r\n            $BootEntries.Add(\r\n                [PSCustomObject]@{\r\n                    BootType     = \"Normal\"\r\n                    BootTime     = $BootTime\r\n                    ShutdownTime = $ShutdownTime\r\n                    Duration     = (New-TimeSpan -Start $BootTime -End $ShutdownTime)\r\n                }\r\n            )\r\n            $BootTime = $null\r\n            $ShutdownTime = $null\r\n        }\r\n\r\n        $i++\r\n    }\r\n\r\n    Write-Host \"Uptime entries created!\"\r\n\r\n    # Warn about unexpected shutdown's effect on the report\r\n    if ($BootEntries.BootType -contains \"Unexpected Shutdown\" -and -not $EstimateUnexpectedShutdown) {\r\n        Write-Warning \"There are unexpected shutdowns in your boot history (may or may not be within your timeframe).\" \r\n        Write-Warning \"Unexpected shutdowns do NOT have a shutdown time and will be excluded from all calculations.\"\r\n    }\r\n    elseif ($BootEntries.BootType -contains \"Unexpected Shutdown\") {\r\n        # If requested to estimate the shutdown time. Estimate it based on the last event log prior to the next bootup.\r\n        Write-Warning \"Estimating unexpected shutdown times. This will not be 100% accurate.\"\r\n        $entry = 0\r\n        $BootEntries | ForEach-Object {\r\n            if ($_.BootType -ne \"Unexpected Shutdown\") {\r\n                $entry++\r\n                return\r\n            }\r\n\r\n            $EventFilter = @{\r\n                LogName   = \"*\"\r\n                StartTime = $_.BootTime\r\n                EndTime   = $BootEntries[$($entry - 1)].BootTime\r\n            }\r\n\r\n            # We only want one event to minimize impact on performance\r\n            $LastEvent = Get-WinEvent -FilterHashtable $EventFilter -MaxEvents 1\r\n            $_.ShutdownTime = $LastEvent.TimeCreated\r\n            $_.Duration = (New-TimeSpan -Start $_.BootTime -End $LastEvent.TimeCreated)\r\n            $entry++\r\n        }\r\n    }\r\n\r\n    Write-Host \"`nOldest uptime record: $($BootEntries | Select-Object -ExpandProperty BootTime -Last 1)`n\"\r\n\r\n    # We now have all the information needed to decide what uptime records should be output.\r\n    Write-Host \"Filtering uptime records to your time frame...\"\r\n    $ReportableBootEntries = New-Object System.Collections.Generic.List[object]\r\n    $BootEntries | ForEach-Object {\r\n        if ($_.Duration) {\r\n            $_.Duration = $_.Duration | ConvertFrom-TimeSpan\r\n        }\r\n\r\n        if ( $_.ShutdownTime -and $_.ShutdownTime -le $EndDay -and $_.ShutdownTime -ge $StartDay) {\r\n            $ReportableBootEntries.Add($_)\r\n            return\r\n        }\r\n\r\n        if ( $_.BootType -eq \"Current Boot\" -and $_.BootTime -le $StartDay -and $_.BootTime -le $EndDay ) {\r\n            $ReportableBootEntries.Add($_)\r\n            return\r\n        }\r\n\r\n        if ( $_.BootTime -and $_.BootTime -ge $StartDay -and $_.BootTime -le $EndDay) {\r\n            $ReportableBootEntries.Add($_)\r\n            return\r\n        }\r\n    }\r\n\r\n    # Now let's use our information to calculate the total amount of time the system has been online in the time range.\r\n    Write-Host \"Calculating uptime during time frame...\"\r\n    $ReportableBootEntries | ForEach-Object {\r\n        # If the current boot is in the time range we'll need to use the End Date as the ending time frame.\r\n        if ($_.BootType -eq \"Current Boot\" -and $_.BootTime -gt $StartDay) {\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $_.BootTime -End $EndDay)\r\n            return\r\n        }\r\n        elseif ($_.BootType -eq \"Current Boot\") {\r\n            # If the boot time is older than the start date we'll use the start date.\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $StartDay -End $EndDay)\r\n            return\r\n        }\r\n\r\n        # If we're missing the information required to make these calculations we should skip it.\r\n        if (-not $_.BootTime -or -not $_.ShutdownTime) {\r\n            return\r\n        }\r\n\r\n        # If the uptime entry is in our time range we can add it straight in.\r\n        if ($_.BootTime -ge $StartDay -and $_.ShutdownTime -le $EndDay) {\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $_.BootTime -End $_.ShutdownTime)\r\n            return\r\n        }\r\n\r\n        # If the uptime entry starts to early then we need to use the start day as the starting point.\r\n        if ($_.BootTime -le $StartDay -and $_.ShutdownTime -le $EndDay) {\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $StartDay -End $_.ShutdownTime)\r\n            return\r\n        }\r\n\r\n        # If the uptime entry goes too long than we need to use the end date as a reference.\r\n        if ($_.ShutdownTime -ge $EndDay -and $_.BootTime -ge $StartDay) {\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $_.BootTime -End $EndDay)\r\n            return\r\n        }\r\n\r\n        # If the uptime entry is both before the start day and after the end day we'll use both the start and end day.\r\n        if ($_.ShutdownTime -ge $EndDay -and $_.BootTime -le $StartDay) {\r\n            $TotalTimeOnline = $TotalTimeOnline + (New-TimeSpan -Start $StartDay -End $EndDay)\r\n            return\r\n        }\r\n    }\r\n\r\n    # We're now ready to output our results to the activity log\r\n    Write-Host \"\"\r\n\r\n    $TotalTimeFrame = (New-TimeSpan -Start $StartDay -End $EndDay)\r\n    Write-Host \"### Time Frame ###\"\r\n    Write-Host \"Start Date: $StartDay\"\r\n    Write-Host \"End Date: $EndDay`n\"\r\n\r\n    # For the percentage we'll take the total number of seconds it was online for and divide it by the total number of seconds possible\r\n    $Percentage = $([math]::Round(($TotalTimeOnline.TotalSeconds \/ $TotalTimeFrame.TotalSeconds * 100), 2))\r\n    Write-Host \"### Statistics ###\"\r\n    Write-Host \"Percentage Online: $Percentage%\"\r\n    Write-Host \"Total Time Frame: $($TotalTimeFrame | ConvertFrom-TimeSpan)\"\r\n    if ($TotalTimeOnline) {\r\n        $HumanFriendlyTotalUptime = $($TotalTimeOnline | ConvertFrom-Timespan)\r\n    }\r\n    else {\r\n        $HumanFriendlyTotalUptime = \"0d 0h 0m 0s\"\r\n    }\r\n    Write-Host \"Total Uptime: $HumanFriendlyTotalUptime\"\r\n\r\n    # Let's output our table as well\r\n    Write-Host \"`n### Uptime Entries ###\"\r\n    $ReportableBootEntries | Format-Table -AutoSize | Out-String | Write-Host\r\n\r\n    if ($PercentageCustomField) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$PercentageCustomField'.\"\r\n            Set-NinjaProperty -Name $PercentageCustomField -Value \"$Percentage%\"\r\n            Write-Host \"Successfully set Custom Field '$PercentageCustomField'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.Message)\"\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    if ($WysiwygCustomField) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$WysiwygCustomField'.\"\r\n            $htmlReport = New-Object System.Collections.Generic.List[String]\r\n            $htmlReport.Add(@\"\r\n&lt;h1&gt;Uptime Statistics&lt;\/h1&gt;\r\n&lt;ul class=\"unstyled\"&gt;&lt;strong&gt;Percentage Online:&lt;\/strong&gt; $Percentage%&lt;\/ul&gt;\r\n&lt;ul class=\"unstyled\"&gt;&lt;strong&gt;Uptime (In Range):&lt;\/strong&gt; $HumanFriendlyTotalUptime&lt;\/ul&gt;\r\n&lt;ul class=\"unstyled\"&gt;&lt;strong&gt;Range:&lt;\/strong&gt; $($StartDay.ToShortDateString()) - $($EndDay.ToShortDateString())&lt;\/ul&gt;\r\n\"@)\r\n            $htmlTable = $ReportableBootEntries | ConvertTo-Html -Fragment \r\n            $htmlTable = $htmlTable -replace \"&lt;tr&gt;&lt;td&gt;Current Boot&lt;\/td&gt;\", '&lt;tr class=\"success\"&gt;&lt;td&gt;Current Boot&lt;\/td&gt;'\r\n            $htmlTable = $htmlTable -replace \"&lt;tr&gt;&lt;td&gt;Normal&lt;\/td&gt;\", '&lt;tr class=\"other\"&gt;&lt;td&gt;Normal&lt;\/td&gt;'\r\n            $htmlTable = $htmlTable -replace \"&lt;tr&gt;&lt;td&gt;Unexpected Shutdown&lt;\/td&gt;\", '&lt;tr class=\"danger\"&gt;&lt;td&gt;Unexpected Shutdown&lt;\/td&gt;'\r\n            $htmlTable | ForEach-Object { $htmlReport.Add($_) }\r\n            Set-NinjaProperty -Name $WysiwygCustomField -Value ($htmlReport | Out-String)\r\n            Write-Host \"Successfully set Custom Field '$WysiwygCustomField'!\"\r\n        }\r\n        catch {\r\n            Write-Host \"[Error] $($_.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<div class=\"in-context-cta\"><p>Accedi a oltre 700 script nel Dojo NinjaOne<\/p>\n<p><a href=\"https:\/\/www.ninjaonesandbox.dev\/it\/prova-gratuita\/\">Ottieni l&#8217;accesso<\/a><\/p>\n<\/div>\n<h2>Analisi dettagliata<\/h2>\n<p>Lo script per monitorare il tempo di attivit\u00e0 in Windows opera in diverse fasi:<\/p>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"1\"><strong>Inizializzazione dei parametri:<\/strong> Accetta parametri come il numero di giorni, date specifiche di inizio e fine e nomi di campi personalizzati per l&#8217;output.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><strong>Controllo dell&#8217;ambiente:<\/strong> Regola i parametri in base alle variabili dell\u2019ambiente, se disponibili.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><strong>Convalida:<\/strong> Assicura che i parametri di ingresso siano coerenti e validi dal punto di vista logico.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><strong>Analisi del registro eventi:<\/strong> Lo script recupera i registri degli eventi del sistema per identificare gli eventi di avvio e arresto.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><strong>Calcolo del tempo di attivit\u00e0:<\/strong> Calcola il tempo di attivit\u00e0 analizzando la durata degli eventi di avvio e arresto.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"1\"><strong>Generazione di report:<\/strong> Genera un report dettagliato che include la percentuale del tempo di attivit\u00e0, il periodo totale e le singole voci di avvio.<\/li>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"7\" data-aria-level=\"1\"><strong>Output in forma di campo personalizzato:<\/strong> I risultati possono essere inviati a campi personalizzati specificati per l&#8217;integrazione con altri strumenti come NinjaOne.<\/li>\n<\/ul>\n<h2>Casi d&#8217;uso potenziali<\/h2>\n<p>Considera un responsabile IT che supervisiona una rete di dispositivi Windows in un ambiente aziendale. Utilizzano questo script per monitorare l&#8217;affidabilit\u00e0 del sistema, in particolare dopo la distribuzione di un aggiornamento significativo. Esaminando le statistiche sui tempi di attivit\u00e0, possono affrontare in modo proattivo eventuali problemi di instabilit\u00e0 o identificare i dispositivi che richiedono manutenzione.<\/p>\n<h2>Confronti<\/h2>\n<p>Solitamente il tempo di attivit\u00e0 viene spesso controllato manualmente tramite Gestione attivit\u00e0 o gli strumenti System Information di Windows. Tuttavia, questo script automatizza il processo, fornisce informazioni pi\u00f9 dettagliate e consente l&#8217;analisi cronologica su intervalli di tempo personalizzati, rendendolo pi\u00f9 efficiente e completo.<\/p>\n<h2>Domande frequenti<\/h2>\n<p><strong>D1: Lo script per monitorare il tempo di attivit\u00e0 in Windows \u00e8 in grado di generare report su sistemi remoti? \u00a0<\/strong><br \/>\nR1: S\u00ec, se viene eseguito in un ambiente di rete con privilegi di accesso adeguati.<\/p>\n<p><strong>D2: \u00c8 possibile programmare l&#8217;esecuzione automatica di questo script? \u00a0<\/strong><br \/>\nR2: S\u00ec, lo script pu\u00f2 essere pianificato utilizzando l&#8217;Utilit\u00e0 di pianificazione delle attivit\u00e0 di Windows o strumenti simili.<\/p>\n<p><strong>D3: Quanto \u00e8 precisa la stima dell&#8217;arresto imprevisto? \u00a0<\/strong><br \/>\nR3: Fornisce una stima basata sull&#8217;ultimo registro eventi presente, che potrebbe non essere accurata al 100% ma offre un&#8217;approssimazione vicina.<\/p>\n<h2>Implicazioni<\/h2>\n<p>La comprensione del tempo di attivit\u00e0 dei dispositivi \u00e8 fondamentale per la sicurezza e l&#8217;efficienza dell&#8217;IT. Un tempo di attivit\u00e0 continuo per periodi prolungati potrebbe indicare la mancanza di aggiornamenti importanti o patch, con conseguente rischio per la sicurezza. Al contrario, frequenti riavvii potrebbero segnalare un&#8217;instabilit\u00e0 di fondo del sistema.<\/p>\n<h2>Raccomandazioni<\/h2>\n<p>Le best practice includono la pianificazione regolare dello script per un monitoraggio costante, la personalizzazione dei campi di output per l&#8217;integrazione con gli strumenti di gestione IT e l&#8217;integrazione dello script con altri strumenti di monitoraggio per un&#8217;analisi completa del sistema.<\/p>\n<h2>Considerazioni finali<\/h2>\n<p>L&#8217;integrazione di questo script PowerShell in una suite di gestione IT come NinjaOne migliora la capacit\u00e0 di monitorare e mantenere l\u2019integrit\u00e0 del sistema in modo efficiente. La <a href=\"https:\/\/www.ninjaonesandbox.dev\/it\/\">piattaforma completa di NinjaOne<\/a> integra le funzionalit\u00e0 dello script, fornendo una visione panoramica dell\u2019integrit\u00e0 e delle prestazioni della rete.<\/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":[4273],"class_list":["post-238922","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/script_hub\/238922","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/comments?post=238922"}],"wp:attachment":[{"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/media?parent=238922"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/operating_system?post=238922"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaonesandbox.dev\/it\/wp-json\/wp\/v2\/use_cases?post=238922"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}