3

I am trying to write a script in PowerShell that will use the invoke command with credentials on a remote machine to execute code that will return a string containing the Java version on that machine. Java is not installed, sometimes it is just dropped in the server as a JDK folder and the application is pointed to that location, so unfortunately I cannot use the registry to find the Java version. The only idea I came up with is to call from within the invoke command something along the lines of:

& "path_to_java.exe" "-version"

Or even something more complicated and then use a regular expression to find the version:

start-process $java -ArgumentList "-version" -NoNewWindow -Wait -RedirectStandardError "$path\tempoutput.txt"
$javaversionoutput = gc "$path\tempoutput.txt"
del "$path\tempoutput.txt"

However, on some servers I keep running into an issue where it is complaining about not having enough heap space to run that Java version command (through the invoke command on that remote server).

Error occurred during initialization of VM
Could not reserve enough space for object heap
D:\Java\jdk1.6.0_39\bin\java.exe
Could not create the Java virtual machine.
+ CategoryInfo          : NotSpecified: (Could not creat...irtual machine.:String) [],     RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName        : <server>

From my research it has to do with the MaxMemoryPerShellMB that is set for a remote PowerShell session. On some servers it is set to 150, on some it's 1024. So sometimes I can successfully get the java -version to run from the PowerShell remote session, and sometimes I cannot, because there is too little memory. If I set it on the remote machine by logging in and doing it manually:

winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1000"}

It starts to work. But I cannot go to each server each time and set it manually. If I try to set MaxMemoryPerShellMB through an invoke command, it says I don't have access, even though I can use the same account to change MaxMemoryPerShellMB on the server if I login and do it directly.

I feel like I have run out of solutions and was hoping to find some help here. Sorry if there has been a topic for this, I only found three and none of them answer my question. Below are the references if you guys are interested. There really is nothing I could find :P

Community
  • 1
  • 1
alexfvolk
  • 1,810
  • 4
  • 20
  • 40
  • 1
    Can you try adding this argument to the jvm: `-Xms 10m`. That will, hopefully, to 10m. I don't know if this will work, since the jvm may actually be trying allocate space for stuff, but it's worth a try. – CodeChimp Feb 18 '14 at 19:11
  • are you on an elevated PowerShell prompt when you are running invoke-command? – Adil Hindistan Feb 18 '14 at 19:57
  • 1
    Is there a reason you're not using WMI? `Get-WmiObject -Class Win32_Product -Filter "Name like 'Java%'" | Select -Expand Version` – genesys Feb 18 '14 at 21:21
  • @Dallas Moore, yes, Java is not always installed, sometimes it just a jdk folder in some location, we just point the application (like jboss) to it from the start up batch script, so I cannot use Win32Product since Java is not always installed. – alexfvolk Feb 19 '14 at 18:15
  • @CodeChimp I've tried playing around with the settings, but I get Invalid initial heap size – alexfvolk Feb 19 '14 at 18:22
  • Just wanted to add to the conversation, @DallasMoore one reason why people shouldn't use Win32_Product is because it is slow, and the query can time out causing you to not get anything back (for more details see: https://blogs.technet.microsoft.com/askds/2012/04/19/how-to-not-use-win32_product-in-group-policy-filtering/) – HAL9256 Feb 18 '16 at 16:25

3 Answers3

2

Honestly, I would just check the version of the file java.exe, something like

$Machines = Get-Content C:\Lists\Servers.txt

$Machines | for-each{

$java = gci '\\$_\c$\Program Files (x86)\Java\jre7\bin\java.exe'

$java.VersionInfo

And you get a VersionInfo object back , something like

 ProductVersion   FileVersion      FileName
 --------------   -----------      --------
 7.0.510.13       7.0.510.13       \\$_\c$\Program Files (x86)\Java\jre7\bin\java.exe

Or probably $null if path not found (of course you can check for that first with test-path but whatever). Good thing is that you can do real operations with the VersionInfo object if you so choosed, one of the awesome benefits of powershell. And Java sucks.

MDMoore313
  • 3,233
  • 1
  • 23
  • 38
  • 1
    Hard-coding the assumption of JRE and version 7 into a script to determine the java version...? – Eric Kramer Mar 26 '21 at 19:10
  • @EricKramer fair enough, though in my defense I worked in a managed environment at the time, and I was the one managing the machines' configuration so that caused a bit of a blind spot in my answer. If I updated this, the spirit of the answer would remain the same~ using the `gci` command in powershell on an exe. I would update it to search both `Prog Files` and `Prog Files (x86)`, filter the results for `java.exe` and run `gci` on all of those, and print out a pretty table. – MDMoore313 Mar 28 '21 at 18:16
  • 1
    fair enough. I do prefer your use of the metadata compared to other responses that make assumptions about `java -version` output. Thanks for your reply and your updated suggestions. – Eric Kramer Mar 29 '21 at 19:21
1

You can use this one liner for getting the latest java version installed. If u have older versions installed too it only returns the latest:

[system.diagnostics.fileversioninfo]::GetVersionInfo(('C:\Program Files (x86)\Java\'+([regex]::matches((&"java.exe" -version 2>&1)[0].ToString(), '(?<=\").+?(?=\")').value.Insert(0,"jre")) + "\bin\java.exe"))
Mathis Michel
  • 277
  • 2
  • 7
0

This should work with no problem

gc "D:\serverlists\serverlist.txt" | foreach {  
[system.diagnostics.fileversioninfo]::GetVersionInfo("\\$_\c$\Program Files\Java\jre6\bin\java.exe"); }