简体   繁体   中英

Powershell Subinacl.exe Double-Spaced Output, inability to capture summary information (statistics)

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM