question

YonglongYL44Wang-5709 avatar image
0 Votes"
YonglongYL44Wang-5709 asked YonglongYL44Wang-5709 commented

Method invocation failed because [System.Object[]] does not contain a method named 'Substring'.

I want to write a powershell script to get the java daemon , when it's over 30(%) or 40%, i will restart some java application, here is my script.


$java_used_cpu_string = Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' | Select-Object -ExpandProperty countersamples| Select-Object -Property instancename, cookedvalue| ? {$_.instanceName -notmatch "^(idle|total|system)$"} | Sort-Object -Property cookedvalue -Descending| Select-Object -First 5| ft InstanceName,@{L='CPU';E={($.Cookedvalue/100/$env:NUMBER_OF_PROCESSORS).toString('P')}} -AutoSize |findstr java
$java_used_cpu1 = $java_used_cpu_string -replace "^.+?\s+(.+)$",'$1'
$java_used_cpu = $java_used_cpu1.Substring(0,$java_used_cpu1.Length-1)
$num_java_used_cpu = [int]$java_used_cpu


but the got the following error.

Method invocation failed because [System.Object[]] does not contain a method named 'Substring'.
At D:\ProgramFiles86\ValidateAddressWs\bin\restart_dma_cpu_high.ps1:4 char:1
+ $java_used_cpu = $java_used_cpu1.Substring(0,$java_used_cpu1.Length- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound



windows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered YonglongYL44Wang-5709 commented

I think you can reduce that code quite a bit:

 $num_java_used_cpu = Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' | 
     Select-Object -ExpandProperty countersamples |          # get array of PerformanceCounterSample objects
         Where-Object {$_.InstanceName -eq 'java'} |         # get just the counters for java        
             Sort-Object -Property cookedvalue -Descending | # sort by cpu consumer
                 Select-Object InstanceName, @{L = 'CPU'; E = { [int]($_.Cookedvalue/$env:NUMBER_OF_PROCESSORS)} } -First 1  # get the largest CPU consumer
    
 Format-Table $num_java_used_cpu
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

do you mean i can just write the script to 2 lines , right ? :


$num_java_used_cpu = Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' | Select-Object -ExpandProperty countersamples | Where-Object {$.InstanceName -eq 'java'} | Sort-Object -Property cookedvalue -Descending | Select-Object InstanceName, @{L = 'CPU'; E = { [int]($.Cookedvalue/$env:NUMBER_OF_PROCESSORS)} } -First 1
Format-Table $num_java_used_cpu



PS D:\ProgramFiles86\bin> $num_java_used_cpu = Get-Counter -ErrorAction SilentlyContin
% Processor Time' | Select-Object -ExpandProperty countersamples | Where-Object {$.InstanceName -eq 'ja
ct -Property cookedvalue -Descending | Select-Object InstanceName, @{L = 'CPU'; E = { [int]($
.Cookedval
F_PROCESSORS)} } -First 1

PS D:\ProgramFiles86\bin> echo $num_java_used_cpu
InstanceName CPU


java 0

PS D:\ProgramFiles86\bin> Format-Table $num_java_used_cpu
Format-Table : Cannot convert System.Management.Automation.PSObject to one of the following types {Syste
System.Management.Automation.ScriptBlock}.
At line:1 char:1
+ Format-Table $num_java_used_cpu
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Format-Table], NotSupportedException
+ FullyQualifiedErrorId : DictionaryKeyUnknownType,Microsoft.PowerShell.Commands.FormatTableCommand

0 Votes 0 ·

Don't get hung up one the number of lines in your scripts. Make the script's function clear to the reader. Unless you're typing the script at the command line don't use aliases ("?", "%", "gci"), use the full cmdlet name (Where-Object, Foreach-Object, Get-ChildItem). Use comments, Be considerate and keep in mind that whoever takes over after you're gone has to understand what you've left behind!

In the case you propose, ask if you need the $num_java_used_cpu at all. Do you need that value later in your script? If the answer is "no" then remove the variable entirely. Without the $num_java_used_cpu the need for the "Format-Table" also disappears! However, if you do retain it, recall that the output of the Select-Object cmdlet is a PSCustomObject and not a simple variable. For you to use it, pipe the $num_java_used_cpu into the Format-Table. You could probably remove the "-First 1" from the last Select-Object, too.

0 Votes 0 ·

Sorry, my format is not very good .
Yes, i need $num_java_used_cpu in the later ( i will compare it with threshold in the later).
for example, if the output ( with your scripts) is as below :

InstanceName CPU


java 46

Then what i need is 46 (int type) , i will compare it with a threshold(like 30,40 in the later ) .
what change need to be done with your scripts ?

Thanks you in advance.

0 Votes 0 ·
Show more comments
cooldadtx avatar image
0 Votes"
cooldadtx answered cooldadtx commented

$java_used_cpu1 is an array, not a string, hence the error.

Get-Counter will return back multiple results. Therefore your $java_used_cpu_string is an array. Using findstr just filters that array down. Using replace on the next line runs it for each array element. At this point you have 0 or more possible values.

If you only ever expect a single value to come back from the Get-Counter call then after the findstr call pipe to select-object -first 1.

$java_used_cpu_string = Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' | Select-Object -ExpandProperty countersamples| Select-Object -Property instancename, cookedvalue| ? {$_.instanceName -notmatch "^(idle|total|system)$"} | Sort-Object -Property cookedvalue -Descending| Select-Object -First 5| ft InstanceName,@{L='CPU';E={($.Cookedvalue/100/$env:NUMBER_OF_PROCESSORS).toString('P')}} -AutoSize |findstr java | Select-Object -First 1
$java_used_cpu1 = $java_used_cpu_string -replace "^.+?\s+(.+)$",'$1'
$java_used_cpu = $java_used_cpu1.Substring(0,$java_used_cpu1.Length-1)
$num_java_used_cpu = [int]$java_used_cpu


That should limit the results to 1, assume there was at least one instance running.

· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

there still an error for 3:
$java_used_cpu = $java_used_cpu1.Substring(0,$java_used_cpu1.Length-1)

Method invocation failed because [System.Object[]] does not contain a method named 'Substring'.
At D:\restart_dma_cpu_high.ps1:22 char:1
+ $java_used_cpu = $java_used_cpu1.Substring(0,$java_used_cpu1.Length- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound



0 Votes 0 ·
cooldadtx avatar image cooldadtx YonglongYL44Wang-5709 ·

That's because in the middle of your query you have added Select-Object -First 5 which is requesting the first 5 entries. But to me that doesn't make sense because you are looking for a specific process java. If you select the first 5 then if it isn't in the first 5 you'll not find it even though it is there. The select/sorting should be run after all your conditions are completed.

$java_used_cpu_string = Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' | Select-Object -ExpandProperty countersamples| Select-Object -Property instancename, cookedvalue| ? {$_.instanceName -notmatch "^(idle|total|system)$"} | ft InstanceName,@{L='CPU';E={($.Cookedvalue/100/$env:NUMBER_OF_PROCESSORS).toString('P')}} -AutoSize |findstr java | Sort-Object -Property cookedvalue -Descending | Select-Object -First 1


The selection top logic should be last after the sorting occurs after the filtering has happened.

0 Votes 0 ·
LimitlessTechnology-2700 avatar image
0 Votes"
LimitlessTechnology-2700 answered

Hello YonglongYL44Wang

I would recommend the next article regarding the calling of substring in variables: https://social.technet.microsoft.com/Forums/windowsserver/en-US/9363666b-cb2b-4cf7-9a96-290030ec8df0/problems-using-substring-method?forum=winserverpowershell



--If the reply is helpful, please Upvote and Accept as answer--

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.