Hey, Scripting Guy! How Can I Use Windows PowerShell to Get a List of All the Open Windows on a Computer?

Hey, Scripting Guy! How Can I Use Windows PowerShell to Get a List of All the Open Windows on a Computer?

  • Comments 3
  • Likes

Hey, Scripting Guy! Question

Hey, Scripting Guy! Someone told me that there’s a way to use Windows PowerShell to get a list of all the open windows on a computer. Any chance you could show me how to do that?

-- JD

SpacerHey, Scripting Guy! AnswerScript Center

Hey, JD. You bet we can. Before we do that, however, we’d like to take a moment and salute Peter Costantini, the oldest living Scripting Guy. Peter, best-known for being the author of Dr. Scripto’s Script Shop and for being the crazy guy who sings on webcasts, recently accepted a Program Manager position in the Management Practices group at Microsoft. Peter will still be a Scripting Guy; he just won’t be able to devote much time to scripting and to writing Script Center articles.

Which, all things considered, puts him on the same footing as the other Scripting Guys. But at least he has an excuse for not doing anything.

Speaking of the other Scripting Guys, we wish Peter the best of luck, and, as a special tribute, thought we’d recap some of his greatest moments as a Scripting Guy:

For example, just a few weeks ago he – well, actually, Dean did that.

But about a year ago Peter – never mind; Jean wrote that, didn’t she?

Still there was – oh, right. But if it hadn’t set the building on fire that would have been a pretty good little script.

And of course, there are many other great moments, far too, uh, numerous to name.

Note. As you might expect, Peter’s true contributions to scripting and to the Script Center can’t be measured by the amount of work he did. Or at least that’s what he keeps telling the rest of us.

On the bright side, though, the years Peter spent sitting around doing nothing useful or important made him the obvious choice for a management position at Microsoft.

To be honest, our first reaction when Peter announced he was leaving was to simply sit around and mope. (Of course, that’s usually our first reaction to anything.) But Peter wouldn’t have wanted us to act that way; instead, he would have wanted us to get on with our lives. So here you go, Peter; this one’s for you:

Get-Process | Where-Object {$_.MainWindowTitle -ne ""} | Select-Object MainWindowTitle

As you can see, this is a pretty simple little command. We start out by calling the Get-Process Cmdlet, which – as the names implies – retrieves a collection of all the processes running on the computer. Of course, we don’t really want a collection of all the processes running on the computer; after all, that collection includes services and other processes that aren’t running in a visible window. Therefore, we “pipe” that collection to the Where-Object Cmdlet, and ask Where-Object to filter out all processes except for those where the MainWindowTitle property is not equal to an empty string.

Note. Yes, we know: in Windows PowerShell you use the –ne operator instead of <>. And no, it doesn’t matter whether we like using –ne; we just have to use –ne.

What’s that going to do for us? That’s going to weed out services and other processes that don’t run in a visible window (if there’s no window then MainWindowTitle will be equal to an empty string). We then pass this filtered collection to the Select-Object Cmdlet and ask Select-Object to display only the MainWindowTitle property:

MainWindowTitle
---------------
open_windows.ps1 - Notepad
Inbox - Microsoft Outlook
Windows PowerShell
more_hey_scripting_guy.doc - Microsoft Word

Nice observation: you won’t find the MainWindowTitle property anywhere in WMI’s Win32_Process class. That’s because the Get-Process Cmdlet doesn’t use WMI to retrieve process information; instead, it uses the .NET Frameowork class System.Diagnostics.Process.

Unfortunately, there’s one minor drawback to this command: it doesn’t return any Windows Explorer windows (for example, a window open to C:\Scripts). But that’s OK; here’s another one-liner that does return Windows Explorer windows:

$a = New-Object -com "Shell.Application"; $b = $a.windows() | select-object LocationName; $b

What we do here is use the New-Object Cmdlet to create an instance of the Shell.Application object. We call the Windows() method to retrieve a collection of Shell windows, then use the Select-Object Cmdlet to echo back the value of the LocationName property. That’s going to result in a report similar to this:

LocationName
------------
Stuff
Hey Scripting Guy
Scripts

Alternatively, you can echo back the LocationURL property to get the complete path. Of course, in that case, you might want to do some cleanup work as well, seeing as how LocationURL returns paths similar to this:

file:///C:/Documents%20and%20Settings/kenmyer/Desktop/Stuff/Hey%20Scripting%20Guy

But here’s a command that might be helpful in trying to clean up that string.

We hope that answers your question, JD. And in case you’re wondering, we gave absolutely no thought to stripping Peter of his Scripting Guy status after he accepted his new job. Was that in recognition of his valuable contributions to the scripting world, contributions that we expect will continue throughout the coming years? You bet it was.

Well, that and the fact that if we got rid of Peter then Greg would become the oldest living Scripting Guy, and there’s no way Greg is going to accept that. So see, Peter? We like to kid you and give you a bad time, but you’ll always fill a very important role on the team. Always.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • how to join thoose two commands into single command

  • how can I use this to select a window and then pass a keystroke combination to it, to close out of it.  

    So what I'd like to do is combine the above script with my own:

    "Get-Process | Where-Object {$_.MainWindowTitle -eq "test"} | Select-Object MainWindowTitle

    [System.Windows.Forms.SendKeys]::SendWait("%{F4}")"

  • Ohhh my, Surprise! Your script doesn't quite work the way you said it would .... On my Win 7 Ultimate 64-bit machine, the 2nd script ($a = New-Object -com "Shell.Application"; $b = $a.windows() | select-object LocationName; $b) incorrectly lists Samsung's "Kies" utility (for my Galaxy tablet) among processes that run in their own open window. Wrong-O! Perhaps it's a really, really teeny-tiny window ? Huh? Would you care to comment, Script-Weenie? (The fact is, filtering for processes with a nul-named window just seems pretty amateurish to me. I wonder how the Linux boys would approach this?).