4

I've been scouring these forums for hours trying to figure out a way to code something that I thought would be much more simple than this.

So here's what I'm trying to do: My task scheduler runs a script every two days. The script opens an explorer.exe path to a folder, and then deletes all of the files in that folder. The scheduler runs the script at night while I'm not in office. However, when I get into the office, the explorer window is open to that page. Trivial, I know - but i don't want to see that window open, so I want the script to run, and then close the window, so I don't see anything.

I've tried this every which way. When I try to do something simple like

$var1 = invoke-item C:\path\file
$var1.quit()

or

$var1.close()

but when I do that, I get an error message saying that the variable is null.

Then I tried stopping the process. But I don't want all explorer files to close, just that particular explorer window to close. So in order to do that, I have to know the ID of the window. But since the ID of that particular window is not static, I need to get the process ID - assign it to a variable - then use the stop-process cmdlet using the variable.

This is what I'm trying now:

get-process | where-object {$_.MainWindowTitle -eq "filename"} | select -property id | $var2

However, when I run this script, it's still saying that the variable is null.

So how do I assign a value to a variable? Or if anyone has a better way of closing a specific window.

(I've tried using the stop-process using just the mainwindowtitle - but it still wants an id)

Knetic
  • 2,099
  • 1
  • 20
  • 34
Justin Beagley
  • 279
  • 2
  • 5
  • 14
  • 2
    Why would you automate `explorer.exe`? You can do what you're describing in a single PowerShell pipeline without ever interacting with the desktop – Mathias R. Jessen May 02 '16 at 22:30
  • 3
    Why is your script opening an Explorer window in the first place? If you don't want a UI to display, don't use a UI element to do the work. Code the deletion yourself in your script, and then you won't have this issue. An Explorer window is designed to provide a **user interface** for a **user sitting in front of the keyboard**. There is zero reason to be using one in your automated deletions via a script. This is very much an XY problem; you're fighting to solve problem Y that wouldn't exist if you'd concentrate instead on properly dealing with X. – Ken White May 02 '16 at 22:31
  • I understand why you would think that. So the folder i access to delete all the files, it is constantly replenished. When i tried running the script without opening explorer - the amount of files deleted, was the same amount that was being replenished. Meaning there was no NET DECREASE of files in the folder - meaning the script would have to run all day, every day. The script runs the sendkeys - ctrl+all then DEL. That seems to work better, and deletes everything back to zero files more quickly, and then the amount builds back up over a few days. – Justin Beagley May 03 '16 at 19:28
  • If it works with GUI, it definately works directly with `Remove-Item`. If anything, GUI-automation would be slower. But without the actual script you've tried (which you would have to ask about in a new StackOverflow question), there's not much we can do to help you besides recommending to fix it. As for this question, I've already answered. :-) – Frode F. May 03 '16 at 19:46

2 Answers2

8

If you really want to close a specific File Explorer window, then you would need to use Shell.Application. List opens file explorer windows:

$shell = New-Object -ComObject Shell.Application
$shell.Windows() | Format-Table Name, LocationName, LocationURL

Name          LocationName LocationURL           
----          ------------ -----------           
File Explorer Windows      file:///C:/Windows    
File Explorer folder       file:///C:/path/folder

I want to close the one in c:\path\folde, so lets find it and close it:

$shell = New-Object -ComObject Shell.Application
$window = $shell.Windows() | Where-Object { $_.LocationURL -like "$(([uri]"c:\path\folder").AbsoluteUri)*" }
$window | ForEach-Object { $_.Quit() }

However as mentioned in the comments, you're overcomplicating this. The point of PowerShell is to automate it, which usually means you don't want to use a GUI at all. I'm not sure what you want to remove or keep etc. but here's a sample you can work with:

#Get contents of folder (not recursive)
Get-ChildItem -Path 'c:\path\folder' |
#Only files
Where-Object { !$_.PSIsContainer } |
#Remove...
Remove-Item
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • Thanks for the response - i figured it had something to do with shell.application, but didn't know much beyond that. However, the way you're closing it seems like it's still closing every explorer instance/window. Is there not a way to close a specific explorer window either by using the MainWindowTitle, or by sending the process ID to a variable, and then stopping the process by variable? – Justin Beagley May 03 '16 at 19:31
  • Did you try it? All Windows Explorer windows runs in one explorer.exe-process (per user session/login), which means you can't kill the process. The sample above closes only the window that's inside the `c:\path\folder`-folder. You would normaly use `LocationURL` (path) or `LocationName` (title / name of folder) to find the correct window. See updated answer. – Frode F. May 03 '16 at 19:41
  • Sweet - yes that did work. Thank you. The only part of that code that I don't understand is the [uri].absoluteuri)* Could you explain that to me? Thanks again for your help – Justin Beagley May 03 '16 at 19:55
  • 1
    Look at the table showing my file explorers, the `LocationURL`-values are URIs (`file://c:/path..`) and not filepaths (`c:\path\..`). So to convert the filepath I want to search for to the valid format (URI), I convert the filepath to an `URI`-object and get it's `AbsoluteURI`-value (full URI-path). You could use `$uri = ([uri]"c:\path\folder").AbsoluteUri` and `.. | Where-Object { $_.LocationURL -like "$uri*" }` if that makes it easier to understand. :-) – Frode F. May 03 '16 at 20:04
  • Also - does this mean that you cannot close an application (not necessarily explorer) by mainwindowtitle? – Justin Beagley May 03 '16 at 20:06
  • There are no `MainWindowTitle` for the window, it's not a process. However, you can use the title of the window with `LocationName`. see the table I posted above...... – Frode F. May 03 '16 at 20:09
  • A short abbrevation to the PowerShell command lines above would be using $window.Quit() instead of $window | ForEach-Object { $_.Quit() } – Peter M. Dec 23 '21 at 11:17
0
# Close specific window, when folder path contains cyrillic symbols
$folder = "D:\folder"
$shell = New-Object -ComObject Shell.Application
$window = $shell.Windows() | Where-Object {$_.LocationURL -eq "file:///"+([uri]$folder.Replace("\","/")).OriginalString}
$window | ForEach-Object -Process {$_.Quit()}
farag
  • 325
  • 1
  • 4
  • 20