Windows Powershell
If there is no appropriate context menu item on your system you can create one by using the following reg file to adapt the registry:
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\shell\PowerShell] @="Open PowerShell window here" [HKEY_CLASSES_ROOT\Directory\shell\PowerShell\Command] @="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command [Environment]::CurrentDirectory=(Set-Location -LiteralPath:'%L' -PassThru).ProviderPath\""Please check version and path of your powershell executable. Store contents within file PowerShellFromHere.reg and double click on it.
When you finally have succeeded with clicking the menu item the PowerShell window will show an appropriate prompt for the location where it has been opened:
Within the command window you can directly enter PowerShell commands (e.g. "Get-ChildItem", probably better known under its shortcut "dir"). If you have some scripts of your own, you can start them and provide all needed arguments within command line.
# File: HelloWorld.ps1 write-host "Hello world!"To start the script enter "./HelloWorld.ps1" within PowerShell window. As you might have expected the following output is generated:
PS D:\\Gerald\TEMP> ./HelloWorld.ps1 Hello world! PS D:\\Gerald\TEMP>If you have problems with starting a script on your machine, you might have to set the appropriate security policy within the PowerShell window:
PS D:\\Gerald\TEMP> Set-ExecutionPolicy unrestricted
:: File: CheckBuildResults.cmd :: Start powershell script, suppress command window, but write :: output to logfile PowerShell.exe -WindowStyle Hidden ./CheckBuildResults.ps1 >CheckBuildResults.run.log :: Start powershell script and suppress command window ::PowerShell.exe -WindowStyle Hidden ./CheckBuildResults.ps1 :: Start powershell script within command window ::PowerShell.exe ./CheckBuildResults.ps1
You can start script execution with a selfdefined keystroke, a hotkey. To define a hotkey for your script perform the following steps:
Within the ISE there are three sections:
# File: Example.ps1 # Global variables and definitions [int]$script:counter # script global counter # User defined functions function MyFirstFunction() { # break statement into several lines: $sum = $x ` + $y } # Main part of the script # directly use script statements and call functions ...You can use "#" to mark the rest of the line as a comment.
To break a longer statement for better readability into several lines you have to use a special line-continuation character: the trailing back-tick ` (yes this is not a spot of dust on your monitor, this is the character to use)
[int]$counter = 5 # 32 bit signed integer [long]$numRecords = 100 # 64 bit signed integer [double]$pi = 3.14 # 64 bit floating-point number [bool]$isFemale = $true # boolean true/false [string]$info = "-" # string of unicode characters [char]$ch # unicode character [byte]$num # 8 bit number
# Example: Define an array of test names $myDefinedTests = New-Object System.Collections.ArrayListWorking with such an ArrayList is simple:
# add an entry $myDefinedTests.Add($testName) #remove an entry $myDefinedTests.Remove($someTest) # check if an element is already contained if ($myDefinedTests.Contains($someTest)) { ... } # get total number of contained elements $numElements = $myDefinedTests.Count # clear array # (unwanted output from execution is suppressed via # piping to null device) $myDefinedTests.Clear() | Out-Null
function CreateMyDataStruct([bool]$in_flag,[string]$in_info, [int]in_number)) { $newObject = New-Object Object $newCheckInfo | Add-Member NoteProperty isFemale $in_flag $newCheckInfo | Add-Member NoteProperty name $in_info $newCheckInfo | Add-Member NoteProperty age $in_number return $newObject }Using the data struct:
[System.Object]$person = CreateMyDataStruct $true "Mrs. Smith" 36 if (-not $person.isFemale) { write-host $person.name "is of age" $person.age }
Operator | Meaning |
-and | and |
-or | or |
-not | not |
! | not |
Operator | Meaning |
-eq | is equal to |
-ne | is not equal to |
-ge | greater than or equal to |
-gt | greater than |
-le | less than or equal to |
-lt | less than |
if (($num -gt 0) -and (-not ($num -eq 17))) { # do something }
if ($condition) { } if ($condition) { } else { } if ($condition) { } elseif ($otherCondition) { } else { }
[int]$num = 7 switch ($num) { 1 {write-host "one"} 2 {write-host "two"} default {write-host "other value"} }
switch ($num) { {$_ -gt 2} {write-host "greater 2"} {($_ -gt 5) -and ($_ -lt 10)} {write-host "greater 5 and less 10"} default {write-host "something else"} }Output:
greater 2 greater 5 and less 10
{$_ -gt 2} {write-host "greater 2"; break}
for ($i=0; $i -lt 7; $i++) { ... }
foreach ($element in $container) { # do something with $element }
while ($condition) { # do something }
do { # do something } while ($condition)You can use "break" to leave a loop or "continue" to continue with the next loop cycle.
function GetSum([int]$in_x, [int]$in_y) { [int]$sum = $in_x + $in_y return $sum }Calling your function:
[int}$someVal = 17 [int]$result = GetSum $someVal 4 # here $result has value 21
$result = GetSum $someVal # result is 17, missing argument is replaced by 0 $result = GetSum $someVal 4 5 6 # result is 21, last arguments (5, 6) are ignored $result = GetSum $someVal (4 + 5 + 6) # result is 32, the expression within brackets is evaluated before # it gets passed to the function as second argument
function GetSum([int]$in_x, [int]$in_y) { # this is a message written to screen, and not a message to # output, i.e. this is not part of the returned values write-host "calculating..." [int]$sum = $in_x + $in_y # the follwing lines will return 3 different values [string]$info = "hello" $info # pass to output 3.14 * 2 # pass to output return $sum # pass to output }Calling the function
[int]$someVal = 17 # here $result is no longer of type int, omitting type # specification will allow implicit setting of appropriate # type $result = GetSum $someVal 4 write-host "Result=" $resultOutput
calculating... Result= hello 6,28 21
Attention:
Trying to change a local variable within an subordinate scope results in
creating a new variable within the called scope. Changes will not affect
the original variable within the enclosing scope.
[int]$counterA = 1 # local per default, readable within this script [int]$script:counterB = 1 # readable and writable within this script function IncrementCounters ([int]$in_level) { [string]$funcInfo = "IncrementCounters-" + $in_level + ": " # all variables can be read without specifying scope: write-host "" write-host ($funcInfo + "counterA=" + $counterA) write-host ($funcInfo + "counterB=" + $counterB) write-host "" write-host ($funcInfo + "now incrementing all counters...") # changing counterA causes creation of a new variable # within new scope to store the changed value! $counterA += 1 # for changing value of script variable explicitly # use "script" specification otherwise # a new variable would be created $script:counterB += 1 write-host "" write-host ($funcInfo + "counterA=" + $counterA) write-host ($funcInfo + "counterB=" + $counterB) write-host "" if ($in_level -eq 1) { IncrementCounters 2 write-host "" write-host ($funcInfo + "counterA=" + $counterA) write-host ($funcInfo + "counterB=" + $counterB) write-host "" } } #----- main ----- write-host "" write-host ("main: counterA=" + $counterA) write-host ("main: counterB=" + $counterB) write-host "" IncrementCounters 1 write-host "" write-host ("main: counterA=" + $counterA) write-host ("main: counterB=" + $counterB) write-host ""Output
main: counterA=1 main: counterB=1 IncrementCounters-1: counterA=1 IncrementCounters-1: counterB=1 IncrementCounters-1: now incrementing all counters... IncrementCounters-1: counterA=2 IncrementCounters-1: counterB=2 IncrementCounters-2: counterA=2 IncrementCounters-2: counterB=2 IncrementCounters-2: now incrementing all counters... IncrementCounters-2: counterA=3 IncrementCounters-2: counterB=3 IncrementCounters-1: counterA=2 # scope level 1 is not changed! IncrementCounters-1: counterB=3 main: counterA=1 # main scope is not changed! main: counterB=3
Attention:
Trying to change a private variable within an subordinate scope results in
creating a new variable within the called scope. Changes will not affect
the original variable within the enclosing scope.
[int]$private:counterC = 1 # visible only within main scope function ReadCounter () { # private variable value is not available here: write-host ("ReadCounter: counterC=" + $counterC) write-host ("ReadCounter: private:counterC=" + $private:counterC) write-host "" } function PassPrivateValue ([int]$in_someValue) { write-host ("PassPrivateValue: in_someValue=" + $in_someValue) $in_someValue += 5 # change is not visible outside the function write-host ("PassPrivateValue: in_someValue=" + $in_someValue) } #----- main ----- write-host ("main: counterC=" + $counterC) write-host "" # no read access ReadCounter # private variable is changeable only within scope of definition $private:counterC += 1 $counterC += 1 # scope specification is not necessary write-host ("main: counterC=" + $counterC) write-host "" # for read access private variables can be explicitly passed to a function PassPrivateValue $counterC write-host "" write-host ("main: counterC=" + $counterC)
main: counterC=1 ReadCounter: counterC= # value is not available ReadCounter: private:counterC= main: counterC=3 PassPrivateValue: in_someValue=3 PassPrivateValue: in_someValue=8 # changed value is not visible outside main: counterC=3
Format expression with several values: "any text {0..} any text {1..} .." - f $val1, $val2, ..
# Formatting of double values, # first column left justified with leading zeros, various precisions # second column right justified with precision 2 $someValue = 3.45678 $otherValue = 145.678 "{0,-10}{1,10:N2}" -f $someValue, $otherValue "{0,-10:0#.00 }{1,10:N2}" -f $someValue, 8.1 "{0,-10:0#.000}{1,10:N2}" -f ($someValue*3), ($otherValue * 2) write-host "" # Percentage, first column right adjusted "{0,5:P1} {1,-20}" -f (10 / 200),"Small percentage" "{0,5:P1} {1,-20}" -f 0.9567, "High percentage"
3,45678 145,68 03,46 8,10 10,370 291,36 5,0% Small percentage 95,7% High percentage
Within the script you have to attach an "output level" to each text line. The principle here is: the more important the information is the smaller the attached output level is. Depending on the current value for the script variable $OUTPUT_LEVEL_STDOUT the output of the given text will be suppressed (if the script variable is less than the output level attached to the given text).
[int]$OUTPUT_LEVEL_STDOUT = 1 # add your comments here (depending on your usage of WriteLine): # 0 : no output # 1 : basic output for regular usage of the script # 2 : more detailed output # 3 : trace information for debugging
# Write output to stdout. # Depending on the configured output level call may be ignored. function WriteLine ($in_outputLevel, [string]$in_info) { if ($in_outputLevel -le $OUTPUT_LEVEL_STDOUT) { write-host $in_info } }
[int]num = 5 WriteLine 1 "This is an important information" WriteLine 3 ("DetailedInfo: num=" + $num)
#Generate a formatted time stamp function CurTime { $t = (Get-Date -format T) return $t }
#using built-in function write-host write-host "The current time is" ((CurTime) + ". This is really late.") #using helper WriteLine (see slightly different syntax for combining strings) WriteLine 1 ("The current time is " + (CurTime) + ". This is really late.") #Remark: Omitting the brackets around CurTime does not work. The rest of # the line would be regarded as possible (but not needed) parameters for # CurTime and therefore would be ignored completelyOutput:
The current time is 13:10:10. This is really late. The current time is 13:10:10. This is really late.
The function expects an arbitrary string starting with the date, e.g. "2011/12/02...." or "2011-12-02....". For both cases the function returns the date in german format "02.12.2011". Additional string contents after the date are ignored.
# Transform date from "2011/12/02...." to "02.12.2011" function ParseAndTransformDate ([string]$in_date) { [string]$date = $in_date.Substring(8,2) + "." $date += $in_date.Substring(5,2) + "." + $in_date.Substring(0,4) return $date; }
As you can automatically generate the contents for both email subject and message body the receiver can be provided with sufficient context information about the problem.
The sending of an email has to be organized with use of the mail server existing in your environment. Depending on the needed security and authentication procedures you have to specify more or less authentication data.
Within office environments there are often the following situations:
[string]$MY_EMAIL_ADDRESS = "Somebody@SomeCompany.com" [string]$MAIL_SMTP_SERVER = "SomeCompany.smtp.server" [int] $MAIL_PORT = 567 [bool] $MAIL_USE_WINDOWS_LOGON_ACCOUNT = $true # true if mail logon is required [bool] $MAIL_USE_EXTERNAL_MAIL_ACCOUNT = $false
$MY_EMAIL_ADDRESS = "mail@gerald-fahrnholz.de" $MAIL_SMTP_SERVER = "mail.gerald-fahrnholz.de" $MAIL_PORT = 25 $MAIL_USE_WINDOWS_LOGON_ACCOUNT = $false $MAIL_USE_EXTERNAL_MAIL_ACCOUNT = $true $MAIL_EXTERNAL_USER = "YourUserName" $MAIL_EXTERNAL_PASSWORD = "YourPassword"
function SendEmailToMyself ($subject, $info) { SendEmailTo $MY_EMAIL_ADDRESS $subject $info } #---------------------------------------------------------- function SendEmailTo ($to, $subject, $info) { WriteLine 3 "Sending email..." $from = $MY_EMAIL_ADDRESS $body = $info WriteLine 3 ("To : " + $to) WriteLine 3 ("SmtpServer : " + $MAIL_SMTP_SERVER) if ($MAIL_USE_WINDOWS_LOGON_ACCOUNT) { WriteLine 3 ("Using windows login for authentication") $SMTPClient = New-Object Net.Mail.SmtpClient($MAIL_SMTP_SERVER, $MAIL_PORT) $SMTPClient.UseDefaultCredentials = $true # $SMTPClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network $SMTPClient.EnableSsl = $false $SMTPClient.Send($from, $to, $subject, $body) } elseif ($MAIL_USE_EXTERNAL_MAIL_ACCOUNT) { WriteLine 3 ("Using external mail account for user " + $MAIL_EXTERNAL_USER) $SMTPClient = New-Object Net.Mail.SmtpClient($MAIL_SMTP_SERVER, $MAIL_PORT) $SMTPClient.EnableSsl = $false $SMTPClient.Credentials = New-Object System.Net. NetworkCredential($MAIL_EXTERNAL_USER, $MAIL_EXTERNAL_PASSWORD); $SMTPClient.Send($from, $to, $subject, $body) } else # simple mail without authentication { Send-MailMessage -To $to -Subject $subject -From $from -Body $body -SmtpServer $MAIL_SMTP_SERVER } WriteLine 3 "...email was sent" }
[string]title = "..." [string]info = GetDetailedInfoFromSomewhere() SendEmailToMyself ($title + " - (automated mail info)") $info
Within a PowerShell script you can process the closed event of the balloon. But to do so you would need an event loop within your script. To limit programming efforts and nevertheless have a practicable solution for simple sequential scripts in the following a simpler mechanism for closing balloons is presented.
# Prepare usage of system tray balloon [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null [System.Windows.Forms.NotifyIcon]$script:balloon = $null
function OpenBalloon ($title, $info) { # get the icon from the running process $path = Get-Process -id $pid | Select-Object -ExpandProperty Path $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) # open balloon $script:balloon = New-Object System.Windows.Forms.NotifyIcon $script:balloon.Icon = $icon $script:balloon.BalloonTipIcon = 'Info' $script:balloon.BalloonTipTitle = $title $script:balloon.BalloonTipText = $info $script:balloon.Visible = $true WriteLine 3 "Open balloon..." $script:balloon.ShowBalloonTip(60) # timeout value did not work! # simple alternative method: # wait for some time then delete balloon and proceed with script # Start-Sleep -Seconds 30 # $script:balloon.dispose() WriteLine 3 "...proceed script execution while balloon is open" }The function AlertInSystemTray closes an eventually still existing balloon and displays the given text within a new balloon. In this way you are sure that a running script only displays the latest message and the user has not to close many outdated balloons one by one.
function AlertInSystemTray ([string]$in_title, [string]$in_info) { # Remark: # This script runs sequentially and does not support any event loop. # Therefore we do not call register-objectevent for the closed event # of the balloon. Instead we will dispose the old balloon each time # before we open a new balloon for the next message if ($script:balloon) { # in any case close the balloon which may still be open from last message WriteLine 3 "Deleting balloon" $script:balloon.dispose() $script:balloon = $null } if ($in_info -ne "") { # open new balloon only when there is something to report OpenBalloon $in_title $in_info } }
[string]$title = "..." [string]$info = GetDetailedInfoFromSomewhere() AlertInSystemTray $title $info
PowerShell scripts may often run without a user watching for the progress of the script. There may be good reasons to continue script execution also in the case the user does not confirm the message box or answer the request. For these cases there is the possibility to limit the time period for displaying the message box. When the time period has elapsed the message box will close automatically and the script execution continues.
[int]$MSGBOX_MAX_REPEAT = 3 # if user does not confirm the # msgbox with "Yes" the msg box will be # closed and reopened the given number of times
Within the implementation body of the function you can adjust the period of time for visibilty and invisibility.
function OpenMsgBox ($title, $info) { # Configure messages and waiting times $message = $info $maxDisplayTimeInSeconds = 15 # if user does not confirm, # close message box automatically $repeatAlertAfterSeconds = 4 # if user does not confirm, # repeat alert after N seconds $delayedReminderWaitSeconds = 60 # delay alert for another N seconds if user # clicks "NO" # Create a single instance of scripting host to open message boxes $ws = new-object -comobject wscript.shell $repeatCounter = $MSGBOX_MAX_REPEAT do { WriteLine 3 ("MsgBox " + (CurTime) + " Open MsgBox...") # Open message box $constYesNoButton = 4 $buttonClick = $ws.popup($message,$maxDisplayTimeInSeconds, $title,$constYesNoButton) $repeatCounter -= 1; # Process anwser $constYesButton = 6 $constNoButton = 7 $constTimeout = -1 if ($buttonClick -eq $constYesButton) { # we are finished, terminate execution WriteLine 3 ("MsgBox " + (CurTime) + " ... user has confirmed") $waitSeconds = 0 } else # timeout or user has clicked NO { if ($buttonClick -eq $constTimeout) { WriteLine 3 ("MsgBox " + (CurTime) + " ... user did not react, repeat alert after a short while") $waitSeconds = $repeatAlertAfterSeconds } elseif ($buttonClick -eq $constNoButton) { WriteLine 3 ("MsgBox " + (CurTime) + " ... user wants to prolong waiting time") $waitSeconds = $delayedReminderWaitSeconds } else { WriteLine 3 ("MsgBox " + (CurTime) + " ... unexpected answer, repeat alert immediately") $waitSeconds = 2 } } if (($waitSeconds -gt 0) -and (($repeatCounter -gt 0))) { WriteLine 3 ("MsgBox " + (CurTime) + " waiting another " + $waitSeconds + " seconds...") Start-Sleep -Seconds $waitSeconds } if (($waitSeconds -gt 0) -and ($repeatCounter -eq 0)) { WriteLine 3 ("MsgBox " + (CurTime) + " ... giving up, user is sleeping") } } while (($waitSeconds -gt 0) -and ($repeatCounter -gt 0)) }
[string]$title = "..." [string]$info = GetDetailedInfoFromSomewhere() OpenMsgBox $title $info
For more infos about message boxes see Popup method within Windows scripting host (Microsoft MSDN library)
Popular ways of notification are:
# Activate one or more alert targets to get informed about important events. # If at least one alert target is active you could call this script from # cmd file with option "-WindowStyle Hidden" to make the cmd shell completely # invisible [bool]$ALERT_AS_SYSTRAY_BALLOON = $true [bool]$ALERT_AS_MESSAGE_BOX = $false [bool]$ALERT_AS_EMAIL = $true
# Alerts the user about the given info text. If text is empty # call will be ignored. function Alert ([string]$in_title, [string]$in_info) { # ----- Open balloon within system tray ----- if ($ALERT_AS_SYSTRAY_BALLOON) { AlertInSystemTray $title $info } # ----- Send email ----- if ($ALERT_AS_EMAIL) { if ($in_info -ne "") { SendEmailToMyself ($in_title + " - (automated mail info)") $in_info } } # ----- Open message box ----- if ($ALERT_AS_MESSAGE_BOX) { if ($in_info -ne "") { OpenMsgBox $in_title $in_info } } }
[string]title = "..." [string]info = GetDetailedInfoFromSomewhere() Alert $title $info
$web = New-Object System.Net.WebClient [string]$webAddress ="https://www.gerald-fahrnholz.de/small_pages/links.htm" [string]$pageContents = $web.DownloadString($webAddress) # write to stdout write-host $pageContents # or parse the returned string...
[string]$parentDirToExamine = "D:\Test" [int]$numRelevantEntries = 3 # Step 1: get all elements of parent directory # Remark: explicitly define array type otherwise you may # get only a single element and not an array which may # prevent you from examining the number of elements within # the array [System.Object[]]$subDirs = get-childitem $parentDirToExamine | # Step 2: get directory elements which are folders where {$_.PsIsContainer} | # Step 3: sort them with descending LastWriteTime, # i.e. newest entry is the first sort-object -property LastWriteTime -descending | # Step 4: from this ordered set we are only interested # on the first N elements (parent dir may contain less entries) select-object -first $numRelevantEntries # write found results to stdout write-host "Num entries found: " + $subDirs.Count) foreach ($subDir in $subDirs) { write-host $subDir.Name }
[string]$dirPath = "C:\Temp" $allFiles = get-childitem $dirPath $bmpFiles = $allFiles | where {$_.extension -eq ".bmp"}
# get current wallpaper $oldWallpaper = Get-ItemProperty -path 'HKCU:\Control Panel\Desktop\'` -name Wallpaper write-host "Current wallpaper: " $oldWallpaper.Wallpaper # path to picture in bitmap format [string]$newBmpFile = "C:\TEMP\SomePicture.bmp" # Set new wallpaper by changing values within registry Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name Wallpaper ` -value $newBmpFile -Force # display centered and stretched Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' ` -name TileWallpaper -value "0" Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' ` -name WallpaperStyle -value "2" # activate changed registry settings rundll32.exe user32.dll,UpdatePerUserSystemParameters
The simple concept of time controlled polling may help in all these situations:
# repeat the script execution every 2 minutes # specifying 0 means: script is executed only once [int]$REPEAT_CHECK_AFTER_SECONDS = 120 do { # perform some checks (e.g. call some functions) ... if ($REPEAT_CHECK_AFTER_SECONDS -gt 0) { # after some sleep time the check for the latest # results will be repeated Start-Sleep -Seconds $REPEAT_CHECK_AFTER_SECONDS } } } while ($REPEAT_CHECK_AFTER_SECONDS -gt 0)
You can specify a change interval and a bitmap directory as command arguments. The script randomly sets a bitmap from the given directory as desktop wallpaper. If the given change interval is 0 then the wallpaper is set only once and the script terminates. Otherwise the wallpaper will be set repeatedly.
Enthusiastic programmers may run into the risk of forgetting to remove the teabag
out of their cup. Here is the solution for this problem: a script which reminds you
by a popup message when tea is ready. You can specify your desired preparation
time via command line parameter. By clicking a corresponding button you
can prolong the waiting time.
Of course you can adjust the script to remind you to other important things
of daily life.
The script collects informations about your computer system. Basically the information is collected via "Get-Wmiobject" and "System.IO.DriveInfo".
COMPUTER SYSTEM HostName : SIRIUS Owner : Gerald Fahrnholz Domain : ARBEITSGRUPPE Manufacturer : Dell Inc. Model : Inspiron 9300 OS name : Microsoft Windows XP Professional OS Service Pack : 3 OS version : 5.1.2600 OS serial number : 76497-OEM-0011903-00102 OS directory : C:\WINDOWS\system32 PROCESSOR and MEMORY Class : Win32_Processor Manufacturer : GenuineIntel Name : Intel(R) Pentium(R) M processor 2.00GHz Description : x86 Family 6 Model 13 Stepping 8 Number of cores : 1 L2 cache size : 2 MB Max clock speed : 1994 MHz Physical memory : 2 GB DISK SPACE Drive DiskType VolumeName Free FreeSpace TotalSize Format C: local 25,1% 23,36 GB 93,15 GB NTFS E: removable MYUSBSTICK 4,4% 0,02 GB 0,48 GB FAT
# get processor name $processor = Get-WmiObject win32_processor "Processor name :" $processor.Name.Trim(' ') "Number of cores :" $processor.NumberOfCores
The script checks if any process from a configurable set of process names is running and tries to kill all instances of them.
The execution can be configured for one time execution or repeated (time controlled) execution to capture also unwanted processes which are started later in time.
Attention: the demo script deletes all instances of notepad.exe on your system. Therefore save all open text documents before starting script execution.
PS C:\UserData\Gerald\SW\PowerShell>./Killer -? Killer.ps1 - commandline syntax -checkEverySecrepeat the check for unwanted processes when the given time interval has elapsed; default time interval is 30 seconds; a time interval of 0 means single execution; processname_1 processName_2 ... a list of (unwanted) processes to be deleted, the names are separated by blanks; you have to specify at least one process name -? or -help show these infos and exit from script execution
[string[]]$processesToDelete = GetArrayOfProcessnamesFromSomewhere # option "SilentlyContinue" tolerates search for not existing processes get-process $processesToDelete -ErrorAction SilentlyContinue ` | foreach-object {$_.kill()}
The script checks CPU load and working set usage. To identify the processes which make heavy use of CPU and memory the top N processes are shown within two distinct rankings.
$processor = Get-WmiObject win32_processor $operatingSystem = get-wmiobject win32_OperatingSystem $runningProcesses = get-process foreach($process in $runningProcesses) { [double]$procTotalCpuTime = $process.CPU [double]�procWorkingSet = $process.Workingset64 } $totalCpuLoad = $processor.LoadPercentage # total physical memory usable by the operating system $totalPhysicalMemory = $operatingSystem.TotalVisibleMemorySize # still free physical memory usable by the operating system $freePhysicalMemory = $operatingSystem.FreePhysicalMemoryRemark
In modern sw development "continous integration" should be a well known phrase. In practice it means that all team members continuously add their changed source code to the central repository. To ensure code stability there is a "continuous integration server" (e.g. CruiseControl) which continously builds the source code. Even execution of unit tests can be integrated into the build process.
CruiseControl offers build results in the form of intranet web pages which can be read by all developers. The developer can be notified about the failure of a project via a notification icon within system tray.
What the developper should do in case of an signalled error:
Browse the CruiseControl web page, look for the project he has worked on, click to the page with detailed build results, check if he has checked in a bad piece of code and probably fix it. In many cases this is a blind alarm because the error may be caused by someone else or by some side effects on the CruiseControl server.
And here comes the help of the script CheckBuildResults.ps1. The following features are supported:
10.05.2012 19:15:32 Build : OK 10.05.2012 19:15:32 UnitTest : OK 10.05.2012 20:14:36 Build : COMPILE_ERROR : InfraStructure MainGui --- COMPILE_ERROR --- Infrastructure d:\SomePath\InfraStructure\UserList.h(41): error C2661: 'Access::CheckAuthentication' : no overloaded function takes 5 arguments --- COMPILE_ERROR --- MainGui MainWindow.cpp(1): fatal error C1083: Cannot open precompiled header file: 'D:\SomePath\MouseTracking.pch': No such file or directory 11.05.2012 08:52:06 Build : OK 11.05.2012 09:11:52 UnitTest : OK 11.05.2012 10:27:49 Build : OK 11.05.2012 09:11:52 UnitTest : TEST_EXEC_ERROR : TestAccounts TestReaction --- TEST_EXEC_ERROR --- TestAccounts !!Error at location TestAccounts.cpp (173): (call location of error) Expected : date: 19.03.2012 Found : date: 18.03.2012 First error in: Test 40 / Z1 Logging to event log --- TEST_EXEC_ERROR --- TestReaction [TimedExec]: 11.05.2012 09:03:51 FAILURE (TIMEOUT_EXE_TERMINATION) TestReaction.exe StartTime: 11.05.2012 09:02:21 Timeout of 90 sec elapsed