Measure actual clock speed via powershell during an intensive task - powershell

I have the following script to measure the current cpu clock rate from this [link][1].
$MaxClockSpeed = (Get-CimInstance CIM_Processor).MaxClockSpeed
$ProcessorPerformance = (Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance").CounterSamples.CookedValue
$CurrentClockSpeed = $MaxClockSpeed*($ProcessorPerformance/100)
I am looking to test the performance of the CPU to see how far it can go in terms of frequency.
The reason for this is that we have a few machines that are faulty out of our hundreds of machines, and it turns out that when you push them a bit, their clock rate doesn't change and stays at around 20% utilization. This would allow us, via our monitoring system, to find them easily.
Is there a way to programmatically via powershell to make an intensive task during or just before capturing the actual clock speed to know how far it can get? Something like a loop or something?
[1]: Unable to get current CPU frequency in Powershell or Python

I found something interesting on this website.
So to make the cpu work at 100% for a short time, I can use a background job:
$NumberOfLogicalProcessors = Get-WmiObject win32_processor | Select-Object -ExpandProperty NumberOfLogicalProcessors
ForEach ($core in 1..$NumberOfLogicalProcessors){
start-job -ScriptBlock{
$result = 1;
foreach ($loopnumber in 1..2147483647){
$result=1;
foreach ($loopnumber1 in 1..2147483647){
$result=1;
foreach($number in 1..2147483647){
$result = $result * $number
}
}
$result
}
}
}
Read-Host "Press any key to exit..."
Stop-Job *
It makes the cpu go usually at 100% of utilization. During that time I can easily run the script:
$MaxClockSpeed = (Get-CimInstance CIM_Processor).MaxClockSpeed
$ProcessorPerformance = (Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance").CounterSamples.CookedValue
$CurrentClockSpeed = $MaxClockSpeed*($ProcessorPerformance/100)
For instance, in my case, when I test the $processorPerformance I get "107.998029830411" as an example, so this shows My processor works fine when I push it.
N.B I must add the Start-sleep -Seconds 20 parameter while the background tasks are running, because on all the machines it takes around 15 seconds until the x logical processors are running at 100%.

Related

MSAcpi_ThermalZoneTemperature won't refresh

I want to read temperature sensors from my motherboard in PowerShell 5.1. Unfortunately the corresponding WMI-object won't fetch new values if I call it more than once. Even restarting PowerShell won't help. The only way to get new data is to reboot my PC and run the code again...
My code:
Write-Host "Temperatures:"
Write-Host "-------------"
$ThermalZones = Get-WmiObject -Class MSAcpi_ThermalZoneTemperature -Namespace "root/wmi"
$ThermalZones = $ThermalZones | Where -Property CurrentTemperature -gt 0
$ThermalZones | ForEach {"$($_.InstanceName.Replace('ACPI\ThermalZone\', '')): $($_.CurrentTemperature / 10 - 273) [°C]"}
I noticed there is a "SamplingPeriod" property for each zone which is 0 by default every time I re-run the code but changing it seems to have no effect... Can I somehow force a refresh?
The temperature is updated, if Speedfan is started.
This is one way to force the refresh.
Or log off an log on again.
Unfortunately the parameter SamplingPeriod can not be set but only requested.

Start-sleep unexpected behavior

I expected the following code to complete in about one second.
It executes in about 20 seconds:
$i = 0; do{sleep -Milliseconds 1; $i=$i+1}while($i -lt 1000)
Could you please suggest why? I'm not able to find any clues in docs.
Thanks in advance!
Calling a cmdlet comes at a cost. Just because you use Start-Sleep -Milliseconds 1, doesn't mean it's going to take 1ms. This is because that cmdlet has overhead it needs to take care of behind the scenes, like setting up the timer, instantiating objects, etc.
Measure-Command { Start-Sleep -Milliseconds 1 }
# TotalMilliseconds : 25.1157
See the above...even though I told it to only run for 1ms, it still took 25ms because of the overhead. This overhead won't be exactly the same every time, but you should always expect there to be some.
On my computer, it seems to average about 16ms of overhead per call. So if you run that 1000 times, then on average, it's going to take 16 seconds to run, just for the sleep alone.
I obtained the average by running this a few times:
Measure-Command { 1..100 | % { Start-Sleep -Milliseconds 1 } }
It's like driving a car. You don't just hop in a car and go, you need to start it up first, and there's things going on behind the scenes the car needs to do in order to start. And that takes a little bit of time.

How do you get Windows PowerShell to play a sound after .bat job has finished running?

As the title states, I have a .bat job running within PowerShell that when finished running, I would like a sound notification to go off. I was wondering if there was a PowerShell command that I can add to my existing PowerShell command.
In addition to the solutions #TheGameiswar suggests, you can have some fun by making the system actually speak to you:
# Create a new SpVoice objects
$voice = New-Object -ComObject Sapi.spvoice
# Set the speed - positive numbers are faster, negative numbers, slower
$voice.rate = 0
# Say something
$voice.speak("Hey, Harcot, your BAT file is finished!")
Note: I only tested this on Windows 10, so it may not work on other versions, but give it a go and see.
Besides the excellent solutions of boxdog (here) and TheGameiswar (here), I want to mention another possibility, which lets you play some standard system sounds:
[System.Media.SystemSounds]::Asterisk.Play()
[System.Media.SystemSounds]::Beep.Play()
[System.Media.SystemSounds]::Exclamation.Play()
[System.Media.SystemSounds]::Hand.Play()
[System.Media.SystemSounds]::Question.Play()
Another text-to-speech approach
Add-Type -AssemblyName System.Speech
$synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$synth.Speak("Hey $env:USERNAME, your job is finished!")
Customization
For full details, read the docs.
Voice
Select a voice:
$synth.SelectVoice("Microsoft Zira Desktop")
You can view available voices with:
$synth.GetInstalledVoices() | Select-Object -ExpandProperty VoiceInfo
Rate
Set the speaking rate from -10 (slow) through 10 (fast):
$synth.Rate = 5
Volume
Set the volume from 0 (quiet) through 100 (loud):
$synth.Volume = 75
you could use powershell automatic variables to check bat file status ..As per this,$? returns true ,if command is successfull..
below is sample code
$a =Invoke-Command -ScriptBlock {
& "C:\temp1\test.bat"
}
if($?){
[console]::beep(500,300)
}
You could also play custom sounds,
$PlayWav=New-Object System.Media.SoundPlayer
$PlayWav.SoundLocation=’C:\Foo\Soundfile.wav’
$PlayWav.playsync()
references:
https://devblogs.microsoft.com/scripting/powertip-use-powershell-to-play-wav-files/

How to stop a powershell block after a timeout for powershell script

I want to invoke the command
$myArray = Get-Wmiobject -Class Win32-printer
But, on rare occasions, this command sometimes never fails nor succeed, returning the list of available printer.
I would like to assign $myArray only if the invocation takes less than a few seconds, lets say 5. Otherwise, I want to display a dialog telling that printers are unavailable at this moment.
How to start a powershell block with a timeout?
You can use a job for that:
$job = Start-Job { Get-Wmiobject -Class Win32-printer }
$job | Wait-Job -Timeout 5
if ($job.State -eq 'Running') {
# Job is still running, cancel it
$job.StopJob()
} else {
# Job completed normally, get the results
$myArray = $job | Receive-Job
}
I would say to create your own customized WMI queries using type casting and the native .NET providers. This way the work is still being done in the same opened console and you have physical control on the time outs.
I basically had the same frustration as you did. I would be querying servers all day until I hit the one that had a broken WMI. After so much, I started researching how to create my own WMI function to get around this. That was my solution to the problem. Learned a lot along the way.
Here is an article to help you along your way.
http://stevenmurawski.com/powershell/2009/01/dealing-with-wmi-timeouts/
Just to add to the above- powershell also has a built in stopwatch diagnostic for timeout functionality.
https://technet.microsoft.com/en-us/magazine/2009.03.heyscriptingguy.aspx

Sending a Refresh() to WMI in PowerShell

In a PowerShell script I am trying to get the number of page faults per second with this command:
(Get-WmiObject Win32_PerfFormattedData_PerfOS_memory).PageFaultsPersec
Unfortunately, it reads always the same value because I don't Refresh() the performance counter.
How can I send a Refresh() method to Performance Data via PowerShell?
You can get the value using performance counters:
Get-Counter '\Memory\Page Faults/sec'
However, if I call you code in a loop, it works without problems (although it is better practise to first store the wmi object).
1..10 | % { sleep -sec 2; (Get-WmiObject Win32_PerfFormattedData_PerfOS_memory).PageFaultsPersec }