ื”ื—ื–ืจืช ืขืจืš ืž-powershell invoke-command ืœืกื•ื›ืŸ SQL Server

ื›ืฉื™ืฆืจืชื™ ืžืชื•ื“ื•ืœื•ื’ื™ื” ืžืฉืœื™ ืœื ื™ื”ื•ืœ ื’ื™ื‘ื•ื™ื™ื ื‘ืžืกืคืจ ืฉืจืชื™ MS-SQL, ื‘ื™ืœื™ืชื™ ื–ืžืŸ ืจื‘ ื‘ืœื™ืžื•ื“ ื”ืžื ื’ื ื•ืŸ ืœื”ืขื‘ืจืช ืขืจื›ื™ื ื‘-Powershell ื‘ืžื”ืœืš ืฉื™ื—ื•ืช ืžืจื—ื•ืง, ืื– ืื ื™ ื›ื•ืชื‘ ืœืขืฆืžื™ ืชื–ื›ื•ืจืช ืœืžืงืจื” ืฉื–ื” ืฉื™ืžื•ืฉื™ ืœืžื™ืฉื”ื• ืื—ืจ.

ืื– ื‘ื•ืื• ื ืชื—ื™ืœ ืขื ืกืงืจื™ืคื˜ ืคืฉื•ื˜ ื•ื ืคืขื™ืœ ืื•ืชื• ื‘ืื•ืคืŸ ืžืงื•ืžื™:

$exitcode = $args[0]
Write-Host 'Out to host.'
Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)

ื›ื“ื™ ืœื”ืคืขื™ืœ ืกืงืจื™ืคื˜ื™ื, ืืฉืชืžืฉ ื‘ืงื•ื‘ืฅ CMD ื”ื‘ื, ืœื ืื›ืœื•ืœ ืื•ืชื• ื‘ื›ืœ ืคืขื:

@Echo OFF
PowerShell .TestOutput1.ps1 1
ECHO ERRORLEVEL=%ERRORLEVEL%

ืขืœ ื”ืžืกืš ื ืจืื” ืืช ื”ื“ื‘ืจื™ื ื”ื‘ืื™ื:

Out to host.
Out to output.
ExitCode: 1
1
ERRORLEVEL=1


ืขื›ืฉื™ื• ื‘ื•ืื• ื ืจื™ืฅ ืืช ืื•ืชื• ืกืงืจื™ืคื˜ ื“ืจืš WSMAN (ืžืจื—ื•ืง):

Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]

ื•ื”ื ื” ื”ืชื•ืฆืื” ืขื‘ื•ืจื›ื:

Out to host.
Out to output.
ExitCode: 2
2
ERRORLEVEL=0

ื ื”ื“ืจ, ืจืžืช ื”ืฉื’ื™ืื” ื ืขืœืžื” ืื™ืคืฉื”ื•, ืื‘ืœ ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืงื‘ืœ ืืช ื”ืขืจืš ืžื”ืกืงืจื™ืคื˜! ื‘ื•ืื• ื ื ืกื” ืืช ื”ืขื™ืฆื•ื‘ ื”ื‘ื:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]

ื–ื” ืืคื™ืœื• ื™ื•ืชืจ ืžืขื ื™ื™ืŸ. ื”ื”ื•ื“ืขื” ื‘ืคืœื˜ ื ืขืœืžื” ืื™ืคืฉื”ื•:

Out to host.
ExitCode: 2
ERRORLEVEL=0

ื›ืขืช, ื›ืกื˜ื™ื™ื” ืœื™ืจื™ืช, ืืฆื™ื™ืŸ ืฉืื ื‘ืชื•ืš ืคื•ื ืงืฆื™ื™ืช Powershell ืืชื” ื›ื•ืชื‘ Write-Output ืื• ืจืง ื‘ื™ื˜ื•ื™ ืžื‘ืœื™ ืœื”ืงืฆื•ืช ืื•ืชื• ืœืฉื•ื ืžืฉืชื ื” (ื•ื–ื” ืžืจืžื– ื‘ืื•ืคืŸ ืžืจื•ืžื– ืขืœ ืคืœื˜ ืœืขืจื•ืฅ ื”-Output), ืื– ื’ื ื›ืืฉืจ ื”ื•ื ืคื•ืขืœ ื‘ืื•ืคืŸ ืžืงื•ืžื™, ืฉื•ื ื“ื‘ืจ ืœื ื™ื•ืฆื’ ืขืœ ื”ืžืกืš! ื–ื• ืชื•ืฆืื” ืฉืœ ืืจื›ื™ื˜ืงื˜ื•ืจืช ื”-powershell pipeline - ืœื›ืœ ืคื•ื ืงืฆื™ื” ื™ืฉ ืฆื™ื ื•ืจ Output ืžืฉืœื”, ื ื•ืฆืจ ืขื‘ื•ืจื” ืžืขืจืš ื•ื›ืœ ืžื” ืฉื ื›ื ืก ืืœื™ื• ื ื—ืฉื‘ ืœืชื•ืฆืื” ืฉืœ ื‘ื™ืฆื•ืข ื”ืคื•ื ืงืฆื™ื”, ื”ืื•ืคืจื˜ื•ืจ Return ืžื•ืกื™ืฃ ืืช ืขืจืš ื”ื”ื—ื–ืจื” ืœืื•ืชื• ื”ื“ื‘ืจ. pipeline ื›ืืœืžื ื˜ ื”ืื—ืจื•ืŸ ื•ืžืขื‘ื™ืจ ืืช ื”ืฉืœื™ื˜ื” ืœืคื•ื ืงืฆื™ื™ืช ื”ืงืจื™ืื”. ืœืฉื ื”ืžื—ืฉื”, ื”ื‘ื” ื ืจื™ืฅ ืืช ื”ืกืงืจื™ืคื˜ ื”ื‘ื ื‘ืื•ืคืŸ ืžืงื•ืžื™:

Function Write-Log {
  Param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [String[]] $OutString = "`r`n" )
  Write-Output ("Function: "+$OutString)
  Return "ReturnValue"
}
Write-Output ("Main: "+"ParameterValue")
$res = Write-Log "ParameterValue"
$res.GetType()
$res.Length
$res | Foreach-Object { Write-Host ("Main: "+$_) }

ื•ื”ื ื” ื”ืชื•ืฆืื”:

Main: ParameterValue

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
2
Main: Function: ParameterValue
Main: ReturnValue

ืœืคื•ื ืงืฆื™ื” ื”ืจืืฉื™ืช (ื’ื•ืฃ ื”ืกืงืจื™ืคื˜) ื™ืฉ ื’ื ืฆื™ื ื•ืจ ืคืœื˜ ืžืฉืœื”, ื•ืื ื ืจื™ืฅ ืืช ื”ืกืงืจื™ืคื˜ ื”ืจืืฉื•ืŸ ืž-CMD, ืžืคื ื” ืืช ื”ืคืœื˜ ืœืงื•ื‘ืฅ,

PowerShell .TestOutput1.ps1 1 > TestOutput1.txt

ื•ืื– ื ืจืื” ืขืœ ื”ืžืกืš

ERRORLEVEL=1

ื•ื‘ืงื•ื‘ืฅ

Out to host.
Out to output.
ExitCode: 1
1

ืื ื ื‘ืฆืข ืฉื™ื—ื” ื“ื•ืžื” ืž-powershell

PS D:sqlagent> .TestOutput1.ps1 1 > TestOutput1.txt

ืื– ื–ื” ื™ื”ื™ื” ืขืœ ื”ืžืกืš

Out to host.
ExitCode: 1

ื•ื‘ืงื•ื‘ืฅ

Out to output.
1

ื–ื” ืงื•ืจื” ื‘ื’ืœืœ ืฉื”-CMD ืžืฉื™ืง ืืช powershell, ืฉื‘ื”ื™ืขื“ืจ ื”ื•ืจืื•ืช ืื—ืจื•ืช, ืžืขืจื‘ื‘ ืฉื ื™ ืฉืจืฉื•ืจื™ื (Host ื•-Output) ื•ื ื•ืชืŸ ืื•ืชื ืœ-CMD, ืฉืฉื•ืœื— ืืช ื›ืœ ืžื” ืฉื”ื•ื ืงื™ื‘ืœ ืœืงื•ื‘ืฅ, ื•ื‘ืžืงืจื” ืฉืœ ื”ืฉืงื” ืž-powershell, ืฉื ื™ ื”ืฉืจืฉื•ืจื™ื ื”ืœืœื• ืงื™ื™ืžื™ื ื‘ื ืคืจื“, ื•ื”ืคื ื™ื•ืช ืžื—ื“ืฉ ืฉืœ ื”ืกืžืœ ืžืฉืคื™ืขื•ืช ืจืง ืขืœ ืคืœื˜.

ื ื—ื–ื•ืจ ืœื ื•ืฉื ื”ืจืืฉื™, ื”ื‘ื” ื ื–ื›ื•ืจ ืฉืžื•ื“ืœ ื”ืื•ื‘ื™ื™ืงื˜ .NET ื‘ืชื•ืš powershell ืงื™ื™ื ื‘ืžืœื•ืื• ื‘ืชื•ืš ืžื—ืฉื‘ ืื—ื“ (ืžืขืจื›ืช ื”ืคืขืœื” ืื—ืช), ื›ืืฉืจ ืžืคืขื™ืœื™ื ืงื•ื“ ืžืจื—ื•ืง ื‘ืืžืฆืขื•ืช WSMAN, ื”ืขื‘ืจืช ื”ืื•ื‘ื™ื™ืงื˜ื™ื ืžืชืจื—ืฉืช ื‘ืืžืฆืขื•ืช ืกืจื™ืืœื™ื–ืฆื™ื” ืฉืœ XML, ืžื” ืฉืžื‘ื™ื ืขื ื™ื™ืŸ ืจื‘ ื ื•ืกืฃ. ืœืžื—ืงืจ ืฉืœื ื•. ื‘ื•ืื• ื ืžืฉื™ืš ื‘ื ื™ืกื•ื™ื™ื ืฉืœื ื• ืขืœ ื™ื“ื™ ื”ืคืขืœืช ื”ืงื•ื“ ื”ื‘ื:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$res.GetType()
$host.SetShouldExit($res)

ื•ื–ื” ืžื” ืฉื™ืฉ ืœื ื• ืขืœ ื”ืžืกืš:

Out to host.

ExitCode: 3

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
ะะต ัƒะดะฐะตั‚ัั ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะฐั€ะณัƒะผะตะฝั‚ "exitCode", ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ: "System.Object[]", ะดะปั "SetShouldExit" ะฒ ั‚ะธะฟ "System.Int32": "ะะต ัƒะดะฐะตั‚ัั ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต "System.Object[]" ั‚ะธะฟะฐ "System.Object[]" ะฒ ั‚ะธะฟ "System
.Int32"."
D:sqlagentTestOutput3.ps1:3 ะทะฝะฐะบ:1
+ $host.SetShouldExit($res)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

ERRORLEVEL=0

ืชื•ืฆืื” ืžืขื•ืœื”! ื”ืžืฉืžืขื•ืช ื”ื™ื ืฉื›ืืฉืจ ืงื•ืจืื™ื ืœ-Invoke-Command ื ืฉืžืจืช ื—ืœื•ืงืช ื”ืฆื™ื ื•ืจื•ืช ืœืฉื ื™ ืคืชื™ืœื™ื (Host ื•-Output), ืžื” ืฉื ื•ืชืŸ ืœื ื• ืชืงื•ื•ื” ืœื”ืฆืœื—ื”. ื‘ื•ืื• ื ื ืกื” ืœื”ืฉืื™ืจ ืจืง ืขืจืš ืื—ื“ ื‘ื–ืจื ื”ืคืœื˜, ืฉืขื‘ื•ืจื• ื ืฉื ื” ืืช ื”ืกืงืจื™ืคื˜ ื”ืจืืฉื•ืŸ ืฉืื ื• ืžืคืขื™ืœื™ื ืžืจื—ื•ืง:

$exitcode = $args[0]
Write-Host 'Out to host.'
#Write-Output 'Out to output.'
Write-Host ('ExitCode: ' + $exitcode)
Write-Output $exitcode
$host.SetShouldExit($exitcode)

ื‘ื•ื ื ืจื™ืฅ ืืช ื–ื” ื›ื›ื”:

$res=Invoke-Command -ComputerName . -ScriptBlock { &'D:sqlagentTestOutput1.ps1' $args[0] } -ArgumentList $args[0]
$host.SetShouldExit($res)

ื•... ื›ืŸ, ื–ื” ื ืจืื” ื›ืžื• ื ื™ืฆื—ื•ืŸ!

Out to host.
ExitCode: 4

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType


ERRORLEVEL=4

ื‘ื•ืื• ื ื ืกื” ืœื”ื‘ื™ืŸ ืžื” ืงืจื”. ืงืจืื ื• ืœ-powershell ื‘ืื•ืคืŸ ืžืงื•ืžื™, ืฉื‘ืชื•ืจื• ืงืจืื ื• ืœ-powershell ื‘ืžื—ืฉื‘ ื”ืžืจื•ื—ืง ื•ื‘ื™ืฆืขื ื• ืืช ื”ืกืงืจื™ืคื˜ ืฉืœื ื• ืฉื. ืฉื ื™ ื–ืจืžื™ื (Host ื•-Output) ืžื”ืžื›ื•ื ื” ื”ืžืจื•ื—ืงืช ื”ื•ืขื‘ืจื• ื‘ืกื™ื“ืจื” ื•ื”ื•ืขื‘ืจื• ื—ื–ืจื”, ื‘ืขื•ื“ ืฉื–ืจื ื”-Output, ื‘ืขืœ ืขืจืš ื“ื™ื’ื™ื˜ืœื™ ื‘ื•ื“ื“, ื”ื•ืžืจ ืœืกื•ื’ Int32 ื•ื›ื›ื–ื” ื”ื•ืขื‘ืจ ืœืฆื“ ื”ืžืงื‘ืœ, ื•ื”ืฆื“ ื”ืžืงื‘ืœ ื”ืฉืชืžืฉ ื‘ื• ื›ืงื•ื“ ื”ื™ืฆื™ืื” ืฉืœ ื”-powershell ื”ืžืชืงืฉืจ.

ื•ื›ื‘ื“ื™ืงื” ืื—ืจื•ื ื”, ื‘ื•ืื• ื ื™ืฆื•ืจ ืขื‘ื•ื“ื” ื—ื“-ืฉืœื‘ื™ืช ื‘ืฉืจืช SQL ืขื ื”ืกื•ื’ "ืžืขืจื›ืช ื”ืคืขืœื” (cmdexec)" ืขื ื”ื˜ืงืกื˜ ื”ื‘ื:

PowerShell -NonInteractive -NoProfile "$res=Invoke-Command -ComputerName BACKUPSERVER -ConfigurationName SQLAgent -ScriptBlock {&'D:sqlagentTestOutput1.ps1' 6}; $host.SetShouldExit($res)"

ื”ื™ื“ื“! ื”ืžืฉื™ืžื” ื”ื•ืฉืœืžื” ืขื ืฉื’ื™ืื”, ื˜ืงืกื˜ ื‘ื™ื•ืžืŸ:

ะ’ั‹ะฟะพะปะฝัะตั‚ัั ะพั‚ ะธะผะตะฝะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั: DOMAINagentuser. Out to host. ExitCode: 6.  ะšะพะด ะทะฐะฒะตั€ัˆะตะฝะธั ะฟั€ะพั†ะตััะฐ 6.  ะจะฐะณ ะทะฐะฒะตั€ัˆะธะปัั ั ะพัˆะธะฑะบะพะน.

ืžืกืงื ื•ืช:

  • ื”ื™ืžื ืข ืžืฉื™ืžื•ืฉ ื‘-Write-Output ื•ืžืฆื™ื•ืŸ ื‘ื™ื˜ื•ื™ื™ื ืœืœื ื”ืงืฆืื”. ืฉื™ื ืœื‘ ืฉื”ืขื‘ืจืช ืงื•ื“ ื–ื” ืœืžืงื•ื ืื—ืจ ื‘ืกืงืจื™ืคื˜ ืขืฉื•ื™ื” ืœื”ื ื™ื‘ ืชื•ืฆืื•ืช ื‘ืœืชื™ ืฆืคื•ื™ื•ืช.
  • ื‘ืกืงืจื™ืคื˜ื™ื ืฉืœื ืžื™ื•ืขื“ื™ื ืœื”ืคืขืœื” ื™ื“ื ื™ืช, ืืœื ืœืฉื™ืžื•ืฉ ื‘ืžื ื’ื ื•ื ื™ ื”ืื•ื˜ื•ืžืฆื™ื” ืฉืœืš, ื‘ืžื™ื•ื—ื“ ืขื‘ื•ืจ ืฉื™ื—ื•ืช ืžืจื—ื•ืง ื“ืจืš WINRM, ื‘ืฆืข ื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช ื™ื“ื ื™ ื‘ืืžืฆืขื•ืช Try/Catch, ื•ื•ื“ื ืฉื‘ื›ืœ ืคื™ืชื•ื— ืฉืœ ืื™ืจื•ืขื™ื, ื”ืกืงืจื™ืคื˜ ื”ื–ื” ืฉื•ืœื— ื‘ื“ื™ื•ืง ืขืจืš ืกื•ื’ ืคืจื™ืžื™ื˜ื™ื‘ื™ ืื—ื“ . ืื ืืชื” ืจื•ืฆื” ืœืงื‘ืœ ืืช ืจืžืช ื”ืฉื’ื™ืื” ื”ืงืœืืกื™ืช, ืขืจืš ื–ื” ื—ื™ื™ื‘ ืœื”ื™ื•ืช ืžืกืคืจื™.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”