Я работаю с Psexe c из-за некоторых ограничений компании в отношении PSremoting и WMI, а также из-за ненормального вывода PSexe c и определенных значений, интерпретируемых как код ошибки / код выхода в PowerShell. Я адаптировал оболочку из этого post .
Все работает нормально при вызове на локальном компьютере, но не stdout при вызове из этапа сборки Jenkins.
Я хотел бы сделать запрос для рабочего стола SessionID удаленной машины, и эти данные возвращаются в stdout. Есть ли способ сделать это с помощью оболочки, или мне понадобится прямой подход? Это действительно сработало, но я хотел иметь лучшую структуру и отчеты об ошибках во всех сценариях, используемых для сборки:
$stdout = & $psexec \\$hostName -u $user -p $pass -accepteula cmd /c "tasklist /FI "IMAGENAME eq taskhost*" /FO List | findstr "Session#:""
Функция Get-SessionID:
function Get-SessionID
{
<#
.SYNOPSIS
Get session ID.
.DESCRIPTION
Get the host machines desktop session ID.
.PARAMETER None
#>
# Import external functions
Push-Location $PSScriptRoot
Import-module .\Write-Log.ps1 -Force
Import-module .\CheckAndLoad-EnvironmentVariable.ps1 -Force
Import-module .\Psexec-Wrapper.ps1 -Force
# Check and load the environment variables
$hostName = "<IP Address of the remote machine>"
$psexec = "<Path to PSExec.exe>"
$user = "<Remote Machine User Name>"
$pass = "<Remote Machine Password>"
$cmd = "-u $user -p $pass -accepteula -nobanner cmd /c tasklist /FI ""IMAGENAME eq taskhost*"" /FO List"
Write-Log("Running the following command with PsExec: $psexec \\$hostName $cmd")
# Call PsExec with the command line arguments
$result = Psexec-Wrapper $psexec $hostName $cmd
# Check if PsExec call was successful
if(!$? -or ($LASTEXITCODE -ne 0) -or ($result.session_id -eq "") -or ($result.session_id -eq "None"))
{
$errorMessage = "Failed to get the session ID. Result: $logResult"
Report-Error $errorMessage "-13"
Pop-Location
return
}
# Process results
$logResult = $result | Out-String
Write-Log("PsExec output: $logResult")
#Report if error occurred
If($result.exit_code -ne 0)
{
#Exit code for certain run issues should be -13 or Psexec specific error code
$errorMessage = $result.std_err | Out-String
Report-Error $errorMessage $result.exit_code
Pop-Location
return
}
# Get the ID from string
$sessionID= $result.session_id | Out-String
Pop-Location
return $sessionID
}
Вот код оболочки :
function Psexec-Wrapper
{
param
(
[Parameter(Mandatory=$true)] [string] $psexec_path,
[Parameter(Mandatory=$true)] [string] $remote_computer,
[Parameter(Mandatory=$true)] [string] $command_str,
[switch] $include_blank_lines
)
begin
{
$remote_computer_regex_escaped = [regex]::Escape($remote_computer)
# $ps_exec_header = "`r`nPsExec v2.2 - Execute processes remotely`r`nCopyright (C) 2001-2016 Mark Russinovich`r`nSysinternals - www.sysinternals.com`r`n"
$ps_exec_regex_headers_array = @(
'^\s*PsExec v\d+(?:\.\d+)? - Execute processes remotely\s*$',
'^\s*Copyright \(C\) \d{4}(?:-\d{4})? Mark Russinovich\s*$',
'^\s*Sysinternals - www\.sysinternals\.com\s*$'
)
$ps_exec_regex_info_array = @(
('^\s*Connecting to ' + $remote_computer_regex_escaped + '\.{3}\s*$'),
('^\s*Starting PSEXESVC service on ' + $remote_computer_regex_escaped + '\.{3}\s*$'),
('^\s*Connecting with PsExec service on ' + $remote_computer_regex_escaped + '\.{3}\s*$'),
('^\s*Starting .+ on ' + $remote_computer_regex_escaped + '\.{3}\s*$')
)
$bypass_regex_array = $ps_exec_regex_headers_array + $ps_exec_regex_info_array
$exit_code_regex_str =('^.+ exited on ' + $remote_computer_regex_escaped + ' with error code (\d+)\.\s*$')
$process_id_regex_str =('^.+ started on ' + $remote_computer_regex_escaped + ' with process ID (\d+)\.\s*$')
$session_id_regex_str =('^\s*Session#:\s*(\d+)\s*$')
$ps_exec_args_str = ('"\\' + $remote_computer + '" ' + $command_str)
}
process
{
$return_dict = @{
'std_out' = (New-Object 'system.collections.generic.list[string]');
'std_err' = (New-Object 'system.collections.generic.list[string]');
'bypassed_std' = (New-Object 'system.collections.generic.list[string]');
'process_id' = "None";
'session_id' = "None";
'exit_code' = $null;
}
$process_info = New-Object System.Diagnostics.ProcessStartInfo
$process_info.CreateNoWindow = $true
$process_info.RedirectStandardError = $true
$process_info.RedirectStandardOutput = $true
$process_info.UseShellExecute = $false
$process_info.FileName = $psexec_path
$process_info.Arguments = $ps_exec_args_str
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $process_info
$process.Start() | Out-Null
$std_dict = [ordered] @{
'std_out' = New-Object 'system.collections.generic.list[string]';
'std_err' = New-Object 'system.collections.generic.list[string]';
}
# $stdout_str = $process.StandardOutput.ReadToEnd()
while ($true)
{
$line = $process.StandardOutput.ReadLine()
if ($line -eq $null)
{
break
}
$std_dict['std_out'].Add($line)
}
# $stderr_str = $process.StandardError.ReadToEnd()
while ($true)
{
$line = $process.StandardError.ReadLine()
if ($line -eq $null)
{
break
}
$std_dict['std_err'].Add($line)
}
$process.WaitForExit()
ForEach ($std_type in $std_dict.Keys)
{
ForEach ($line in $std_dict[$std_type])
{
if ((-not $include_blank_lines) -and ($line -match '^\s*$'))
{
continue
}
$do_continue = $false
ForEach ($regex_str in $bypass_regex_array)
{
if ($line -match $regex_str)
{
$return_dict['bypassed_std'].Add($line)
$do_continue = $true
break
}
}
if ($do_continue)
{
continue
}
$exit_code_regex_match = [regex]::Match($line, $exit_code_regex_str)
$process_id_regex_match = [regex]::Match($line, $process_id_regex_str)
$session_id_regex_match = [regex]::Match($line, $session_id_regex_str)
if ($exit_code_regex_match.Success)
{
$return_dict['exit_code'] = [int] $exit_code_regex_match.Groups[1].Value
if ($std_type -eq 'std_err')
{
$return_dict['std_err'].Add($line)
}
}
elseif ($process_id_regex_match.Success)
{
$return_dict['process_id'] = [int] $process_id_regex_match.Groups[1].Value
$return_dict['exit_code'] = 0
if ($std_type -eq 'std_out')
{
$return_dict['std_out'].Add($line)
}
}
elseif ($session_id_regex_match.Success)
{
$return_dict['session_id'] = [int] $session_id_regex_match.Groups[1].Value
$return_dict['exit_code'] = 0
if ($std_type -eq 'std_out')
{
$return_dict['std_out'].Add($line)
}
}
elseif ($std_type -eq 'std_out')
{
$return_dict['std_out'].Add($line)
}
elseif ($std_type -eq 'std_err')
{
$return_dict['std_err'].Add($line)
$return_dict['exit_code'] = -13
}
else
{
throw 'this conditional should never be true; if so, something was coded incorrectly'
}
}
}
return $return_dict
}
}