The other day I was helping Gladys Kravitz on her transition to VS Code. Like many of you, she has been using the PowerShell ISE for years and has a deeply ingrained workflow. I'll be the first to admit that making the transition to VS Code is not easy. I remember when I made the transition. It was hard. But so was learning PowerShell. Jumping into VS Code is like learning anything new. You need constant exposure and repetition. Eventually, you'll build up new muscle memory and develop new work processes. Let me help you start today to break out of the ISE rut by showing a little PowerShell tough love. And yes, this is meant to be a bit tongue in cheek and a way to teach a few PowerShell concepts.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Kill the ISE
Gladys' big challenge, probably like many of you, is trying to break the habit of launching the PowerShell ISE. It doesn't matter if you are running the ise alias at a PowerShell prompt or using a Start Menu shortcut. My idea is that if you can't stop yourself from doing this, then why not have the ISE turn around and launch VS Code? I gave Gladys a few lines of code to put in her PowerShell ISE profile script that launched VS Code and then killed the ISE. I've since, refined that code and I thought I'd share it with everyone else.
There are a few assumptions in the process. First, is that when you installed VS Code, you included the option to include the application in your %PATH%. You can test this. At a PowerShell prompt run code. If VS Code launches, you are ready to continue.
ISE Profile Script
The PowerShell ISE is nothing more than a different PowerShell host. As such it has its own set of profile scripts. Open the PowerShell ISE and in the console, view your profiles.
You can see the scripts with ISE in the name. $Profile will be the script for the current user in the current host, or the ISE. If you have one, you can run psedit $profile to open it. Otherwise, create a new file:
New-Item $profile -force -ItemType File
Then open the file in the ISE. I'll give you code to add in a moment.
Profile Processing
My goal is to transition from the ISE to VSCode as quickly and as seamlessly as possible. As I was testing, I found the ISE taking a bit longer to get to the code I inserted. Then I remembered. PowerShell looks for and processes PowerShell profile scripts starting from "All Users All Hosts" down to "Current User Current Host". In my case, and maybe yours, I am using a "Current User Current Host" profile script. This script is defining functions and PSDrives that I want to very regardless of whether I am using the PowerShell ISE or Windows PowerShell. PowerShell 7 is a different host so it has a different set of profile scripts.
In the "Current User Current Host", I added an If statement.
if ($host.name -notmatch "ISE") {
. c:\scripts\jdh-functions.ps1
. c:\scripts\jdh-aliases.ps1
. c:\scripts\jdh-variables.ps1
. c:\scripts\jdh-psdrives.ps1
...
}
Now when the ISE launches and processes this profile script, it won't do anything. I could also have gone this route.
If ($host.name -match "ISE") {
Return
}
Now for the tough love. At the beginning of the profile script for the PowerShell ISE, insert this code.
$WindowState = Add-Type -MemberDefinition @'
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
'@ -Name "WindowState" -Namespace Win32Functions -PassThru
#get the current process
$me = Get-Process -Id $pid
#minimize the ISE
$WindowState::ShowWindowAsync($me.MainWindowHandle, 2)
#see if a path was specified
#split on arguments, trimming blank items
$c = (Get-CimInstance -class win32_process -Filter "processid = $pid" -Property Commandline).Commandline.Split() | Where-object {$_}
#Launch VSCode, assuming you added it to your path
$cmd = Get-Command code.cmd
if ($c.count -gt 1) {
#pass each file name to VSCode
$c[-1].split(",").foreach( { &$cmd.source (Resolve-Path $_).Path })
}
else {
&$cmd.source
}
#Gracefully close the ISE
$me.CloseMainWindow()
Here's what happens.
When I launch the PowerShell ISE, I want to pretend I didn't. So the first part of the code is creating a custom type built from a Win32API. This lets me minimize the PowerShell ISE window. While minimized, I use Get-CimInstance to get the PowerShell ISE process. This is because I want to check for any file names. If I run a command like ise .\get-it.ps1, I want VSCode to also open .\get-it.ps1. WMI gives me this information. If I'm launching multiple files, that will be detected as a comma separated string which I can split.
If I use the ISE alias as I always have, I'll be good. But there is one gotcha. VS Code lets me open an entire folder:
code c:\scripts\psfunctioninfo
But if I try the same thing using the ISE alias, I'll get an error. However, when I click OK to dismiss the error, VS Code will in fact open the folder.
With this PowerShell ISE profile in place, no matter how I launch the ISE, VS Code will open and the ISE will close.
But I REALLY Need the ISE
If for some reason you really want to get into the ISE once you've put this code in place, all you need to do is launch the ISE from a console prompt.
ise -noprofile
But I hope, over time, you'll wean yourself off the PowerShell ISE as your editor of choice and move to VSCode. So if you've been struggling to break the habit, show a little tough love. Your future self will thank you.
Not a bad option for local work, but I know sometimes I still want to use ISE – especially on a server where I want to tweak a PS script locally. Not going to get permissions to install VS Code on those servers anytime soon. 🙂
For my part, I’ve swapped over to VSCode for most of my PS coding anyway. It’s easier for me to use overall. Still learning all of the tricks in the IDE, but I definitely like it more than ISE when given a choice.
Personally, I wouldn’t be editing scripts ON servers in any event. There is no reason for the PowerShell ISE to be installed on a server. I would recommend always editing and testing scripts on your desktop. Then deploy them to servers if you need them ON the server. Doing this work locally and using source control would be a better approach.
I agree in principal but it depends on your usage. For instance, I may remote into a system with a customer that I have never interacted with prior to that day, and I may need to install the PowerShell module I wrote which makes it easy to do bulk configuration/reporting against our software. Then I need write a few lines (or more) of PS code which uses that module. I can write that on my own system of course, but I can’t establish a connection from VS code to the software running on the customer machine which I’m double-hopped into via teamviewer and RDC. So I’ll typically write or tweak the script in ISE on the customer’s server because it’s available and I don’t want to complicate things but installing more than I need to on their system.
When you’re developing scripts/modules/tools for your own organization, it’s a lot easier to stick to VSCode and avoid making any chances to scripts directly on a server.
I like VSC in general and cannot imagine to return back to ISE, but there are a lot of drawbacks. Like extremely slow intelli sense, not working syntax coloring, not working debugger, extremely slow code formatting, bug that deletes random chunk of code when formatting, …
It makes me very sad because this are basic things that anybody except to be working..
Or am I the only one with such problems?
VSCode and the PowerShell extension are constant works in progress. The things you describe are not unique to you. For me, the benefits of VSCode still outweigh the frustrations.
If you really need the ISE use PowerShell: Enable ISE Mode in Visual Studio Code 🙂
@Ondrej Å ebela The only problem I sometimes have is intellisense not kicking it and usually i just relaunch VScode and it’s fixed and it’s not such a pain because VScode launch very Fast wich is really cool when you used monstruosities like eclipse before where you can have two coffees before the thing is ready
Gladys Kravitz the nosey neighbor?
Yes. Every neighborhood needs someone keeping an eye on things! I realize the cultural reference dates me. But that shipped sailed long ago on a 3-hour tour.
Tried this and got “This script contains malicious content and has been blocked by your antivirus software.”.
If you copied and pasted the code into a new .ps1 file, I have no idea why you are getting this message. Unless your AV software is really cranked up and doesn’t like the user32.dll import. You could try deleting the $WindowState lines. They aren’t essential.
It was Defender.
On my work box running McAfee, no alerts, but code doesn’t open the requested file, it just opens whatever was last open.
I don’t know what to say. With the code in place in my ISE profile script, I can run a command like
ise c:\work\q.ps1
at a PowerShell prompt. The ISE briefly opens, then VS Code opens the file and the ISE closes. Can you manually launch a file in VS Code from a prompt:cod c:\work\q.ps1