Create a schedule task to periodically run a PowerShell script
Lately, the anti-virus used by the company I work for have been giving me a few headaches. In a nutshell, every time Visual Studio is opened or the Visual Studio test framework tries find tests, the anti-virus starts his virus scan. By itself that shouldn't be a problem, the scan shouldn't consume too many resources. The reality is the anti-virus scan completely gets out of hand with the amount of resources it's using, making my computer unusable while the scan is being performed. On top of that, Visual Studio is on hold while the scan is running. Here's a few screenshots of the Task Manager while the Anti-Virus is running.
Obviously this problem was reported to our IT department, but as usual all I got was generic response stating the issue will be investigated, which is the same as saying "whatever dude, we might look into it whenever we have some free time to spare". What's upsetting is that I don't have control to the anti-virus settings. On the bright side I've administrator access to my computer, so I would just have to figure out a solution on my own. It's known that every time a new instance of Visual Studio is opened the anti-virus process spawns up and starts running. All I need to do is find the anti-virus process kill it. It's a bit too extreme, but Visual Studio is my bread and butter so yes I'm willing to compromise security in favor for productivity. Plus the problem was reported and nothing was done to resolve it and waiting 30-45 minutes every time I need to open a new Visual Studio instance, is absolutely ridiculous. By the way, in this blog post the name of Anti-virus used won't be mentioned, since it's not relevant for the message I want to pass.
How can this problem be solved? We already know the root cause. Every time Visual Studio is opened, the anti-virus process must be killed and everything comes back to normal. Easy right? But doing this every time is incredibly boring, so let's automate it. Let's create a schedule task, starting at every time a user logon, that every five minutes checks if the Anti-Virus is running and kills it.
To create a scheduled task, the traditional 'schtask' command (reference) or PowerShell Cmdlets can be used (reference). Although, if either of those are used, some options are intentionally not available, like defining a trigger that starts at logon and is invoked every five minutes. Don't know the reason why but most likely those options are blocked for compatibility reasons (old systems might not support it). To bypass this limitation simply create and fully configure new schedule task using the UI 'taskschd.msc' and export it (right-click, Export...). A XML file will be saved containing the entire schedule task definition. Later you can use this schedule task definition file to re-create the schedule task using PowerShell or Windows Command Prompt. Just provide the task name and the XML location.
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2016-03-02T12:51:46.404796</Date>
<Author>DOMAIN\USER</Author>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<Repetition>
<Interval>PT5M</Interval>
<StopAtDurationEnd>false</StopAtDurationEnd>
</Repetition>
<ExecutionTimeLimit>PT30M</ExecutionTimeLimit>
<Enabled>true</Enabled>
<Delay>PT30S</Delay>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>DOMAIN\USER</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\StartupScripts\Kill-Process.vbs</Command>
</Exec>
</Actions>
</Task>
To create a schedule task using the XML presented above, simply save the XML in a known location and execute the following PowerShell:
& schtasks.exe /create /TN "Kill Process Task" /XML ".\ScheduleTask-To-Kill-Process.xml"
The PowerShell script to actually kill the anti-virus process:
#Requires -RunAsAdministrator
# define the process name here
$target = "PROCESS-NAME-TO-KILL"
$process = Get-Process $target -ErrorAction SilentlyContinue
if ($process -ne $null)
{
$process.Kill()
}
One of the down sides of calling PowerShell from a schedule task is that every time the task is triggered, you will see a new command prompt begin opened and closed right away. Obviously this is quite distracting. To avoid this, you can create a VBScript that invokes your PowerShell script from a hidden command prompt shell.
Dim objShell,objFSO,objFile
Set objShell=CreateObject("WScript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")
'enter the path for your PowerShell Script
strPath="C:\StartupScripts\Kill-Process.ps1"
'verify file exists
If objFSO.FileExists(strPath) Then
'return short path name
set objFile=objFSO.GetFile(strPath)
strCMD="powershell -nologo -command " & Chr(34) & "&{" & objFile.Path & "}" & Chr(34)
'Uncomment next line for debugging
'WScript.Echo strCMD
'use 0 to hide window
objShell.Run strCMD,0
Else
'Display error message
WScript.Echo "Failed to find " & strPath
WScript.Quit
End If