Output is different between manual and programmatic executions in PowerShell
110 观看
2回复
286 作者的声誉
I'm getting two different outputs from the same command when run manually vs. programmatically, and I don't understand why.
The command in question:
powershell -Command "Get-Module -ListAvailable"
When run manually in the command prompt, I get this output:
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...}
When run programmatically (via Java), I get this output:
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...}
The output from a programmatic run is missing the "Version" column and is only a subset of the available modules.
I thought maybe somehow I was invoking two different PowerShell executables, so I ran powershell -Command "$PSVersionTable"
both manually and programmatically.
The output from a manual run of 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
The output from a programmatic run of 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
So I think I'm running the same PowerShell executable.
Why am I getting two completely different outputs when running the same command?
The actual Java code that is being used to programmatically run the command:
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\"");
}
}
作者: Chiefwarpaint
的来源
发布者: 2017 年 12 月 27 日
回应 2
1像
22767 作者的声誉
My guess is that you just don't get formatted output when calling PowerShell programmatically from Java, or the different versions have different default format configurations for some reason.
First, some background:
The output you get from running PowerShell at the command line is dictated by the formatting in the format files. These are all stored at $PSHome\*.format.ps1xml
. Get-Module
returns objects of type System.Management.Automation.PSModuleInfo
. If you run Select-String -Pattern 'PSModuleInfo' -Path "$PSHome\*.format.ps1xml"
you can find where the default formats are specified. There will be Table
for Format-Table
, which is the default you normally get. There's also Wide
for Format-Wide
, and List
for Format-List
. You can learn more about the console output formatting at Get-Help about_Format.ps1xml
.
Since the default output for PSModuleInfo
is to use the Table formatting, you should be able to make your Java match PowerShell by calling:
new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Format-Table\"");
Or possibly:
new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Format-Table | Out-String\"");
Or maybe even just:
new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Out-String\"");
As for what Java is doing different or why it's not formatting similarly, I'm afraid I don't know.
You can also always do something like:
new Example().myMethod("powershell -Command \"Get-Module -ListAvailable | Out-String\"");
You may also have success with Get-Module -ListAvailable | ConvertTo-Json -Compress -Depth 1
or Get-Module -ListAvailable | ConvertTo-Xml -NoTypeInformation -As String -Depth 1
or similar if you want to serialize your output. Just bear in mind that the default depth of ConvertTo-Json
is 2, the default depth of ConvertTo-Xml
is 1, and that anything more than depth 3 is going to be really slow.
0像
286 作者的声誉
I'm 99.9% certain this was the true cause of my issue.
When I was manually running the command to check the list of available modules, I was using a 64-bit instance of PowerShell.
My Java program was running in a 32-bit context (was built against a 32-bit JDK). When my program invoked the cmd prompt, it was getting a 32-bit cmd prompt. When the cmd prompt invoked PowerShell, it was getting a 32-bit PowerShell. The 32-bit and 64-bit versions of PowerShell have unique install paths where they store modules.
So, when I was manually installed modules, I was always using a 64-bit PowerShell. I had never manually opened a 32-bit PowerShell and installed any modules. That's why the programmatic output of a Get-Module -ListAvailable
was so small, compared to what I was seeing when I was manually running the same command.
Thanks to @BaconBits for providing me with the clue that helped me identify what was going on. That tip was to execute a [Environment]::Is64BitProcess
to verify what OS architecture context my PowerShell was actually running in.
来自类别的问题 :
- java Java和C#中的int和Integer有什么区别?
- java 如何在Java中确定路由器/网关的IP?
- java 根据XSD文件验证XML文件的最佳方法是什么?
- java 如何整理整数除法的结果?
- java 将List <Integer>转换为List <String>
- java 为什么我不能在接口中声明静态方法?
- java 关闭电脑
- java 如何用Java播放声音?
- java 何时选择已检查和未检查的例外
- java 在Java中覆盖equals和hashCode时应该考虑哪些问题?
- powershell 如何在PowerShell中创建自定义类型以供我的脚本使用?
- powershell 相当于* Nix'在PowerShell中的命令?
- powershell 如何使用PowerShell卸载应用程序?
- powershell PowerShell是一种强类型语言吗?
- powershell Powershell相当于bash&符号(&)用于分叉/运行后台进程
- powershell 在Powershell中使用用户名/密码连接到网络文件夹
- powershell PowerShell中的环境变量,名称中带有点(。)
- powershell Exchange PowerShell:查找活动目录办公室属性
- powershell 有没有办法通过Exchange PowerShell查询谁是activesync / bb用户?
- powershell Powershell中的“@”符号有什么作用?