如何使用填充有路径的变量在PowerShell中导航或执行?

时间:2019-09-13 12:44:16

标签: windows powershell powershell-3.0

我当前是第一次编写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;
}

3 个答案:

答案 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