I can't get my head around this bitwise conversion problem.
Robocopy exit codes don't conform to the normal 0(success), 1(failure) pattern so I want to wrap my robocopy calls in the powershell script below to make my TeamCity build configurations fail or proceed appropriately when robocopy terminates.
That first part was solved using a tip from the net with: ($LastExitCode -band 24)
which correctly treats exit codes 8 through 16 as failures (1) and all others as success (0).
Now I want to echo a message corresponding to the exit code. How do I convert and round/floor the integer exit code (0 - 16) to its hexadecimal equivalent (0x00 - 0x10)?
param(
[string] $source,
[string] $target,
[string[]] $action = @("/MIR"),
[string[]] $options = @("/R:2", "/W:1", "/FFT", "/Z", "/XA:H")
)
$cmd_args = @($source, $target, $action, $options)
& robocopy.exe @cmd_args
$returnCodeMessage = @{
0x00 = "[INFO]: No errors occurred, and no copying was done. The source and destination directory trees are completely synchronized."
0x01 = "[INFO]: One or more files were copied successfully (that is, new files have arrived)."
0x02 = "[INFO]: Some Extra files or directories were detected. Examine the output log for details."
0x04 = "[WARN]: Some Mismatched files or directories were detected. Examine the output log. Some housekeeping may be needed."
0x08 = "[ERROR]: Some files or directories could not be copied (copy errors occurred and the retry limit was exceeded). Check these errors further."
0x10 = "[ERROR]: Usage error or an error due to insufficient access privileges on the source or destination directories."
}
Write-Host $returnCodeMessage[($LastExitCode <what goes here?>)]
exit ($LastExitCode -band 24)
In your case you do not need to convert it. You do not need conversion because Hashtable keys are converted to [int] on pre-compiation stage. If you lookup for $returnCodeMessage.Keys , you will see decimal numbers, not hex numbers
To display all messages you should use
$exitcode = $LastExitCode
Write-Host $( @( $returnCodeMessage.Keys | Where-Object { $_ -band $exitcode } | ForEach-Object {return $returnCodeMessage[$_]} ) -join "`r`n")
IF you want to show Hex-encoded $LastExitCode, do
$exitcode = $LastExitCode
Write-Host $('0x' + [System.Convert]::ToString([int]$exitcode,[int]16) )
return $exitcode
String System.Convert.ToString(Int32, Int32)
As filimonic mentioned, 0x10
and 16
are just different ways of writing the same underlying numeric value (i.e. 0x10 -eq 16
evaluates to true
), so no conversion is needed.
To display each message in the combined return code, you can test each of the individual flag values in turn:
if( $returnCodeMessage.ContainsKey( $LastExitCode ) ) {
$returnCodeMessage[$LastExitCode]
}
else {
for( $flag = 1; $flag -le 0x10; $flag *= 2 ) {
if( $LastExitCode -band $flag ) {
$returnCodeMessage[$flag]
}
}
}
For a return code like 0x00
(no change) or 0x04
(mismatch) that contains only one message, we look it up directly. Otherwise, for a composite code like 0x09
(some copied, some not) or 0x13
(some copied, some extras, access denied), we check for each possibility and output those that match.
Also, since "Any value greater than 8 indicates that there was at least one failure during the copy operation", you could use $LastExitCode -ge 8
instead of $LastExitCode -band 24
to test for errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With