internal/functions/Test-ElevationRequirement.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle#

function Test-ElevationRequirement {
    <#
        .SYNOPSIS
            Command that tests, whether the process runs elevated and has to run as such.
 
        .DESCRIPTION
            Command that tests, whether the process runs elevated and has to run as such.
            Some commands require to be run elevated, when executed against localhost, but not when run against a remote computer.
            This command handles that test and manages the reaction to it.
 
        .PARAMETER ComputerName
            The computer that is being targeted by the calling command.
            This must be a localhost variety, for it to be able to fail.
 
        .PARAMETER Continue
            When using the native capability to terminate on fail, this will call continue in non-EnableException mode.
 
        .PARAMETER ContinueLabel
            When using the native capability to terminate on fail, and using a continue mode, the continue will continue with this label.
 
        .PARAMETER SilentlyContinue
            When using the native capability to terminate on fail, this will call continue in EnableException mode.
 
        .PARAMETER NoStop
            Does not call stop-function when the test fails, rather only returns $false instead
 
        .PARAMETER EnableException
            By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
            This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
            Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
 
        .EXAMPLE
            $null = Test-ElevationRequirement -ComputerName $instance -Continue
 
            This will test whether the currently processed instance is localhost and the process is running elevated.
            If it should have elevation but is not running with elevation:
            - In silent mode it will termiante with an exception
            - In default mode, it will continue with the next instance
 
        .EXAMPLE
            if (-not ( Test-ElevationRequirement -ComputerName $instance -NoStop)) {
                # Do whatever
            }
 
        This will test whether the currently processed instance is localhost and the process is running elevated.
        If it isn't running elevated but should be, the overall condition will be met and the if-block is executed.
    #>

    [CmdletBinding(DefaultParameterSetName = 'Stop')]
    param (
        [DbaInstanceParameter]
        $ComputerName,

        [Parameter(ParameterSetName = 'Stop')]
        [switch]
        $Continue,

        [Parameter(ParameterSetName = 'Stop')]
        [string]
        $ContinueLabel,

        [Parameter(ParameterSetName = 'Stop')]
        [switch]
        $SilentlyContinue,

        [Parameter(ParameterSetName = 'NoStop')]
        [switch]
        $NoStop,

        [bool]
        [Alias('Silent')]
        $EnableException = $EnableException
    )

    $isElevated = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    $testResult = $true
    if ($ComputerName.IsLocalHost -and (-not $isElevated)) { $testResult = $false }

    if ($PSCmdlet.ParameterSetName -like "NoStop") {
        return $testResult
    } elseif ($PSCmdlet.ParameterSetName -like "Stop") {
        if ($testResult) { return $testResult }

        $splatStopFunction = @{
            Message = "Console not elevated, but elevation is required to perform some actions on localhost for this command."
        }

        if (Test-Bound "Continue") { $splatStopFunction["Continue"] = $Continue }
        if (Test-Bound "ContinueLabel") { $splatStopFunction["ContinueLabel"] = $ContinueLabel }
        if (Test-Bound "SilentlyContinue") { $splatStopFunction["SilentlyContinue"] = $SilentlyContinue }

        . Stop-Function @splatStopFunction -FunctionName (Get-PSCallStack)[1].Command
        return $testResult
    }
}