1

I try to run the following script on a remote machine, from the first line I get the normal output, "Command was successful" or something like that. For the second one it seems that its working, but the output its spaced and its not full, there are like 4 lines of output missing.

# This works as expected.
$output = Invoke-Command -ComputerName ServerName -ScriptBlock {auditpol /set /subcategory:"Registry" /success:enable /failure:enable}
# This creates double-spaced output and is missing the last 3 output lines.
$output = Invoke-Command -ComputerName ServerName -ScriptBlock {Subinacl.exe /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD} 

I want this output for the second code line:

SYSTEM\Path : delete Audit ACE 0 \everyone
SYSTEM\Path : new ace for \everyone
HKEY_LOCAL_MACHINE\SYSTEM\Path : 2 change(s)


Elapsed Time: 00 00:00:00
Done:        1, Modified        1, Failed        0, Syntax errors        0
Last Done  : HKEY_LOCAL_MACHINE\SYSTEM\Path

But instead I get:

S Y S T E M \ P a t h   :   d e l e t e   A u d i t   A C E   0   \ e v e r y o n e 

 S Y S T E M \ P a t h   :   n e w   a c e   f o r   \ e v e r y o n e 

 H K E Y _ L O C A L _ M A C H I N E \ S Y S T E M \ P a t h   :   2   c h a n g e ( s )

Without the last 3 lines, which I want to see. I tried change the Output Encoding to Unicode or UTF8 but are not working. Any other solutions?

mklement0
  • 382,024
  • 64
  • 607
  • 775
iMasck
  • 103
  • 1
  • 1
  • 13
  • 1
    You are running two different tools for two different use cases, and it sounds like you are expecting the same results, which is not really a thing. Please define / clarify what you are looking for here. Meaning, the success and error and identifying what you are specifically after on the return results. Otherwise we are left to assume. – postanote Aug 15 '18 at 21:34
  • @postanote Yes, there are two different tools. The second one gives me some trouble because the output its not clear. I already Edited the Question :) – iMasck Aug 15 '18 at 21:48
  • 1
    "*I tried change the Output Encoding to Unicode or UTF8 but are not working.*" - that problem is something encoding text to a double-byte encoding (e.g. PowerShell's "Unicode" but not "UTF8"), and then something reading it back as a single byte encoding, so the double-bytesshow up as char, space, char, space, etc. This https://stackoverflow.com/questions/33630299/double-spacing-of-output-from-subinacl-called-from-powershell describes it and the fix you tried - but which side did you make the change on? Maybe you need to put it inside the scriptblock, before the SubInAcl call? – TessellatingHeckler Aug 15 '18 at 22:35
  • Or here https://social.technet.microsoft.com/Forums/ie/en-US/1a9f523e-5f2d-432f-804c-f49307f5458d/reading-output-from-shell-command-adds-extra-whitespace-and-crlfs?forum=ITCG suggests running it through `cmd /c subinacl...` instead – TessellatingHeckler Aug 15 '18 at 22:36
  • @TessellatingHeckler Intresting, I put the Unicode line in the ScriptBlock and the output its no longer spaced, but there are still missing the last 3 lines. I also tried the cmd /c option, but it seems that its not working – iMasck Aug 15 '18 at 23:07

2 Answers2

1

These tools don't often return proper object, hence your string output on the later.

You can work to handle that output differently than it's default and / or parse the string return to get the format you are after. Using the string cmdlets...

Get-Command -Name '*string*' | Format-Table -AutoSize

CommandType Name                               Version Source                       
----------- ----                               ------- ------                       
Function    ConvertFrom-SddlString             3.1.0.0 Microsoft.PowerShell.Utility 
...       
Function    Format-String                      1.3.6   PowerShellCookbook           
...
Cmdlet      ConvertFrom-String                 3.1.0.0 Microsoft.PowerShell.Utility 
Cmdlet      ConvertFrom-StringData             3.1.0.0 Microsoft.PowerShell.Utility 
Cmdlet      Convert-String                     3.1.0.0 Microsoft.PowerShell.Utility 
...             
Cmdlet      Out-String                         3.1.0.0 Microsoft.PowerShell.Utility 
... 

Since Subinacl is used to display or modify Access ControlEntries (ACEs) for file and folder Permissions, Ownership and Domain, whcih is the same thing that the native cmdlets...

Get-Command -Name '*acl*' | Format-Table -AutoSize

CommandType Name                                               Version      Source                        
----------- ----                                               -------      ------                        
...
Cmdlet      Get-Acl                                            3.0.0.0      Microsoft.PowerShell.Security 
...
Cmdlet      Set-Acl                                            3.0.0.0      Microsoft.PowerShell.Security 
...
Application cacls.exe                                          10.0.17134.1 C:\WINDOWS\system32\cacls.exe 
Application icacls.exe                                         10.0.17134.1 C:\WINDOWS\system32\icacls.exe
... 

... provide. Why not just use them instead as they return proper objects vs Subinacl?

As for encoding.

Are are you saying, you tried this answer, from this discussion and it did nto work for you?

Double spacing of output from SubInACL called from PowerShell

#set output encoding to unicode
[Console]::OutputEncoding = [Text.Encoding]::Unicode

$func_filePath = "G:\test\func.txt"

#use subinacl
[string]$SubInACLCommand = @"
subinacl.exe /file "$func_filePath" /setowner="hostname\Administrators"
"@

Invoke-Expression $SubInACLCommand

#revert output encoding back to default
[Console]::OutputEncoding = [Text.Encoding]::Default

Update for OP

Using RegEx to clean this up on your side. Remove double spaces and empty lines from a string.

 ('S Y S T E M \ P a t h   :   d e l e t e   A u d i t   A C E   0   \ e v e r y o n e 

 S Y S T E M \ P a t h   :   n e w   a c e   f o r   \ e v e r y o n e 

 H K E Y _ L O C A L _ M A C H I N E \ S Y S T E M \ P a t h   :   2   c h a n g e ( s )').replace('  ','|').Replace(' ','').Replace('|',' ') -creplace('(?m)^\s*\r?\n','')

# Results

SYSTEM\Path : delete Audit ACE 0 \everyone
SYSTEM\Path : new ace for \everyone
HKEY_LOCAL_MACHINE\SYSTEM\Path : 2 change(s)

Update for OP

Try this on your machine and see if the full results are actually coming back as you'd expect.

$SubinaclResults = Invoke-Command -ComputerName ServerName -ScriptBlock {Subinacl.exe /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD} 
$SubinaclResults

If the above does to bring back the full result set. My final suggestion would be to output this as a temp file on the remote machine and read it back to your workstation with Get-Content.

postanote
  • 15,138
  • 2
  • 14
  • 25
  • Yes, I tried that answer and it didn't work. The output its weird, when I am on the remote machine and I run the Script Block code, the Output its fine, but when I run the script, from my local machine, the Output does not show up correctly. – iMasck Aug 15 '18 at 22:54
  • Ok, now I suspect that is a bit odd. However, if push comes to shove, you can revert to using RegEx to clean up the output on your side of this. See my update for you using that output you posted. – postanote Aug 15 '18 at 23:09
  • As the other user suggested above, I pute the Unicode line in the ScriptBlock and got the same Output as yours, but still missing the last 3 lines – iMasck Aug 15 '18 at 23:13
  • Are you getting the same thing using the regex example, meaning missing 3 lines? I have not have or use Subinacl on any system in years, thus don't have it on any to actually test what you are seeing. – postanote Aug 15 '18 at 23:16
  • Yes, I also tried with Regex and the three lines are missing – iMasck Aug 15 '18 at 23:22
1

There are two unrelated problems:

  • (a) subinacl.exe produces UTF-16LE-encoded output.

  • (b) Its on-by-default /statistic option seems to write directly to the console, bypassing stdout, and therefore cannot be captured - or at least not easily; do tell us if you know how.

    • Therefore, the last block of lines containing statistics (summary information), which starts with Elapsed: ..., always prints to the console.
    • Related question subinacl get full output was prompted by the same problem.

(a), as stated, can be remedied by telling PowerShell what character encoding to expect when capturing output from external programs, via [Console]::OutputEncoding

(b) cannot be remedied if you do want to capture the statistics lines too; the next best thing is to suppress statistics output altogether with /nostatistic, which at least doesn't produce unwanted console output (but, obviously, you won't have the information at all).

Putting it all together:

$output = Invoke-Command -ComputerName ServerName -ScriptBlock {
  # Tell PowerShell what character encoding to expect in subinacl's output.
  [Console]::OutputEncoding = [Text.Encoding]::Unicode # UTF-16LE
  # Note the addition of /nostatistic to suppress the direct-to-console summary info.
  Subinacl.exe /nostatistic /verbose=1 /keyreg "HKEY_LOCAL_MACHINE\SYSTEM\Path" /sallowdeny="everyone"=SCD
} 

Note: Normally, you'd restore the previous value of [Console]::OutputEncoding afterward, but since the session on the remote computer in which the script block runs ends right after, it isn't necessary here.

mklement0
  • 382,024
  • 64
  • 607
  • 775