Private/Kinds/UserProfileElevated.ps1
|
# The UserProfileElevated Kind: the User Profiles of the machine, read with admin rights. # # The UserProfile Kind runs in the Main Part, in the Session of the User, and the profile # folder of another account does not open for a User: how large it is stays unread. This # Kind lists the same User Profiles with admin rights, measures the folder of each, and # judges nothing: the UserProfile Check is handed its reading as # $Observed['UserProfileElevated'] and fills in what it could not read itself. # # Of a User Profile the account, the kind, when it was last used, whether it is loaded, # and one size: that of the profile folder as a whole (ADR-0006). No folder below it is # told apart, no file is named or opened, and files are not counted. Where a User Profile # lies and what Windows keeps of it in the registry is read, used for the measuring and # the kind, and not kept: what this Kind gathers is written to disk and handed to the # Main Part, and holds what a Report may hold of another User and no more. See # ConvertTo-UserProfileOtherEntry. # # Its one Finding says that the reading was taken, so that the Check is accounted for in # the Report like any other. $script:UserProfileElevatedNeedsAdmin = $true function Get-UserProfileElevatedData { <# .SYNOPSIS Every User Profile of a person on the machine and how large its folder is, as an administrator may read it. Decides nothing. .DESCRIPTION Listed as the UserProfile Kind lists them, by the same function, so that the two readings have one shape and one can fill in the other. Measured by the code that measures the folders of the own User Profile: see Initialize-UserProfileNativeMethod for what it follows and what it never opens. OtherMeasureSeconds (60) is how long the profile folders are measured for, all of them together. A rule of thumb and no limit of Windows: a minute is enough for a handful of User Profiles on a solid-state drive, and on a terminal server with a hundred of them no time is that anybody would wait for. What is not measured by then is said to be unmeasured, User Profile by User Profile: the one the time ran out in has a lower bound, those after it no number. Never more than ten minutes, whatever a Check Definition says. The Elevated Part is given this much longer: see Get-ElevatedExtraTimeout. Those that are not loaded are measured first. They are the ones a Technician may remove, and so the ones whose size is asked for. #> [CmdletBinding()] [OutputType([psobject])] param([hashtable]$Parameters = @{}) $seconds = ConvertTo-Number (Get-Parameter $Parameters 'OtherMeasureSeconds' 60) if ($null -eq $seconds) { $seconds = 60 } $seconds = [int][math]::Min(600, [math]::Max(1, $seconds)) # As Windows lists them, with where each lies: for the measuring, and no further. $read = @(Get-UserProfileOtherReading) $sizes = @{} try { $folders = @($read | Sort-Object @{ Expression = { [bool]$_.Loaded } }, Sid | ForEach-Object { [pscustomobject]@{ Id = $_.Sid; Path = $_.LocalPath } }) Measure-UserProfileFolder -Folder $folders -ProfilePath '' -Seconds $seconds | ForEach-Object { $sizes["$($_.Id)"] = $_ } } catch { $sizes = @{} } # What is kept, and what crosses to the Main Part: see ConvertTo-UserProfileOtherEntry. $profiles = @(foreach ($entry in $read) { ConvertTo-UserProfileOtherEntry -Row $entry -Size $sizes[$entry.Sid] -Measured }) [pscustomobject]@{ PSTypeName = 'Gutcheck.Data.UserProfileElevated' Profiles = $profiles OtherMeasureSeconds = $seconds GatheredAt = Get-Date } } function ConvertTo-UserProfileElevatedFinding { <# .SYNOPSIS One Finding saying how many User Profiles were read with admin rights. Pure. .DESCRIPTION No judgement: which of them count as unused, and whether that matters, is the UserProfile Check's to judge, with the limits of its Definition. #> [CmdletBinding()] [OutputType([psobject])] param([AllowNull()]$Data, [hashtable]$Parameters = @{}) $profiles = @((Get-DataCollection $Data 'Profiles') | ForEach-Object { $_ }) if (-not $profiles.Count) { return New-UnavailableFinding -Category User -Check (Get-Text 'Check.UserProfileElevated.Reading') ` -Hint (Get-Text 'Hint.UserProfile.Repeat') } $measured = @($profiles | Where-Object { "$(Get-DataProperty $_ 'SizeState')" -in 'Complete', 'CutShort' }).Count New-Finding -Category User -Check (Get-Text 'Check.UserProfileElevated.Reading') -Severity OK ` -Value ((Get-Text 'Value.UserProfileElevated.Reading') -f $profiles.Count, $measured) } |