1

我尝试在远程机器上运行以下脚本,从第一行我得到正常输出,“命令成功”或类似的东西。对于第二个,它似乎可以正常工作,但是输出是间隔的并且不是完整的,大约有 4 行输出丢失。

# 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} 

我想要第二个代码行的这个输出:

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

但相反,我得到:

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 )

没有我想看到的最后 3 行。我尝试将输出编码更改为 Unicode 或 UTF8,但不起作用。还有其他解决方案吗?

4

2 回答 2

1

两个不相关的问题

  • (a)subinacl.exe产生UTF-16LE 编码的输出

  • (b) 它的 on-by-default/statistic选项似乎直接写入控制台,绕过标准输出,因此不能被捕获——或者至少不容易被捕获;如果你知道怎么做,请告诉我们。

    • 因此,以 开头的包含统计信息(摘要信息)的最后一行Elapsed: ...总是打印到控制台。
    • 相关问题subinacl get full output是由同样的问题提示的。

(a),如前所述,可以通过告诉 PowerShell 在从外部程序捕获输出时期望什么字符编码来补救,通过[Console]::OutputEncoding

(b) 如果您确实想捕获统计数据行,则无法补救;下一个最好的方法是完全抑制统计输出/nostatistic,这至少不会产生不需要的控制台输出(但是,显然,您根本不会拥有这些信息)。

把它们放在一起:

$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
} 

注意:通常,您会恢复之前的[Console]::OutputEncodingafterward 值,但由于运行脚本块的远程计算机上的会话在此之后立即结束,因此这里没有必要。

于 2018-08-18T18:24:44.733 回答
1

这些工具通常不会返回正确的对象,因此稍后会输出您的字符串。

您可以以不同于默认值的方式处理该输出和/或解析字符串返回以获取您所追求的格式。使用字符串 cmdlet...

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 
... 

由于 Subinacl 用于显示或修改文件和文件夹权限、所有权和域的访问控制条目 (ACE),这与本机 cmdlet...

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
... 

... 提供。为什么不直接使用它们,因为它们返回正确的对象 vs Subinacl?

至于编码。

你是说,你从这个讨论中尝试了这个答案,它对你没有用吗?

从 PowerShell 调用的 SubInACL 输出的双倍间距

#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

OP 更新

使用 RegEx 在您这边清理它。从字符串中删除双空格和空行。

 ('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)

OP 更新

在你的机器上试试这个,看看完整的结果是否真的如你所愿地回来了。

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

如果上面确实带回了完整的结果集。我的最终建议是将其作为临时文件输出到远程计算机上,然后使用 Get-Content 将其读回您的工作站。

于 2018-08-15T22:39:05.150 回答