我当前是第一次编写PowerShell脚本。我只想找出Windows机器上运行的Java版本。它正在搜索所有java.exe
瞬间,将其写入文件中,然后应执行每一行并将输出写入文件中。但是我无法使用变量$command
执行任何操作。因此,for
循环由于错误而只运行了一次,然后退出。
#declaration
$file = ".\text.txt"
$i = 3
$out = ".\output.txt"
Get-ChildItem -Path C:\ -Filter java.exe -Recurse -ErrorAction SilentlyContinue -Force |
Select-Object Directory >> $file
$count = Get-Content $file | Measure-Object -Line
#remove spaces and append "java.exe"
(Get-Content $file | Foreach {$_.TrimEnd()}) | Set-Content $file
(Get-Content $file | foreach {$_ + "\java.exe' -version"}) | Set-Content $file
(Get-Content $file).Replace("C:", "'C:") | Set-Content $file
#remove last 2 lines of the file
$count = $count.Lines - 2
#execute the stored paths
$i = 3
for ($i=3; $i -le $count; $i++) {
$command = Get-Content $file | Select -Index $i;
$command >> $out;
& $command 2> $out; # <----------------This line wont work
echo "_____________________" >> $out;
}
答案 0 :(得分:1)
尽管我不确定您想要的输出是什么样子,但是下面创建了一个PSObjects数组,您可以在屏幕上输出或写入CSV文件。
$result = Get-ChildItem -Path C:\ -Filter java.exe -File -Recurse -ErrorAction SilentlyContinue -Force | ForEach-Object {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $_.FullName
$pinfo.Arguments = "-version"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $pinfo
$process.Start() | Out-Null
$process.WaitForExit()
$output = $process.StandardOutput.ReadToEnd()
if (!$output) { $output = $process.StandardError.ReadToEnd() }
[PsCustomObject]@{
'FileName' = $_.FullName
'VersionInfo' = $output
}
}
# output on screen
$result | Format-List
# output to CSV file (VersionInfo field uses multiple lines)
$result | Export-Csv -Path 'D:\javaversions.csv' -UseCulture -NoTypeInformation
屏幕上的结果将类似于:
FileName : C:\Program Files\Java\jdk1.8.0_31\bin\java.exe VersionInfo : java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) FileName : C:\Program Files\Java\jdk1.8.0_31\jre\bin\java.exe VersionInfo : java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) FileName : C:\Program Files\Java\jre1.8.0_221\bin\java.exe VersionInfo : java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
答案 1 :(得分:0)
@Theo的另一种解决方案是使用一个临时文件,如下所示:
$GetParams = @{
Path = 'C:\'
Filter = 'java.exe'
Recurse = $true
Force = $true
File = $true
ErrorAction = 'SilentlyContinue'
}
$JavaExeFiles = Get-ChildItem @GetParams | select -First 1
$StartParams = @{
ArgumentList = '-version'
NoNewWindow = $true
RedirectStandardError = '.\javaver.txt'
}
$JaveExeDetails = foreach ($JaveExe in $JavaExeFiles) {
Remove-Item -Path $StartParams.RedirectStandardError -EA Ignore
Start-Process @StartParams -FilePath $JaveExe.FullName -Wait
[PSCustomObject]@{
File = $JaveExe.FullName
Version = Get-Content -Path $StartParams.RedirectStandardError
}
}
# For viewing in the console
$JaveExeDetails | fl *
# For export to a file
$JaveExeDetails | fl * | Out-File -FilePath ./JavaVersions.txt
答案 2 :(得分:0)
您的代码不起作用,因为您要将整个命令行写入中间文件,然后尝试通过调用运算符从该文件中调用命令字符串。这不起作用,因为命令"'C:\path\to\java.exe' -version"
不存在。您应该得到这样的错误:
PS C:\> $command = "'C:\path\to\java.exe' -version" PS C:\> & $command & : The term ''C:\path\to\java.exe' -version' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:3 + & $command + ~~~~~~~~ + CategoryInfo : ObjectNotFound: ('C:\path\to\java.exe' -version:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
使代码正常工作的最简单方法是直接调用可执行文件:
Get-ChildItem -Path 'C:\' -Filter 'java.exe' -Recurse -EA SilentlyContinue -Force |
ForEach-Object {
$_.FullName + ' -version'
& $_.FullName -version 2>&1
'__________________'
} |
Set-Content $out
如果您想使用中间文件来使用该方法,则需要在命令行之前添加call运算符,将其转换为脚本块,然后调用它。
Get-Content $file | ForEach-Object {
$command
& ([Scriptblock]::Create("& $command")) 2>&1
'__________________'
} | Out-File $out