DSCResources/ROACommon/Src/Start-WaitProcess.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
function Start-WaitProcess {
<#
    .SYNOPSIS
        Starts and waits for a process to exit.
    .NOTES
        This is an internal function and shouldn't be called from outside.
#>

    [CmdletBinding(SupportsShouldProcess)]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
    [OutputType([System.Int32])]
    param (
        # Path to process to start.
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [System.String] $FilePath,

        # Arguments (if any) to apply to the process.
        [Parameter()]
        #[AllowNull()]
        [System.String[]] $ArgumentList,

        # Credential to start the process as.
        [Parameter()] [AllowNull()]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.CredentialAttribute()] $Credential,

        # Working directory
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String] $WorkingDirectory = (Split-Path -Path $FilePath -Parent)
    )
    process {

        $startInfo = New-Object System.Diagnostics.ProcessStartInfo;
        $startInfo.UseShellExecute = $false; #Necessary for I/O redirection and just generally a good idea
        $process = New-Object System.Diagnostics.Process;
        $process.StartInfo = $startInfo;
        $startInfo.FileName = $FilePath;

        $startInfo.RedirectStandardError = $true
        $startInfo.RedirectStandardOutput = $true
        $exitCode = 0;

        $displayParams = '<None>';
        if ($ArgumentList) {

            $arguments = [System.String]::Join(' ', $ArgumentList);
            $displayParams = $arguments;
            $startInfo.Arguments = $arguments;
        }

        try {

            if ($PSBoundParameters.ContainsKey('Credential')) {

                $commandLine = '"{0}" {1}' -f $startInfo.FileName, $startInfo.Arguments;
                Write-Verbose ($localizedData.StartingProcessAs -f $FilePath, $displayParams, $Credential.UserName);
                Register-PInvoke;
                [Source.NativeMethods]::CreateProcessAsUser(
                    $commandLine,
                    $Credential.GetNetworkCredential().Domain,
                    $Credential.GetNetworkCredential().UserName,
                    $Credential.GetNetworkCredential().Password,
                    [ref] $exitCode
                );
            }
            else {

                Write-Verbose ($localizedData.StartingProcess -f $FilePath, $displayParams);
                [ref] $null = $process.Start();
                $process.WaitForExit();

                if ($process) {

                    $exitCode = $process.ExitCode;
                }
            }

            Write-Verbose ($localizedData.ProcessExited -f $exitCode);
            return $exitCode;
        }
        catch {

            throw;
        }

    } #end process
} #end function Start-WaitProcess