How do I write this Powershell Function More Efficently?

General Tech Learning Aids/Tools 2 years ago

0 2 0 0 0 tuteeHUB earn credit +10 pts

5 Star Rating 1 Rating

Posted on 16 Aug 2022, this text provides information on Learning Aids/Tools related to General Tech. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Take Quiz To Earn Credits!

Turn Your Knowledge into Earnings.

tuteehub_quiz

Answers (2)

Post Answer
profilepic.png
manpreet Tuteehub forum best answer Best Answer 2 years ago

 

I.ve come at this many different ways and looked on alot of sites about Efficient Powershell Scripts but I still could use help making this script more efficient...It uses 3-4% of CPU. The Main Drag on the processor is the MainLogic function. It is nested in a While($true) loop at the start of the body of my script and runs all the time...when certain parameters in the MainLogic function change the function breaks and certain if then statements are tested in the body of the script. I'm trying to learn how to write more efficient code ...Im practicing to be a Lisp Developer and I think a good lesson on Powershell efficiency would be good for us all . I've rewritten this script 3 times and I still need help making it better...I see most windows process use almost no CPU and they run all the time and are very smart code. I'd love to be that good. I need everything in the script\I have to test all he things tested in the script. I commented it alot to aid in someone helping me

Ive tried these things:

  • Am I using the right construct for this situation? I've come at this one many way's...I think I am but there might be a better mathematical approach....I'm learning Linear Algebra to Help me with this.
  • Am I doing too many or unnecessary operations? That's my main Question....could use help with new ideas
  • Am I working with too many objects? not sure if there is another way ....I think I used the minimum ojects but is Getwmiobject better than Get-Process? etc.
  • Is the pipeline the best approach? I think I pipelined well
  • Is there another command model that may work better? I googled but can't find command model pertaining to Powershell
  • Am I thinking about objects properly? Can't seem to find on Google a good PowerShell object lesson I have read 1 1\2 Powershell books though but there was no similar code to mine in them
  • Am I using -Filter (if available)? not available for Get-Process
  • Am I reinitializing variables unnecessarily? No reinitialization
  • Are my loops designed efficiently? I think I designed them the best way - a while($true) nested inside another while($true) so I'm not running my whole script every loop....I need all the stuff in the MainLogic Function (My loop that runs all the time)
  • Am I using Foreach-Object when for will work just as well? not applicable
  • Do I retrieve values once, and save in a variable if needed again later?...I do this
  • Are you passing large collections to the pipeline instead of storing in an object?...Not doing This
  • Am I testing a condition unnecessarily? Am I?

Is this just a big script or am I not seeing the big picture as far as coding....pls cite online resource to help me write more efficient code, If you see Holes in my Logic.

Here is my script: the MainLogic Function is the Processor hog and all that needs to be looked at....I added the rest to aid in my assistance. Thanks in Advance

#this function is ran by itself in a while($true) loop and is the main place in my script where information 
about Firefox.Skype and VPN Processes is gathered.
function global:MainLogic()
{

#Monitor Skype WorkingSet for any changes - If change is detected the change it is processed under the
#"Skype Logic" Section to find out if a Skype call is in progress. 
$SkypeProcess1 = get-process | where-object {$_.ProcessName -eq "skype"}
ss -s 1
$SkypeProcess2 = get-process | where-object {$_.ProcessName -eq "skype"}

$SkypeWsDiff = $SkypeProcess2.workingset - $SkypeProcess1.workingset

###Skype Logic###

#Test Skype Call Status and if changed break from this function in the ###SKype Break### sectiom below and 
#check all parameters in body of script.

$y = $x
wo "`$x `= $x"
wo "`$y `= $y"

#Testing Information gathered in above section to see if Skype call in progress.

if($SkypeWsDiff -gt 8000000){$x = 1}
elseif($SkypeWsDiff -lt -11000000){$x = 2}
wo "Function2 `$x `= $x"
if ($x -eq 1){wo "Skype Telephone Call in Progress"
}
if ($x -eq 2){wo "Skype Telephone Call not in Progress"
}
wo "`$SkypeWsDiff `= $SkypeWsDiff"

###SKype Break###
if($y -ne $x){wo "Skype changed - break"
break}
wo "`$x `= $x"
wo "`$y `= $y"
#Skype Logic End

#Firefox Status gathered below and saved to variable $a is saved to variable $b here and stored to compare later 
#with variable $a to see if Firefox Status changed.

$b = $a
wo "`$a `= $a"
wo "`$b `= $b"


#VPN Status gathered below and saved to variable $c is saved to variable $d here and stored to compare later 
#with variable $c to see if VPN Status changed.

$d = $c
wo "`$c `= $c"
wo "`$d `= $d"

#Firefox and VPN status are saved here to variables for comparison later and above this section in the script.
if(ps firefox -ea 0){$a = 3 ; wo "Firefox is Open"
}
if(-not(ps firefox -ea 0)){$a = 4 ; wo "Firefox is Closed"
}
if(ipconfig | Select-String 'PPP adapter'){$c = 5 ; wo "VPN is Connected"
}
if((
                                                
                                                
0 views
0 shares
profilepic.png
manpreet 2 years ago

CPU usage of 3-4% isn't that much. That being said, use Measure-Command to see which statements consume time and which are not.

In the general sense, try and avoid unecessary work. That is, some commandlets provide built-in filtering. For such, piping output to ? is wasteful. Consider Get-Process:

Measure-Command -Expression { get-process | ? { $_.processname -eq "iexplore" } }
Measure-Command -Expression { get-process -name "iexplore"  }

In my system the first one takes about 13 ms on the average. The second one takes about 1.5 ms. The improvement is about a decade.

In addition, consider storing command results into variables instead of re-running the commands all the time. For example, the code is littered with statements like ipconfig | Select-String. Instead of those, store the output into a variable and update the variable only when necessary.


0 views   0 shares

No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.