הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Monday, February 5, 2018 4:33 AM
Hi. I'm trying to figure out how to detect if a directory is open (in explorer.exe) and close it.
I designed a routine to open two folders when a button is pressed. The problem is that I only want one instance of the folders to be open but each time the program executes it opens the folders so I get multiples of the same folders open on the screen.
I am using the expression "Process.Start("explorer.exe", FolderToOpen)" to open the folder.
Here is my test code:
Private Sub btnOpenFolders_Click(sender As Object, e As EventArgs) Handles btnOpenFolders.Click
Dim FolderToOpen As String = "F:\ZZTestn\Tstn 4 Opening Folders\Opened this folder"
Dim FolderToOpenChr As String
Dim FolderToOpenSubString As String
Dim x As Int16
Dim StringPointer As Int16
StringPointer = 0
x = 0
'Parse out the folder strings here
For x = 0 To (Len(FolderToOpen) - 1) Step 1
FolderToOpenChr = FolderToOpen.Substring(x, 1)
If FolderToOpenChr = "\" Then
StringPointer = x
End If
Next
FolderToOpenSubString = FolderToOpen.Substring(0, StringPointer)
Try
Process.Start("explorer.exe", FolderToOpen)
Process.Start("explorer.exe", FolderToOpenSubString)
Catch ex As Exception
End Try
End Sub
Does anyone know how to detect if a folder is open in WindowsExplorer and how to close that folder if it is open?
All replies (40)
Wednesday, February 21, 2018 8:59 PM ✅Answered
So after working on this for several weeks, and with the help of others that have posted here, I have finalized my example solution. I am posting my working example here and will try to explain why I did what I did in order to get it to work as I needed.
First of all I needed to open Folders in Windows Explorer without generating duplicates of the same open folder. This turned out to be easy as I simply used the statement " Process.Start(FolderToOpen) " where FolderToOpen is the fully qualified path as a string. See the code segment for Button5.
I also needed to be able to reliably get the fully qualified paths of all open Explorer Windows. I needed this in my real project to determine what parts of my code I needed to execute based on what folders were open in windows explorer. The code segment in the Sub that handles Button10 with the comment " 'To List Open Windows In text box " is that code. Member RLWA32 provided code segments that would cull out Internet Explorer Windows an issue I had within my original code.
Finally I needed to close certain Windows Folders in my real project depending on what code I was executing. The example code segment for Button11 with the comment " 'To Close Open Folder Windows by handles " is that code. Again with help from member RLWA32 and a few hours of debugging my old code I was able to put together this code segment that reliably closes open windows.
Here is my sample code. I hope this helps anyone else that is in need of these features in their project.
Option Strict Off
Imports System.IO
Imports System.Runtime.InteropServices
Imports SHDocVw
Imports Shell32
Public Class Form1
Private MyExplorerHandles() As IntPtr
Private Const WM_CLOSE As Integer = &H10
Dim myprocess As Process
Dim OpenFolder1 As String = "C:\ZZZTstn\OpenFolder1"
Dim OpenFolder2 As String = "C:\ZZZTstn\OpenFolder2"
Dim OpenFolder3 As String = "C:\ZZZTstn\OpenFolder3"
Dim OpenFolder4 As String = "C:\ZZZTstn\OpenFolder4"
Dim OpenFolder5 As String = "C:\ZZZTstn\OpenFolder5"
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
' Set the default directory of the folder browser to the current directory.
'FolderBrowserDialog1.SelectedPath = My.Computer.FileSystem.CurrentDirectory
End Sub
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
End
End Sub
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click 'Clears the Text Box
filesListBox.Items.Clear()
filesListBox.Refresh()
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click 'To Open Windows
Process.Start(OpenFolder1)
Process.Start(OpenFolder2)
Process.Start(OpenFolder3)
Process.Start(OpenFolder4)
Process.Start(OpenFolder5)
End Sub
Private Sub Button10_Click(sender As Object, e As EventArgs) Handles Button10.Click 'To List Open Windows In text box
Dim ItemCount As Integer
Dim objShell As Shell32.Shell = New Shell32.Shell()
ItemCount = 0
filesListBox.Items.Clear()
For Each ie As InternetExplorer In objShell.Windows()
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
ItemCount += 1
filesListBox.Items.Add("ItemCount " & ItemCount & " " & path)
End If
Next
End Sub
Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click 'To Close Open Folder Windows by handles
Dim objShell As Shell32.Shell = New Shell32.Shell()
Dim ItemCount As Integer
Dim HWNDcount As Integer
Dim FoldersToDelete As Boolean
Dim FolderHWNDs(50) As Long
FoldersToDelete = False
ItemCount = 0
HWNDcount = 0
For Each ie As InternetExplorer In objShell.Windows() 'Loop to get the HWNDs
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
ItemCount += 1
filesListBox.Items.Add("ItemCount " & ItemCount & " " & path)
Select Case path
Case OpenFolder1, OpenFolder2, OpenFolder3, OpenFolder4, OpenFolder5
FolderHWNDs(HWNDcount) = ie.HWND
FoldersToDelete = True
filesListBox.Items.Add("Got HWND and need to close item " & ItemCount & " with HWND " & FolderHWNDs(HWNDcount) & " " & path)
HWNDcount += 1
End Select
End If
Next
If FoldersToDelete = True Then 'Close all folders in the FolderHWNDs Array
For ItemCount = 0 To HWNDcount - 1
filesListBox.Items.Add("Closing " & FolderHWNDs(ItemCount))
SendMessageW(FolderHWNDs(ItemCount), WM_CLOSE, 0, 0)
Next
End If
End Sub
End Class
I realized that I should have perhaps split this question into the three parts and try to address each issue I was having separately.
That being said, and with the understanding that I could have only got to this point by incorporating elements from everyone that spent the time to reply to this question, I am going to mark this as the Answer.
Monday, February 5, 2018 6:43 AM
First you need to understand that Internet Explorer is a part of Windows and that the "Windows Explorer" and "Internet Explorer" are combined together quite closely. You must understand that otherwise you will think this cannot possibly be correct.
Add a reference for SHDocVw.dll then try the following. Be sure to try it with both a Windows Explorer window open and an Internet Explorer window open. You will get an item for each Windows Explorer window and Internet Explorer window. I don't see a clean way to determine which items are for Windows Explorer except to use the FullName property.
SHDocVw.ShellWindows ShellWindows = new SHDocVw.ShellWindows();
foreach (dynamic w in ShellWindows)
{
SHDocVw.InternetExplorer ie = w as SHDocVw.InternetExplorer;
Console.WriteLine($"{ie.FullName} | {ie.LocationName}");
}
Sam Hobbs
SimpleSamples.Info
Monday, February 5, 2018 6:49 AM
Sorry, I was not going to post C# code since this is VB but then I forgot and posted C#. Let me know if you heed help converting that to VB.Net.
Sam Hobbs
SimpleSamples.Info
Monday, February 5, 2018 6:52 AM
Hi Sam
Yes I need help converting to VB.
Thanks in advance
Monday, February 5, 2018 8:36 AM
Dim ShellWindows As New SHDocVw.ShellWindows()
For Each w As Object In ShellWindows
Dim ie As SHDocVw.InternetExplorer = TryCast(w, SHDocVw.InternetExplorer)
Console.WriteLine($"{ie.FullName} | {ie.LocationName}")
Next w
Sam Hobbs
SimpleSamples.Info
Monday, February 5, 2018 10:13 PM
Hi Sam.
Thanks for your suggestion. I worked on this and finally figured out how to add the SHDocVw.dll as a reference to the project. I think that the "Console.WriteLine($"{ie.FullName} | {ie.LocationName}")" statement is a C# statement so I converted it to VB and the code now looks like this:
Dim ShellWindows As New SHDocVw.ShellWindows()
For Each w As Object In ShellWindows
Dim ie As SHDocVw.InternetExplorer = TryCast(w, SHDocVw.InternetExplorer)
Console.WriteLine(ie.FullName & " " & ie.LocationName)
Next w
This gives me the ability to detect open explorer.exe windows. However I was looking for the complete path name for the window but instead I only get part of the path. For instance for the folder : "F:\ZZTestn\Tstn 4 Opening Folders\Opened this folder" I get "Opened this folder" from ie.LocationName and I don't see a property for the full path. ie.path gives me "C:\Windows" and ie.LocationURL gives me "file:///F:/ZZTestn/Tstn%204%20Opening%20Folders/Opened%20this%20folder"
Also, how can I use this to also close those windows?
Tuesday, February 6, 2018 6:09 AM
Hi TJBlues,
If you want to get the full path, you can take a look the following code:
Public Sub GetListOfSelectedFilesAndFolderOfWindowsExplorer()
Dim filename As String
Dim selected As ArrayList = New ArrayList()
Dim shell = New Shell32.Shell()
For Each window As SHDocVw.InternetExplorer In New SHDocVw.ShellWindows()
filename = Path.GetFileNameWithoutExtension(window.FullName).ToLower()
If filename.ToLowerInvariant() = "explorer" Then
Dim items As Shell32.FolderItems = (CType(window.Document, Shell32.IShellFolderViewDual2)).SelectedItems()
For Each item As Shell32.FolderItem In items
MessageBox.Show(item.Path.ToString())
selected.Add(item.Path)
Next
End If
Next
End Sub
Best Regards,
Cherry
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.
Tuesday, February 6, 2018 6:17 PM
Hi Cherry.
Thanks for the suggestion but this code does not work. The line: "Dim items As Shell32.FolderItems = (CType(window.Document, Shell32.IShellFolderViewDual2)).SelectedItems()" Only selects a path in an open folder that has sub path or file highlighted. IF nothing is highlighted in that open folder then nothing is displayed.
Tuesday, February 6, 2018 8:18 PM
When it comes to shell programming it is often easier to work in C++ because a good number of heavily used shell interfaces and functions are not readily available to VB.Net or C#. Yes, you can use p/invoke and manually create interface code using <ComImport> but this can be time consuming and prone to error. If you are willing to entertain a native C++ solution I would be happy to help in that regard.
Tuesday, February 6, 2018 9:20 PM
Thanks for the suggestion and offer of help but my program is tens of thousands of lines long and has multiple forms. Not practical to convert for just this issue.
Tuesday, February 6, 2018 9:30 PM
Thanks for the suggestion and offer of help but my program is tens of thousands of lines long and has multiple forms. Not practical to convert for just this issue.
I wasn't suggesting rewriting all your code. What it really comes down to is what do you want to achieve? Find all explorer windows open to a particular folder? Close all of them? Find only the first one and close that? This kind of thing could be achieved through either a DLL that can be called from VB.net (p/infoke) or through a COM object that is accessible through interop.
Of course the best option is if someone comes back with a method to provide you with a well-formed, fully qualified path string through VB.NET. But if that doesn't happen...
If the problem is that you are opening two explorer windows when only one is desired then change your posted code -
Process.Start("explorer.exe", FolderToOpen)
Process.Start("explorer.exe", FolderToOpenSubString)
Tuesday, February 6, 2018 10:22 PM
Thanks for the suggestion and offer of help but my program is tens of thousands of lines long and has multiple forms. Not practical to convert for just this issue.
I wasn't suggesting rewriting all your code. What it really comes down to is what do you want to achieve? Find all explorer windows open to a particular folder? Close all of them? Find only the first one and close that? This kind of thing could be achieved through either a DLL that can be called from VB.net (p/infoke) or through a COM object that is accessible through interop.
Of course the best option is if someone comes back with a method to provide you with a well-formed, fully qualified path string through VB.NET. But if that doesn't happen...
If the problem is that you are opening two explorer windows when only one is desired then change your posted code -
Process.Start("explorer.exe", FolderToOpen) Process.Start("explorer.exe", FolderToOpenSubString)
Hi RLWA32.
To answer your question "what do you want to achieve?" :
I want to achieve the following two things:
1. I want to open folders but only if they are not already open. So in my example I am using the following two lines to open example folders:
Process.Start("explorer.exe", FolderToOpen)
Process.Start("explorer.exe", FolderToOpenSubString)
However if they are already open, I don't want to open them again (which produces multiple identical windows and is the issue in my code). To do that I need to discover what folder windows are already open and then write my conditional statement around the two statements above. Hence the question I have about the discovery of open folders.
2. The second thing I am trying to accomplish is to close windows. In my program, once I have completed execution of certain parts of the code I want to close the forms and windows associated with that part of the code. In my case I close a form (and return control back to a main form) and now need to figure out how to close the folder windows (that I have opened in item #1 above). I ask this question because there is no such command "Process.Close()" or "Process.End()"
I had been thinking of writing a separate program in C++ just to handle items like this and then use "Process.Start" to run it but I have never done that and have never passed arguments back and forth between programs. A .dll would be good but there does not seem to be a way to generate a class library in C++ (or at least I don't see "Class Library" in the new project options in Visual C++).
I have been trying to come up with a fix for a month now, so ya, I'm open to any suggestions or help.
Tuesday, February 6, 2018 10:59 PM | 1 vote
Once you open an explore window there is no guarantee that it will remain open since it can easily be closed by the user. Similarly, the user can navigate in the explorer away from the folder of interest. So working with explorer windows in this fashion can be pretty fragile.
So that raises the question - what are you using the explorer windows to accomplish and is there a more robust way to proceed?
Tuesday, February 6, 2018 11:18 PM | 2 votes
I don't know what you want to do with your opened folders, but maybe it could be better to embed 2 Explorer windows (with ExplorerBrowser (I has posted a basic sample in another thread, that can be improved))
on which you will have the control because they will be inside your application.
Tuesday, February 6, 2018 11:31 PM
Yes the Windows API can be frustrating. They do illogical things sometimes.
When I was writing the code i posted previously I tried using ShellWindows similar to what Cherry suggested but it was getting exceptions. After I gave up I rem3embered that sometimes we need to use a "STAThread" instead of "MRAThread". Don't ask me what the difference is. Some applications are STAThread by default but not console programs so that is why I was getting exceptions. So any way try the following and note that [STAThread] is necessary for this.
using System;
namespace csConsole
{
class Program
{
[STAThread]
static void Main(string[] args)
{
try
{
var shell = new Shell32.Shell();
foreach (SHDocVw.InternetExplorer window in shell.Windows())
{
Console.WriteLine($"{window.FullName} | {window.Path} | {window.LocationName}");
Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
foreach (Shell32.FolderItem item in items)
{
Console.WriteLine($"\t{item.Name} | {item.Path}");
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error");
return;
}
}
}
}
Sam Hobbs
SimpleSamples.Info
Wednesday, February 7, 2018 2:09 AM
You have not mentioned what is suppose to happen in the case of the user navigating one or both explorer windows to other folder(s). Do you want the explorer windows to be closed in that case?
Also, as has been asked, what exactly are these two explorer windows needed for? There may very well be a much easier and/or better way to go about doing whatever it is you are doing.
If you want both of the explorer windows to be closed even if one or both have been navigated away from the folder you opened them to, then you can try the below example. It is a bit of a hack but, it seems to work half way decent. However, you would want to test it out thoroughly in your situation.
It works by first getting all the existing explorer window handles that the user might have opened. Then it opens the two explorer windows. Last it compares the existing explorer window handles obtained before opening your two, with the explorer window handles that are currently opened and finds the two handles that did not exist before you open your two.
There is a small chance it could grab a third or fourth explorer window handle if by some crazy chance another explorer window or two just happened to be opened between the time the code gets the existing window handles and the time it compares them to find the new explorer window handles.
Imports System.Runtime.InteropServices
Imports SHDocVw
Public Class Form1
Private MyExplorerHandles() As IntPtr
Private Const WM_CLOSE As Integer = &H10
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ExistingExplorerHandles() As IntPtr = GetExplorerHandles()
Process.Start("C:\Users\User1234\Pictures\Desktop Pictures")
Process.Start("C:\")
Threading.Thread.Sleep(1000)
MyExplorerHandles = GetExplorerHandles.Where(Function(x) Not ExistingExplorerHandles.Contains(x)).ToArray
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each hwnd As IntPtr In MyExplorerHandles
SendMessageW(hwnd, WM_CLOSE, 0, 0)
Next
End Sub
Private Function GetExplorerHandles() As IntPtr()
Return (From ie As Object In New ShellWindows Select New IntPtr(CType(ie, InternetExplorer).HWND)).ToArray
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
End Class
If you say it can`t be done then i`ll try it
Wednesday, February 7, 2018 9:31 PM
You have not mentioned what is suppose to happen in the case of the user navigating one or both explorer windows to other folder(s). Do you want the explorer windows to be closed in that case?
Also, as has been asked, what exactly are these two explorer windows needed for? There may very well be a much easier and/or better way to go about doing whatever it is you are doing.
If you want both of the explorer windows to be closed even if one or both have been navigated away from the folder you opened them to, then you can try the below example. It is a bit of a hack but, it seems to work half way decent. However, you would want to test it out thoroughly in your situation.
It works by first getting all the existing explorer window handles that the user might have opened. Then it opens the two explorer windows. Last it compares the existing explorer window handles obtained before opening your two, with the explorer window handles that are currently opened and finds the two handles that did not exist before you open your two.
There is a small chance it could grab a third or fourth explorer window handle if by some crazy chance another explorer window or two just happened to be opened between the time the code gets the existing window handles and the time it compares them to find the new explorer window handles.
Imports System.Runtime.InteropServices Imports SHDocVw Public Class Form1 Private MyExplorerHandles() As IntPtr Private Const WM_CLOSE As Integer = &H10 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim ExistingExplorerHandles() As IntPtr = GetExplorerHandles() Process.Start("C:\Users\User1234\Pictures\Desktop Pictures") Process.Start("C:\") Threading.Thread.Sleep(1000) MyExplorerHandles = GetExplorerHandles.Where(Function(x) Not ExistingExplorerHandles.Contains(x)).ToArray End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click For Each hwnd As IntPtr In MyExplorerHandles SendMessageW(hwnd, WM_CLOSE, 0, 0) Next End Sub
If you say it can`t be done then i`ll try it
Hey IronRazerz.
Thanks for this nice piece of code. It solves one of the problems I had in that I now do not get multiple identical windows opening. The statement "Process.Start("C:\Users\User1234\Pictures\Desktop Pictures")" ( or in my case "Process.Start(FolderToOpen)") only allows for one open window even if it is called multiple times. Go ahead and try that on your example. So that solves my first problem. I made that change to my code and tested it and confirmed that it fixed my first problem of multiple identical windows opening.
However, the closing of the folder windows does not exactly match your description. After pressing Button 1 I can open or close any numbers of windows and it makes no difference to closing those two windows (and only those two windows) when I press Button 2 UNLESS I had pressed Button 1 for a second time. In that case Button 2 will not close those windows.
Wednesday, February 7, 2018 10:17 PM
.... After pressing Button 1 I can open or close any numbers of windows and it makes no difference to closing those two windows (and only those two windows) when I press Button 2 UNLESS I had pressed Button 1 for a second time. In that case Button 2 will not close those windows.
Well, you can take the easier route and just close the windows before opening them like this...
Imports System.Runtime.InteropServices
Imports SHDocVw
Public Class Form1
Private MyExplorerHandles() As IntPtr = {}
Private Const WM_CLOSE As Integer = &H10
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
CloseMyExplorerWindows()
Dim ExistingExplorerHandles() As IntPtr = GetExplorerHandles()
Process.Start("C:\Users\User1234\Pictures\Desktop Pictures")
Process.Start("C:\")
Threading.Thread.Sleep(1000)
MyExplorerHandles = GetExplorerHandles.Where(Function(x) Not ExistingExplorerHandles.Contains(x)).ToArray
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
CloseMyExplorerWindows()
End Sub
Private Sub CloseMyExplorerWindows()
For Each hwnd As IntPtr In MyExplorerHandles
SendMessageW(hwnd, WM_CLOSE, 0, 0)
Next
End Sub
Private Function GetExplorerHandles() As IntPtr()
Return (From ie As Object In New ShellWindows Select New IntPtr(CType(ie, InternetExplorer).HWND)).ToArray
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
End Class
If you say it can`t be done then i`ll try it
Wednesday, February 7, 2018 10:59 PM
Here is another example that would be better than closing the window before opening them again as the last example does. This keeps track of the handles in a List instead of an Array. Instead of assigning the newly found handles to the class scoped array directly like in the last example, it detects if one of the previously opened explorer windows has been closed first. If one or the other has been closed, the closed window handle(s) are removed from the list before adding the newly found handle(s), if there are any.
Imports System.Runtime.InteropServices
Imports SHDocVw
Public Class Form1
Private MyExplorerHandles As New List(Of IntPtr)
Private Const WM_CLOSE As Integer = &H10
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ExistingExplorerHandles() As IntPtr = GetExplorerHandles()
Process.Start("C:\Users\User1234\Pictures\Desktop Pictures")
Process.Start("C:\")
Threading.Thread.Sleep(1000)
Dim NewExplorerHandles() As IntPtr = GetExplorerHandles.Where(Function(x) Not ExistingExplorerHandles.Contains(x)).ToArray
If NewExplorerHandles.Length > 0 Then
If MyExplorerHandles.Count > 1 Then
If Not IsWindow(MyExplorerHandles(1)) Then MyExplorerHandles.RemoveAt(1)
If Not IsWindow(MyExplorerHandles(0)) Then MyExplorerHandles.RemoveAt(0)
End If
MyExplorerHandles.AddRange(NewExplorerHandles)
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each hwnd As IntPtr In MyExplorerHandles
SendMessageW(hwnd, WM_CLOSE, 0, 0)
Next
End Sub
Private Function GetExplorerHandles() As IntPtr()
Return (From ie As Object In New ShellWindows Select New IntPtr(CType(ie, InternetExplorer).HWND)).ToArray
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
<DllImport("user32.dll")> Private Shared Function IsWindow(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
If you say it can`t be done then i`ll try it
Saturday, February 10, 2018 11:13 AM | 1 vote
So... how did my last example or two work out for you?
If you say it can`t be done then i`ll try it
Sunday, February 11, 2018 4:24 AM
So... how did my last example or two work out for you?
If you say it can`t be done then i`ll try it
Hi IronRazer.
Thanks for all the effort you have put into exploring the issue and providing some unique suggestions. Exploring your suggestions has helped me better understand what is going on with windows explorer and how to get information for the open windows. The issue is that you are starting out the process by first opening the two folders then checking for handles. But I need to know what is open in windows before opening anything from my program. The only way to do that is to get the fully qualified path of all open explorer windows and compare that to the folders I want to open.
The only thing I have come across that will give me something close to the fully qualified path is something like the following code:
Dim ShellWindows As New SHDocVw.ShellWindows()
Dim FolderURL as string
Dim FolderToOpen As String = "F:\ZZTestn\Tstn 4 Opening Folders\Opened this folder"
For Each w As Object In ShellWindows
Dim ie As SHDocVw.InternetExplorer = TryCast(w, SHDocVw.InternetExplorer)
FolderURL = ie.LocationURL
'Write code to replace %20 with a space in the FolderURL string
If FolderURL.Contains(FolderToOpen) Then
'Perform what I need to do if this is true
End If
Next w
In the mean time, since I needed to get my code released, I simply used the "Process.Start(FolderToOpen)" statement to open . This is a stop gap measure as I still need a way to close those windows when I close the application. I may end up using some of my code to get things opened and then coupled with your suggestions to track the handles and use that to close the windows. I'll be working on that this week.
Sunday, February 11, 2018 10:04 AM
This is a stop gap measure as I still need a way to close those windows when I close the application. I may end up using some of my code to get things opened and then coupled with your suggestions to track the handles and use that to close the windows. I'll be working on that this week.
As it has been said, it is simpler to embed explorer inside your application.
Sunday, February 11, 2018 11:00 AM
So... how did my last example or two work out for you?
If you say it can`t be done then i`ll try it
Hi IronRazer.
Thanks for all the effort you have put into exploring the issue and providing some unique suggestions. Exploring your suggestions has helped me better understand what is going on with windows explorer and how to get information for the open windows. The issue is that you are starting out the process by first opening the two folders then checking for handles. But I need to know what is open in windows before opening anything from my program. The only way to do that is to get the fully qualified path of all open explorer windows and compare that to the folders I want to open.
The only thing I have come across that will give me something close to the fully qualified path is something like the following code:
Dim ShellWindows As New SHDocVw.ShellWindows() Dim FolderURL as string Dim FolderToOpen As String = "F:\ZZTestn\Tstn 4 Opening Folders\Opened this folder" For Each w As Object In ShellWindows Dim ie As SHDocVw.InternetExplorer = TryCast(w, SHDocVw.InternetExplorer) FolderURL = ie.LocationURL 'Write code to replace %20 with a space in the FolderURL string If FolderURL.Contains(FolderToOpen) Then 'Perform what I need to do if this is true End If Next w
In the mean time, since I needed to get my code released, I simply used the "Process.Start(FolderToOpen)" statement to open . This is a stop gap measure as I still need a way to close those windows when I close the application. I may end up using some of my code to get things opened and then coupled with your suggestions to track the handles and use that to close the windows. I'll be working on that this week.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim objShell As Shell32.Shell = New Shell32.Shell()
For Each ie As InternetExplorer In objShell.Windows()
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
End If
Next
End Sub
Monday, February 12, 2018 5:55 PM
Hi. I'm trying to figure out how to detect if a directory is open (in explorer.exe) and close it.
I designed a routine to open two folders when a button is pressed. The problem is that I only want one instance of the folders to be open but each time the program executes it opens the folders so I get multiples of the same folders open on the screen.
I am using the expression "Process.Start("explorer.exe", FolderToOpen)" to open the folder.
Here is my test code:
Private Sub btnOpenFolders_Click(sender As Object, e As EventArgs) Handles btnOpenFolders.Click Dim FolderToOpen As String = "F:\ZZTestn\Tstn 4 Opening Folders\Opened this folder" Dim FolderToOpenChr As String Dim FolderToOpenSubString As String Dim x As Int16 Dim StringPointer As Int16 StringPointer = 0 x = 0 'Parse out the folder strings here For x = 0 To (Len(FolderToOpen) - 1) Step 1 FolderToOpenChr = FolderToOpen.Substring(x, 1) If FolderToOpenChr = "\" Then StringPointer = x End If Next FolderToOpenSubString = FolderToOpen.Substring(0, StringPointer) Try Process.Start("explorer.exe", FolderToOpen) Process.Start("explorer.exe", FolderToOpenSubString) Catch ex As Exception End Try End Sub
Does anyone know how to detect if a folder is open in WindowsExplorer and how to close that folder if it is open?
Yes. I didn't read most of the rest of the thread.
Add a ListBox, 2 Buttons to your Form and alter the path and folder name u want to test with, and use the below code. Use windows explorer to open the test folder and the ListBox will display open folders for each explorer running. I figure once you test it you can alter it for your requirement.
Also Razerz and them don't knows nuttin, Razerz can't even read his email. I would've posted this earlier but my smart phones Google and Chrome don't work with this site. Imagine that.
And Razerz I wasn't let off the nut farm I escaped from the nut farm. Least that's what TommyTwoTrain told me on the phone yesterday. :)
Below is old code and doesn't work with Option Strict set to on which I didn't bother attempting to correct. Maybe Razerz and them can help you fix that!
Option Strict Off
Imports Shell32 ' Add ref com, Microsoft Shell Controls and Automatiom
Imports SHDocVw ' Add reference browse C:\Windows\System32\ShDocVw.Dll or Com Microsoft Internet Controls
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.CenterToScreen()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListBox1.Items.Clear()
Dim MShell As New Shell
Dim TempStorage As New List(Of String)
Dim SBW As ShellBrowserWindow
On Error Resume Next
For Each Item In MShell.Windows
SBW = Item
If SBW.LocationURL.ToString.Contains("file:///") Then
Dim Temp As String = SBW.LocationURL.ToString
Temp = Temp.Replace("file:///", "")
Temp = Temp.Replace("%20", " ")
TempStorage.Add(Temp)
End If
Next
For Each Item In TempStorage
ListBox1.Items.Add(Item.ToString)
Next
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim MyFolder As String = "C:\Users\John\Desktop\Test"
Dim OpenFolder As Object = CreateObject("shell.application")
For Each Item In OpenFolder.Windows
If Item.Document.Folder.Self.Path = MyFolder Then
Item.Quit()
End If
Next
End Sub
End Class
La vida loca
Tuesday, February 13, 2018 6:11 AM
Does anyone know how to detect if a folder is open in WindowsExplorer and how to close that folder if it is open?
Yes. I didn't read most of the rest of the thread.
Add a ListBox, 2 Buttons to your Form and alter the path and folder name u want to test with, and use the below code. Use windows explorer to open the test folder and the ListBox will display open folders for each explorer running. I figure once you test it you can alter it for your requirement.
Also Razerz and them don't knows nuttin, Razerz can't even read his email. I would've posted this earlier but my smart phones Google and Chrome don't work with this site. Imagine that.
And Razerz I wasn't let off the nut farm I escaped from the nut farm. Least that's what TommyTwoTrain told me on the phone yesterday. :)
Below is old code and doesn't work with Option Strict set to on which I didn't bother attempting to correct. Maybe Razerz and them can help you fix that!
Option Strict Off Imports Shell32 ' Add ref com, Microsoft Shell Controls and Automatiom Imports SHDocVw ' Add reference browse C:\Windows\System32\ShDocVw.Dll or Com Microsoft Internet Controls Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.CenterToScreen() End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ListBox1.Items.Clear() Dim MShell As New Shell Dim TempStorage As New List(Of String) Dim SBW As ShellBrowserWindow On Error Resume Next For Each Item In MShell.Windows SBW = Item If SBW.LocationURL.ToString.Contains("file:///") Then Dim Temp As String = SBW.LocationURL.ToString Temp = Temp.Replace("file:///", "") Temp = Temp.Replace("%20", " ") TempStorage.Add(Temp) End If Next For Each Item In TempStorage ListBox1.Items.Add(Item.ToString) Next End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Dim MyFolder As String = "C:\Users\John\Desktop\Test" Dim OpenFolder As Object = CreateObject("shell.application") For Each Item In OpenFolder.Windows If Item.Document.Folder.Self.Path = MyFolder Then Item.Quit() End If Next End Sub End Class
La vida loca
Hi Loca.
At first glance it worked but I get an error. See above for the error. You also point out (as I had finally figured out above), the only way to get a fully qualified path for the open windows is to use '??.LocationURL.ToSting' and then parse out the extraneous characters. I admit that I am still working through how you close the windows but this seems to contain everything I need to solve my problem. Thanks.
Tuesday, February 13, 2018 10:28 AM | 1 vote
OK this is what I was looking for. You also point out (as I had finally figured out above), the only way to get a fully qualified path for the open windows is to use '??.LocationURL.ToSting' and then parse out the extraneous characters.
I guess you didn't notice my earlier post -
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim objShell As Shell32.Shell = New Shell32.Shell()
For Each ie As InternetExplorer In objShell.Windows()
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
End If
Next
End Sub
Tuesday, February 13, 2018 1:41 PM
You're welcome. But why did you mark your own post as the answer? 🤤 Also RLWA32 HAS A METHOD TO CONVERT URL TO PATH. See the code in his or her If statement at the bottom of the displayed code window. Then mark that post and my post as the answers or something.
La vida loca
Wednesday, February 14, 2018 4:04 AM
You're welcome. But why did you mark your own post as the answer? 🤤 Also RLWA32 HAS A METHOD TO CONVERT URL TO PATH. See the code in his or her If statement at the bottom of the displayed code window. Then mark that post and my post as the answers or something.
La vida loca
OOPS
Friday, February 16, 2018 4:22 PM
Below is old code and doesn't work with Option Strict set to on which I didn't bother attempting to correct. Maybe Razerz and them can help you fix that!
Option Strict Off Imports Shell32 ' Add ref com, Microsoft Shell Controls and Automatiom Imports SHDocVw ' Add reference browse C:\Windows\System32\ShDocVw.Dll or Com Microsoft Internet Controls Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.CenterToScreen() End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ListBox1.Items.Clear() Dim MShell As New Shell Dim TempStorage As New List(Of String) Dim SBW As ShellBrowserWindow On Error Resume Next For Each Item In MShell.Windows SBW = Item If SBW.LocationURL.ToString.Contains("file:///") Then Dim Temp As String = SBW.LocationURL.ToString Temp = Temp.Replace("file:///", "") Temp = Temp.Replace("%20", " ") TempStorage.Add(Temp) End If Next For Each Item In TempStorage ListBox1.Items.Add(Item.ToString) Next End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Dim MyFolder As String = "C:\Users\John\Desktop\Test" Dim OpenFolder As Object = CreateObject("shell.application") For Each Item In OpenFolder.Windows If Item.Document.Folder.Self.Path = MyFolder Then Item.Quit() End If Next End Sub End Class
La vida loca
Hey MonkeyBoy. At first glance this seemed to work but after using it for a while I found that it causes an error in the following Sub:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim MyFolder As String = "C:\Users\John\Desktop\Test"
Dim OpenFolder As Object = CreateObject("shell.application")
For Each Item In OpenFolder.Windows
If Item.Document.Folder.Self.Path = MyFolder Then
Item.Quit()
End If
Next
End Sub
The error is that if there is an Internet Explorer window open I get the following error: "Public member 'Folder' on type 'HTMLDocumentClass' not found." So I guess I need to check if "Item" is not an HTMLDocumentClass or just use a try - catch in the code.
Friday, February 16, 2018 4:25 PM
The error is that if there is an Internet Explorer window open I get the following error: "Public member 'Folder' on type 'HTMLDocumentClass' not found." So I guess I need to check if "Item" is not an HTMLDocumentClass or just use a try - catch in the code.
And for the third time - See my prior suggestion which solves the above problem as well as returning a proper path string -
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim objShell As Shell32.Shell = New Shell32.Shell()
For Each ie As InternetExplorer In objShell.Windows()
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
End If
Next
End Sub
Friday, February 16, 2018 9:51 PM
Below is old code and doesn't work with Option Strict set to on which I didn't bother attempting to correct. Maybe Razerz and them can help you fix that!
Option Strict Off Imports Shell32 ' Add ref com, Microsoft Shell Controls and Automatiom Imports SHDocVw ' Add reference browse C:\Windows\System32\ShDocVw.Dll or Com Microsoft Internet Controls Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.CenterToScreen() End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ListBox1.Items.Clear() Dim MShell As New Shell Dim TempStorage As New List(Of String) Dim SBW As ShellBrowserWindow On Error Resume Next For Each Item In MShell.Windows SBW = Item If SBW.LocationURL.ToString.Contains("file:///") Then Dim Temp As String = SBW.LocationURL.ToString Temp = Temp.Replace("file:///", "") Temp = Temp.Replace("%20", " ") TempStorage.Add(Temp) End If Next For Each Item In TempStorage ListBox1.Items.Add(Item.ToString) Next End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Dim MyFolder As String = "C:\Users\John\Desktop\Test" Dim OpenFolder As Object = CreateObject("shell.application")9 For Each Item In OpenFolder.Windows If Item.Document.Folder.Self.Path = MyFolder Then Item.Quit() End If Next End Sub End Class
La vida loca
Hey MonkeyBoy. At first glance this seemed to work but after using it for a while I found that it causes an error in the following Sub:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Dim MyFolder As String = "C:\Users\John\Desktop\Test" Dim OpenFolder As Object = CreateObject("shell.application") For Each Item In OpenFolder.Windows If Item.Document.Folder.Self.Path = MyFolder Then Item.Quit() End If Next End Sub
The error is that if there is an Internet Explorer window open I get the following error: "Public member 'Folder' on type 'HTMLDocumentClass' not found." So I guess I need to check if "Item" is not an HTMLDocumentClass or just use a try - catch in the code.
Well windows explorer is not internet explorer. The code I provided is to detect if windows explorer has a folder open only.
Also if rlwa32's coe works try it. And rlwa32's code using uri for the qualified path will auto parse the path out. You can also try disposing of the 'OpenFolder object after using it in case that mey resolve any issues. I only have a smart phone and have to drive 16 miles to the library to upload tested code so I can't assist much further really.
La vida loca
Wednesday, February 21, 2018 7:26 PM
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click Dim objShell As Shell32.Shell = New Shell32.Shell() For Each ie As InternetExplorer In objShell.Windows() Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2) If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system Dim loc As Uri = New Uri(ie.LocationURL) Dim path As String = loc.LocalPath End If Next End Sub
Thanks. This does provide another way of providing a list of open windows but the question remains, how do I close a window?
Wednesday, February 21, 2018 7:38 PM
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click Dim objShell As Shell32.Shell = New Shell32.Shell() For Each ie As InternetExplorer In objShell.Windows() Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2) If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system Dim loc As Uri = New Uri(ie.LocationURL) Dim path As String = loc.LocalPath End If Next End Sub
Thanks. This does provide another way of providing a list of open windows but the question remains, how do I close a window?
Same as before. Get the HWND from the InternetExplorer object and send it a WM_CLOSE message.
Wednesday, February 21, 2018 8:03 PM
Also if rlwa32's coe works try it. And rlwa32's code using uri for the qualified path will auto parse the path out. You can also try disposing of the 'OpenFolder object after using it in case that mey resolve any issues. I only have a smart phone and have to drive 16 miles to the library to upload tested code so I can't assist much further really.
La vida loca
OK and thanks for all your help. You have given me a few ideas. With your help and the help of others that have posted here I have written some code that will open Folder Windows and list out all folder windows that are open in Windows Explorer. Unfortunately I had to write some pretty convoluted code to reliably close Folder Windows. In all cases I had to use a try and catch to ensure I didn't get an unhandled error when the user also has an Internet Explorer window open.
Wednesday, February 21, 2018 8:14 PM
Unfortunately I had to write some pretty convoluted code to reliably close Folder Windows. In all cases I had to use a try and catch to ensure I didn't get an unhandled error when the user also has an Internet Explorer window open.
If you think about the code I posted that culls out Internet Explorer browsers from file system Explorer windows you should be able to use the same concept to ensure that you only attempt to close an InternetExplorer object that is looking at the file system.
Thursday, February 22, 2018 3:36 AM
If you think about the code I posted that culls out Internet Explorer browsers from file system Explorer windows you should be able to use the same concept to ensure that you only attempt to close an InternetExplorer object that is looking at the file system.
Thanks but I have no idea what you mean by that.
Thursday, February 22, 2018 7:28 AM
Thanks. This does provide another way of providing a list of open windows but the question remains, how do I close a window?
Same as before. Get the HWND from the InternetExplorer object and send it a WM_CLOSE message.
Thanks this does do a good job of culling out the internet Explorer Windows but does not fix the issue of having the convoluted code because it does not reliably close windows. Just like my previous example I have to loop through to close windows, then check to see if they were closed and go back and try again until all the folders of interest are closed. Here is my example using the WM_CLOSE message
Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click 'Close open folders
Dim ItemCount As Integer
Dim objShell As Shell32.Shell = New Shell32.Shell()
Dim MyHWND As Long
Dim FoldersToDelete As Boolean
FoldersToDelete = True
ItemCount = 0
While FoldersToDelete = True
For Each ie As InternetExplorer In objShell.Windows() 'Loop to close folders
FoldersToDelete = False
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
ItemCount += 1
filesListBox.Items.Add("ItemCount " & ItemCount & " " & path)
Select Case path
Case OpenFolder1, OpenFolder2, OpenFolder3, OpenFolder4, OpenFolder5
MyHWND = ie.HWND
SendMessageW(MyHWND, WM_CLOSE, 0, 0)
filesListBox.Items.Add("Closing folder " & MyHWND & " " & path)
End Select
End If
Next
For Each ie As InternetExplorer In objShell.Windows() 'Loop to Check if the folders were closed
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
Select Case path
Case OpenFolder1, OpenFolder2, OpenFolder3, OpenFolder4, OpenFolder5
FoldersToDelete = True
End Select
End If
Next
End While
End Sub
Thursday, February 22, 2018 11:52 AM
Same as before. Get the HWND from the InternetExplorer object and send it a WM_CLOSE message.
Thanks this does do a good job of culling out the internet Explorer Windows but does not fix the issue of having the convoluted code because it does not reliably close windows. Just like my previous example I have to loop through to close windows, then check to see if they were closed and go back and try again until all the folders of interest are closed.
I don't know what you mean by "does not reliably close windows."
It seems you are suggesting that after you obtain a valid window handle that the window does not close after it receives a WM_CLOSE message. Are you suggesting that you have discovered a bug in Windows?
I commented early in this thread that trying to work with Explorer windows in this fashion is inherently fragile. I also asked what purpose opening and closing Explorer windows served with a view towards identifying a different, controllable and robust way to achieve your objectives. Others also asked the same question. So far, that question remains unanswered.
Thursday, February 22, 2018 9:02 PM
Same as before. Get the HWND from the InternetExplorer object and send it a WM_CLOSE message.
Thanks this does do a good job of culling out the internet Explorer Windows but does not fix the issue of having the convoluted code because it does not reliably close windows. Just like my previous example I have to loop through to close windows, then check to see if they were closed and go back and try again until all the folders of interest are closed.
I don't know what you mean by "does not reliably close windows."
It seems you are suggesting that after you obtain a valid window handle that the window does not close after it receives a WM_CLOSE message. Are you suggesting that you have discovered a bug in Windows?
I commented early in this thread that trying to work with Explorer windows in this fashion is inherently fragile. I also asked what purpose opening and closing Explorer windows served with a view towards identifying a different, controllable and robust way to achieve your objectives. Others also asked the same question. So far, that question remains unanswered.
I am absolutely not suggesting there is a bug in Windows where it does not close a window after it receives a WM_CLOSE message. I am suggesting that the code does not send all the close messages it needs to send. Let me explain:
After a few hours of debugging and working with the code I had posted (the Button9 code above) I found that something strange happens if you are closing windows while trying to determine what folders are open. It took me a while to grasp what may be happening as the numbers of open folders are reduced. This is what I think is happening in the Button9 code:
- In my test case I have 10 folders open and 5 of these are the ones I want to close.
- The conditional statement for looping through to detect open windows and closing them is "For Each ie As InternetExplorer In objShell.Windows() 'Loop to close folders"
- When the program executes it loops and detects a window that needs it to close and sends the WM_CLOSE message and Windows closes the window associated with that handle. It then evaluates if it has examined all the open windows. The code will execute a couple of these loops and the numbers of open windows will reduce. Some where in its evaluation of "For Each is As......" which I interpret as 'have I examined all ie objects' it determines it has completed examining all open windows and exits. This happens after 1, 2, 3 or 4 windows have been closed and is somewhat random. Thus the need for the outer loop to detect if all the open folder windows of interest were actually closed.
So with that in mind I thought that a better way to accomplish what I want is to split the code into 2 parts. The first part detects what folders are open that I want to close and records the handle in an array and the second part loops through that array and sends the WM_CLOSE message. The example code looks like this:
Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click
Dim objShell As Shell32.Shell = New Shell32.Shell()
Dim ItemCount As Integer
Dim HWNDcount As Integer
Dim FoldersToDelete As Boolean
Dim FolderHWNDs(50) As Long
FoldersToDelete = False
ItemCount = 0
HWNDcount = 0
For Each ie As InternetExplorer In objShell.Windows() 'Loop to get the HWNDs
Dim sfv As ShellFolderView = TryCast(ie.Document, IShellFolderViewDual2)
If Not IsNothing(sfv) Then ' If sfv is nothing the InternetExplorer object is not browsing file system
Dim loc As Uri = New Uri(ie.LocationURL)
Dim path As String = loc.LocalPath
ItemCount += 1
filesListBox.Items.Add("ItemCount " & ItemCount & " " & path)
Select Case path
Case OpenFolder1, OpenFolder2, OpenFolder3, OpenFolder4, OpenFolder5
FolderHWNDs(HWNDcount) = ie.HWND
FoldersToDelete = True
filesListBox.Items.Add("Got HWND and need to close item " & ItemCount & " with HWND " & FolderHWNDs(HWNDcount) & " " & path)
HWNDcount += 1
End Select
End If
Next
If FoldersToDelete = True Then 'Close all folders in the FolderHWNDs Array
For ItemCount = 0 To HWNDcount - 1
filesListBox.Items.Add("Closing " & FolderHWNDs(ItemCount))
SendMessageW(FolderHWNDs(ItemCount), WM_CLOSE, 0, 0)
Next
End If
End Sub
So with your help I was able to get a better way of listing out open Windows Folders (by culling out the Internet Explorer windows) and reliably closing those folders that I want to close. Thanks for your help.
Thursday, February 22, 2018 9:32 PM
If you are interested, following alternative will directly open an Explorer window to a specified file system path and enable you to directly associate the resulting InternetExplorer object with its HWND. Consequently, you would have no need to use the shell windows collection.
Error checking is completely omitted
Public Class Form1
<DllImport("User32.dll", CallingConvention:=CallingConvention.StdCall)>
Public Shared Function PostMessage(ByVal hwnd As IntPtr, msg As UInt16, wparam As Integer, lparam As Integer) As Integer
End Function
Dim ShellBrowser As Guid = New Guid("c08afd90-f2a1-11d1-8455-00a0c91f3880")
Dim hwnd As IntPtr
Dim WM_CLOSE As Integer = &H10
Private Sub OnOpen(sender As Object, e As EventArgs) Handles Button1.Click
Dim objShellBrowser As Object
Dim IE As InternetExplorer
Dim url As Uri = New Uri("C:\Users\RLWA32\Documents")
objShellBrowser = Activator.CreateInstance(Type.GetTypeFromCLSID(ShellBrowser))
IE = objShellBrowser
IE.Navigate2(url.AbsoluteUri)
IE.Visible = True
hwnd = IE.HWND
End Sub
Private Sub OnClose(sender As Object, e As EventArgs) Handles Button2.Click
PostMessage(hwnd, WM_CLOSE, 0, 0)
End Sub
End Class