【问题标题】:Output is different between manual and programmatic executions in PowerShellPowerShell 中手动执行和编程执行的输出不同
【发布时间】:2019-03-02 19:54:31
【问题描述】:

当手动运行和以编程方式运行时,我从同一命令得到两个不同的输出,我不明白为什么。

有问题的命令:

powershell -Command "Get-Module -ListAvailable"

在命令提示符下手动运行时,我得到以下输出:

U:\> powershell -Command "Get-Module -ListAvailable"

Directory: C:\Program Files\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...}
Script     1.0.0.1    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}
Binary     6.5.1.6... VMware.DeployAutomation             {Add-DeployRule, Add-ProxyServer, Add-ScriptBundle, Copy-DeployRule...}
Binary     6.5.1.6... VMware.ImageBuilder                 {Add-EsxSoftwareDepot, Add-EsxSoftwarePackage, Compare-EsxImageProfile, Export-EsxImageProfile...}
Manifest   6.5.4.7... VMware.PowerCLI
Binary     6.5.4.6... VMware.VimAutomation.Cis.Core       {Connect-CisServer, Disconnect-CisServer, Get-CisService}
Binary     6.5.1.5... VMware.VimAutomation.Cloud          {Add-CIDatastore, Connect-CIServer, Disconnect-CIServer, Get-Catalog...}
Manifest   6.5.4.6... VMware.VimAutomation.Common
Binary     6.5.2.6... VMware.VimAutomation.Core           {Add-PassthroughDevice, Add-VirtualSwitchPhysicalNetworkAdapter, Add-VMHost, Add-VMHostNtpServer...}
Binary     6.5.4.7... VMware.VimAutomation.HA             Get-DrmInfo
Binary     7.1.0.5... VMware.VimAutomation.HorizonView    {Connect-HVServer, Disconnect-HVServer}
Binary     6.5.1.5... VMware.VimAutomation.License        Get-LicenseDataManager
Binary     2.0.0.6... VMware.VimAutomation.Nsxt           {Connect-NsxtServer, Disconnect-NsxtServer, Get-NsxtService}
Binary     6.5.1.5... VMware.VimAutomation.PCloud         {Connect-PIServer, Disconnect-PIServer, Get-PIComputeInstance, Get-PIDatacenter}
Manifest   1.0.0.5... VMware.VimAutomation.Sdk            {Get-PSVersion, Get-InstallPath}
Binary     6.5.1.5... VMware.VimAutomation.Srm            {Connect-SrmServer, Disconnect-SrmServer}
Binary     6.5.4.7... VMware.VimAutomation.Storage        {Add-KeyManagementServer, Copy-VDisk, Export-SpbmStoragePolicy, Get-KeyManagementServer...}
Script     1.1        VMware.VimAutomation.StorageUtility Update-VmfsDatastore
Binary     6.5.1.5... VMware.VimAutomation.Vds            {Add-VDSwitchPhysicalNetworkAdapter, Add-VDSwitchVMHost, Export-VDPortGroup, Export-VDSwitch...}
Binary     6.5.4.7... VMware.VimAutomation.Vmc            {Connect-Vmc, Disconnect-Vmc, Get-VmcService, Connect-VmcServer...}
Binary     6.5.1.5... VMware.VimAutomation.vROps          {Connect-OMServer, Disconnect-OMServer, Get-OMAlert, Get-OMAlertDefinition...}
Binary     6.5.1.5... VMware.VumAutomation                {Add-EntityBaseline, Copy-Patch, Get-Baseline, Get-Compliance...}

Directory: C:\Windows\system32\WindowsPowerShell\v1.0\Modules

ModuleType Version Name                             ExportedCommands
---------- ------- ----                             ----------------
Manifest   1.0.0.0 AppLocker                        {Set-AppLockerPolicy, Get-AppLockerPolicy, Test-AppLockerPolicy, Get-AppLockerFileInformation...}
Manifest   1.0.0.0 BitsTransfer                     {Add-BitsFile, Remove-BitsTransfer, Complete-BitsTransfer, Get-BitsTransfer...}
Manifest   1.0.0.0 CimCmdlets                       {Get-CimAssociatedInstance, Get-CimClass, Get-CimInstance, Get-CimSession...}
Script     1.0.0.0 ISE                              {New-IseSnippet, Import-IseSnippet, Get-IseSnippet}
Manifest   1.0.0.0 Microsoft.PowerShell.Archive     {Compress-Archive, Expand-Archive}
Manifest   3.0.0.0 Microsoft.PowerShell.Diagnostics {Get-WinEvent, Get-Counter, Import-Counter, Export-Counter...}
Manifest   3.0.0.0 Microsoft.PowerShell.Host        {Start-Transcript, Stop-Transcript}
Manifest   3.1.0.0 Microsoft.PowerShell.Management  {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...}
Script     1.0     Microsoft.PowerShell.ODataUtils  Export-ODataEndpointProxy
Manifest   3.0.0.0 Microsoft.PowerShell.Security    {Get-Acl, Set-Acl, Get-PfxCertificate, Get-Credential...}
Manifest   3.1.0.0 Microsoft.PowerShell.Utility     {Format-List, Format-Custom, Format-Table, Format-Wide...}
Manifest   3.0.0.0 Microsoft.WSMan.Management       {Disable-WSManCredSSP, Enable-WSManCredSSP, Get-WSManCredSSP, Set-WSManQuickConfig...}
Manifest   1.0.0.0 NetworkSwitchManager             {Disable-NetworkSwitchEthernetPort, Enable-NetworkSwitchEthernetPort, Get-NetworkSwitchEthernetPort, Remove-NetworkSwitchEthernetPortIPAddress...}
Manifest   1.1     PSDesiredStateConfiguration      {Set-DscLocalConfigurationManager, Start-DscConfiguration, Test-DscConfiguration, Publish-DscConfiguration...}
Script     1.0.0.0 PSDiagnostics                    {Disable-PSTrace, Disable-PSWSManCombinedTrace, Disable-WSManTrace, Enable-PSTrace...}
Binary     1.1.0.0 PSScheduledJob                   {New-JobTrigger, Add-JobTrigger, Remove-JobTrigger, Get-JobTrigger...}
Manifest   2.0.0.0 PSWorkflow                       {New-PSWorkflowExecutionOption, New-PSWorkflowSession, nwsn}
Manifest   1.0.0.0 PSWorkflowUtility                Invoke-AsWorkflow
Manifest   1.0.0.0 TroubleshootingPack              {Get-TroubleshootingPack, Invoke-TroubleshootingPack}

Directory: C:\opscode\chefdk\modules

ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script     0.0     chef {chef-apply, chef-client, chef-service-manager, chef-shell...}

以编程方式(通过 Java)运行时,我得到以下输出:

ModuleType Name                      ExportedCommands
---------- ----                      ----------------
Binary     PackageManagement         {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...}
Script     PowerShellGet             {Install-Module, Find-Module, Save-Module, Update-Module...}
Manifest   BitsTransfer              {Add-BitsFile, Remove-BitsTransfer, Complete-BitsTransfer, Get-BitsTrans...
Manifest   CimCmdlets                {Get-CimAssociatedInstance, Get-CimClass, Get-CimInstance, Get-CimSessio...
Script     ISE                       {New-IseSnippet, Import-IseSnippet, Get-IseSnippet}
Manifest   Microsoft.PowerShell.A... {Compress-Archive, Expand-Archive}
Manifest   Microsoft.PowerShell.D... {Get-WinEvent, Get-Counter, Import-Counter, Export-Counter...}
Manifest   Microsoft.PowerShell.Host {Start-Transcript, Stop-Transcript}
Manifest   Microsoft.PowerShell.M... {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...}
Script     Microsoft.PowerShell.O... Export-ODataEndpointProxy
Manifest   Microsoft.PowerShell.S... {Get-Acl, Set-Acl, Get-PfxCertificate, Get-Credential...}
Manifest   Microsoft.PowerShell.U... {Format-List, Format-Custom, Format-Table, Format-Wide...}
Manifest   Microsoft.WSMan.Manage... {Disable-WSManCredSSP, Enable-WSManCredSSP, Get-WSManCredSSP, Set-WSManQ...
Manifest   PSDesiredStateConfigur... {Set-DscLocalConfigurationManager, Start-DscConfiguration, Test-DscConfi...
Manifest   PSDiagnostics             {Start-Trace, Stop-Trace, Enable-WSManTrace, Disable-WSManTrace...}
Binary     PSScheduledJob            {New-JobTrigger, Add-JobTrigger, Remove-JobTrigger, Get-JobTrigger...}
Manifest   TroubleshootingPack       {Get-TroubleshootingPack, Invoke-TroubleshootingPack}
Script     chef                      {chef-apply, chef-client, chef-service-manager, chef-shell...}

程序化运行的输出缺少 “版本” 列,并且只是可用模块的一个子集。

我想我可能以某种方式调用了两个不同的 PowerShell 可执行文件,所以我手动和以编程方式运行了 powershell -Command "$PSVersionTable"

手动运行powershell -Command "$PSVersionTable"的输出:

Name                           Value
----                           -----
PSVersion                      5.0.10586.117
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.10586.117
CLRVersion                     4.0.30319.18444
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

powershell -Command "$PSVersionTable" 程序化运行的输出:

Name                           Value
----                           -----
PSVersion                      5.0.10586.117
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.10586.117
CLRVersion                     4.0.30319.18444
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

所以我认为我正在运行相同的 PowerShell 可执行文件。

为什么我在运行相同的命令时会得到两个完全不同的输出?

用于以编程方式运行命令的实际 Java 代码:

public class Example {

    private void myMethod(String command) throws IOException {
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader bufferedReader =
            new BufferedReader(new InputStreamReader(process.getInputStream()));

        String output = "";
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            output += (line + "\n");
        }

        System.out.println((output.isEmpty() ?
                            "No output was received!!!" :
                            output));


        BufferedReader errorBufferedReader =
            new BufferedReader(new InputStreamReader(process.getErrorStream()));
        String errorOutput = "";
        while ((line = errorBufferedReader.readLine()) != null) {
            errorOutput += (line + "\n");
        }

        System.out.println((errorOutput.isEmpty() ?
                           "Nothing in the error output stream." :
                           errorOutput));
    }


    public static void main(String[] args) throws IOException {
        new Example().myMethod(
            "powershell -Command \"Get-Module -ListAvailable\"");
    }

}

【问题讨论】:

  • 以编程方式运行它时使用的实际代码是什么。命令是否在相同的用户上下文中运行?一个是 64 位,另一个是 32 位吗?
  • @EBGreen 我将在一秒钟内发布对问题的更新,其中包括代码。
  • @EBGreen 代码现在包含在帖子中。程序执行是通过 IntelliJ 中的 32 位 JDK 完成的。手动执行是通过 cmd 提示符 (C:\Windows\system32\cmd.exe) 完成的。主机操作系统为 64 位 Win 7。
  • 您可以调用[Environment]::Is64BitProcess 来验证您是否正在运行 PowerShell.exe 的 32 位或 64 位可执行文件。
  • 我怀疑那是你的问题。如果您从 64 cmd 运行 Powershell,您将获得 64 位 Powershell 而不是 32 位

标签: java powershell


【解决方案1】:

我的猜测是,从 Java 以编程方式调用 PowerShell 时,您只是没有得到格式化输出,或者由于某种原因不同版本具有不同的默认格式配置。

首先,一些背景:

在命令行运行 PowerShell 获得的输出由格式文件中的格式决定。这些都存储在$PSHome\*.format.ps1xmlGet-Module 返回 System.Management.Automation.PSModuleInfo 类型的对象。如果您运行Select-String -Pattern 'PSModuleInfo' -Path "$PSHome\*.format.ps1xml",您可以找到指定默认格式的位置。 Format-Table 将有 Table,这是您通常获得的默认值。还有Wide 对应Format-WideList 对应Format-List。您可以在Get-Help about_Format.ps1xml 了解有关控制台输出格式的更多信息。

由于PSModuleInfo 的默认输出是使用表格格式,您应该能够通过调用使您的 Java 匹配 PowerShell:

new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Format-Table\"");

或者可能:

new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Format-Table | Out-String\"");

或者甚至只是:

new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Out-String\"");

至于 Java 有什么不同或者为什么它的格式不一样,恐怕我不知道。

您也可以随时执行以下操作:

new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Out-String\"");

如果您想序列化您的输出,您也可以使用Get-Module -ListAvailable | ConvertTo-Json -Compress -Depth 1Get-Module -ListAvailable | ConvertTo-Xml -NoTypeInformation -As String -Depth 1 或类似方法取得成功。请记住,ConvertTo-Json 的默认深度是 2,ConvertTo-Xml 的默认深度是 1,深度 3 以外的任何东西都会非常慢

【讨论】:

  • 感谢您的帮助和建议,我相信它们会派上用场。但是,我现在相当确定我的真正问题是由于以下原因:: 当我手动运行 powershell -Command "Get-Module -ListAvailable" 时,我是通过 64 位命令提示符运行它。这反过来又调用了 64 位 PowerShell。当我以编程方式运行相同的命令时,Java 使用的是 32 位命令提示符。这反过来又调用了 32 位 PowerShell。 32 位和 64 位有不同的模块安装路径,所以这就是我得到 diff 输出值的原因。
【解决方案2】:

我 99.9% 确定这是我的问题的真正原因。

当我手动运行命令检查可用模块列表时,我使用的是 64 位 PowerShell 实例。

我的 Java 程序在 32 位上下文中运行(针对 32 位 JDK 构建)。当我的程序调用 cmd 提示符时,它得到了 32 位 cmd 提示符。当 cmd 提示符调用 PowerShell 时,它得到的是 32 位 PowerShell。 32 位和 64 位版本的 PowerShell 具有存储模块的唯一安装路径。

所以,当我手动安装模块时,我总是使用 64 位 PowerShell。我从未手动打开 32 位 PowerShell 并安装任何模块。这就是为什么 Get-Module -ListAvailable 的编程输出与我手动运行相同命令时看到的相比如此之小。

感谢@BaconBits 为我提供线索,帮助我确定发生了什么。该技巧是执行[Environment]::Is64BitProcess 来验证我的 PowerShell 实际运行的操作系统架构上下文。

【讨论】:

    猜你喜欢
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多