PowerShell in Task Scheduler

One of the programs on my computer creates a shortcut on my desktop every time I restart my computer. As people who know me can attest, I am a little compulsive about certain things, and having anything on my computer’s desktop is one of them. The program in question does not have an option to disable this thing, so someone suggested to me to use Task Scheduler to remove the shortcut. Since I’ve been using PowerShell a lot, I thought I’d try that.

The PowerShell Script

First, you need a script to execute the task at hand. In my case I needed to remove the shortcut from my desktop. After searching for a while, I found it in the Users folder. Create a new PowerShell file in the ISE and write this script:

$MyFile = "C:\Users\<UserName>\Desktop\<TheShortCutYouMustDelete>.lnk"

if (Test-Path $MyFile) 
    {
        Remove-Item $MyFile -Force
    } 

Obviously, you replace <UserName> with your user name, and the name for the shortcut. I’m sure you can even replace the folder with an environment variable. Save this script as a .ps1 file and put it in a folder, like your documents folder. I called mine RemoveShortcut.ps1 and put it in the folder “C:\Users\DENSTER\Documents\”.

For me, this was a need of the moment, because this program was stubbornly creating this shortcut. You can use PowerShell for a million different things, so anything you can do with PowerShell you can put in the Task Scheduler.

Update July 24, 2020 – Based on a conversation with @steveendow on Twitter the other day, automatically updating NavContainerHelper would be a good example. I had already written most of this post (started it back in June) and was about to add the update as a second example before publishing it when Steve created his version of this same post himself. I actually gave him the update script that he used, and I suggested using the Task Scheduler, so I don’t feel too bad for this redundant post, and it saves me from having to test the NavContainerHelper update script in the scheduler :).

Task Scheduler

Next, you need to create a task in the Windows Task Scheduler. Hit the Start button and type ‘task scheduler’, and the app will come up. When the Task Scheduler opens, you’ll see the “Task Scheduler Library”. To make it easier on yourself, create a new folder by right clicking on the Library node and then clicking “New Folder”. Enter a name and hit Enter. This creates a folder where you can save your own tasks. Trust me, it is VERY easy to lose tasks in the standard folders. Having your own folder is going to save you a ton of time.

My new folder “theDenSter”

To create a new task, right click your new folder and select ‘Create Task’. Give it a name and then select the SYSTEM account under security options. You can leave it under your own account, but then you will see PowerShell pop up and run as you are using the computer. Selecting the SYSTEM account makes it so that it happens in the background.

You need a trigger to execute the task. I chose to run it at log on, and I set the task to repeat every 5 minutes for 30 minutes. The reason I did that is because the program that created the shortcut sometimes took a while to create the shortcut, and running my script just once did not always remove it right away, so I had to repeat it a few times. Take a look at all the available triggers and select the one that makes sense to you. Make sure that the trigger is enabled.

Now the meat of the task: the action. We are going to run the PowerShell script, so select ‘Start a program’ and enter ‘powershell’ in the “Program/script” box. The file name goes into the “Add arguments” box:

-File "C:\Users\DENSTER\Documents\RemoveShortcut.ps1"

If you want to be able to manually execute the task, you have to check the box for “Allow task to be run on demand” on the Settings tab. This way you can run the task at any time right from the Task Scheduler.

That’s it. Hope this is useful for you. I had not thought of using the Task Scheduler, but it feels like I could automate a bunch of things. It’s nice to have the ability, let me know if you use the Task Scheduler, and what you use it for.

Span Some (but not all) Monitors

If you use multiple monitors, and you would love to span your RDP session or your Hyper-V session across some, but not all, monitors, then this is the post for you. Say you have three monitors, I will tell explain how you can span your RDP/VM across two of those monitors, while still using the software that runs on the host on the remaining monitor.

Why I Wanted to Know This

My desk has my laptop on a stand on the left side, plus two external monitors to the right of the laptop. The first external monitor is my primary work screen, so it is positioned right in the middle of my desk. I think of the middle screen as “screen 1” and the one on the right as “screen 2”. My laptop screen is just ‘my laptop screen’ :).

My screen setup. Note that the laptop screen shows a third of a fantastic looking multi-screen spacescape, mostly hidden by my 2 screen spanning RDP session into my VM on the two external monitors ‘screen 1’ and ‘screen 2’

For my daily development work, I use Hyper-V virtual machines, and I used to full screen it either on screen 1 or 2, depending on what I was doing. Doing development I’d have my VM full on screen 1, and other supporting programs on the host on screen 2. Writing documentation, I’d have the VM full on screen 2 and Word on screen 1, and then I’d use Snagit for taking screenshots.

When I started including documentation (in markdown files) into my source code, it became difficult to work on documentation, because I would want to take screenshots of the app, and then incorporate it into the markdown file. I would have to switch between VSCode and the app inside the VM, switch to the host to activate Snagit, and then switch back to the VM to process the screenshot in the documentation. Very tedious situation with lots of clicks. I did try to use ‘all monitors’ in the Hyper-V connector, but then it would be difficult to take proper screenshots because I only had Snagit installed on the host. I’d have to minimize the VM, start the Snagit screenshot with delay, re-activate the VM and hope that it would be back up in time for me to take the screenshot.

So, then I thought it would be nice if I could span my VM across just 2 of my 3 screens. I could have VSCode on screen 1, the app on screen 2 (both inside the VM), and Snagit on the host on the laptop. Kudos go to Martin, one of the IT leaders at one of my clients, for teaching me how to do this for RDP. Although the Hyper-V connection uses RDP technology, there does not seem to be a way to do the same thing for Hyper-V – it’s either only 1 monitor, or all monitors. “No problem”, Martin said, “you can use RDP to connect to your VM”, and he showed me how to make that work as well. Let me share this useful nugget with you.

RDP Into your VM

First you need to make sure that your VM is set up to accept remote connections. This section explains how to do that for Windows Server 2019, which is what I use in my VMs.

Inside the VM:

  • Click Start and open Settings
  • Go to the “Remote Desktop” page, and turn on Enable Remote Desktop

Back on the host – open Hyper-V Manager and select your VM. At the bottom, you will see a screen part with three tabs. In the Networking tab, it shows the IP address of your VM. Be aware that this IP address can change without any clear indication when or why. Hyper-V Manager will go long times using the same IP address when restarting the same VM, and all of a sudden it will change it. Maybe there is a way to set this up as a fixed IP address, but I don’t know how. Until then, you’ll have to update your rdp file with the VM’s IP address.

Now open Remote Desktop Connection, and expand the options. Enter the VM’s IP address into the computer name and Click on ‘Save As’. Save the rdp file and test your connection. Very cool, congratulations, you are now using RDP to connect to your VM.

X of Y Monitors in RDP

The rdp file is nothing more than a text file with key-value pairs. We are going to edit this file using notepad, and add some screen properties. Feel free to use any other text editor. You can even open it with VSCode if you want.

You need the following settings in the rdp file:

  • screen mode id:i:2 – Determines whether the session is opened in full screen, and the value 2 stands for ‘full screen’. I tried leaving this out and for fun tried to use the laptop monitor and screen 1 at the same time, and that did not work well for me. It seems that this only works when the screens have the same resolution capabilities.
  • span monitors:i:1 – I think this is a boolean parameter – 1 means on
  • use multimon:i:1 – Same here, I think this is a boolean so 1 for on
  • selectedmonitors:s:1,2 – This is a 0 based index, so 1,2 means screen 1 and screen 2 for me
The ‘MyVM.rdp’ file in Visual Studio Code, showing the relevant screen properties

If you’re interested, here is where you can read more about rdp properties.

Now, instead of opening the VM through the Hyper-V Connection Manager, just double click the rdp file and it will connect. You should now see the desktop across the monitors that you defined in your rdp file. If you take a closer look at the image above, you can see that it shows an RDP session spanning my ‘screen 1’ and ‘screen 2’ monitors, with my laptop showing the host.

Great Improvement

For me this was a really big improvement for my workflow. I used to have to maximize, minimize, switch between VM and host, and it was just distracting to me. Now I can have Outlook, Spotify, and Snagit all visible to my left, and have the real estate of two full monitors to work on whatever I want to run inside the VM, all at the same. The most I need to do is click on my host desktop to make my Snagit keyboard shortcut work.

Personally I do most of my work in my local VMs, but this would also work for regular RDP sessions. This gives you total control over the screens that you want to use.

Hope this helps you, let me know in the comments or send me a message on Twitter.