Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem using USER32 function

Status
Not open for further replies.

jmille34

Programmer
Joined
Sep 14, 2005
Messages
224
Location
US
Code:
Public Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As System.IntPtr) As Integer
...
Dim p As Process
For Each p In Process.GetProcesses
  Try
    MsgBox(p.ProcessName & "=" & IsWindowVisible(p.Handle))
  Catch ex As Exception
  End Try
Next

I've tried a zillion variations on this code, and I just cannot get it to be able to tell if each process is visible or not. It will pull the same list you would see in task manager, but all handles return 0. I tried changing the api return to boolean, and they all return false.

I'm running x64 if that matters, but I thought that's why you use system.intprt instead of integer or long.

Is this api IsWindowVisible the wrong one for this purpose? It sounded pretty darn specific when I found it, but now I'm wondering if it's a red herring.
 
So when you run it, windows that are visible on the task bar return true, and everything else returns false?

I just tried it on a different machine with regular xp32, and it still returned false for everything.. :(

It's *eventually* going to be a desktop manager that roughly reproduces some of the functionality of the Linux multiple desktop system using icons in the system tray, and a way to send open apps to other desktops. At work it's not uncommon for me to have 18 gazillion different windows going, and though I can't run linux there, some desktop switching would be nice.. I tried a few shareware, but I didn't like them.. I want something ultra simple.. sooooo if I can figure this out I'ma do it muhself
 
If you read the MSDN article I mentioned you will see that that is not what happens. My results are those that I would have expected based on that document.

[vampire][bat]
 
I've put this slightly more comprehensive solution together so that you can see the results that you would get from interpreting the data slightly differently.

The sections marked in bold will give you what you need plus the Desktop (which you can check for and ignore if you don't need it)

Code:
  [b]Public Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As System.IntPtr) As Integer[/b]

  Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click

    [b]Dim VisibleWindowsByWindowHandle As New ArrayList[/b]
    Dim InvisibleWindowsByWindowHandle As New ArrayList
    Dim VisibleWindowsByProcessHandle As New ArrayList
    Dim InvisibleWindowsByProcessHandle As New ArrayList

    Dim IsVisibleByProcess As Boolean
    [b]Dim IsVisibleByWindow As Boolean[/b]

    Dim a As Integer
    Dim processes() As Process = System.Diagnostics.Process.GetProcesses

    Dim nl As String = Environment.NewLine

    TextBox1.Text = "Total Processes found: " + processes.Length.ToString + nl
    TextBox1.Text += "------------------------------------" + nl + nl

    TextBox1.Text += "Errors" + nl
    TextBox1.Text += "=====================================" + nl
    [b]For Each p As Process In processes
      Try
        p.Refresh() 'Not necessary, but can't hurt[/b]
        IsVisibleByProcess = CBool(IsWindowVisible(p.Handle))
        [b]IsVisibleByWindow = CBool(IsWindowVisible(p.MainWindowHandle))[/b]
        If IsVisibleByProcess Then
          VisibleWindowsByProcessHandle.Add(p.ProcessName + " ==> " + p.MainWindowTitle)
        Else
          InvisibleWindowsByProcessHandle.Add(p.ProcessName)
        End If
        [b]If IsVisibleByWindow Then
          If p.ProcessName = "explorer" AndAlso p.MainWindowTitle = "" Then
            VisibleWindowsByWindowHandle.Add(p.ProcessName + " ==> " + "<Windows Desktop>")
          Else
            VisibleWindowsByWindowHandle.Add(p.ProcessName + " ==> " + p.MainWindowTitle)
          End If[/b]
        Else
          InvisibleWindowsByWindowHandle.Add(p.MainWindowTitle + " (" + p.ProcessName + ")")
        [b]End If[/b]
      [b]Catch[/b]
        TextBox1.Text += p.ProcessName + nl
      [b]End Try[/b]
    [b]Next[/b]

    TextBox1.Text += "------------------------" + nl + nl

    TextBox1.Text += "Visible Windows By Process Handle (" + _
                                    VisibleWindowsByProcessHandle.Count.ToString + ")" + nl
    TextBox1.Text += "====================================" + nl
    For a = 0 To VisibleWindowsByProcessHandle.Count - 1
      TextBox1.Text += VisibleWindowsByProcessHandle(a).ToString + nl
    Next
    TextBox1.Text += "-----------------------------------" + nl
    TextBox1.Text += nl

    TextBox1.Text += "Invisible Windows By Process Handle (" + _
                                    InvisibleWindowsByProcessHandle.Count.ToString + ")" + nl
    TextBox1.Text += "====================================" + nl
    For a = 0 To InvisibleWindowsByProcessHandle.Count - 1
      TextBox1.Text += InvisibleWindowsByProcessHandle(a).ToString + nl
    Next
    TextBox1.Text += "-----------------------------------" + nl
    TextBox1.Text += nl

    TextBox1.Text += "Visible Windows By Window Handle (" + _
                                    VisibleWindowsByWindowHandle.Count.ToString + ")" + nl
    TextBox1.Text += "====================================" + nl
    For a = 0 To VisibleWindowsByWindowHandle.Count - 1
      TextBox1.Text += VisibleWindowsByWindowHandle(a).ToString + nl
    Next
    TextBox1.Text += "-----------------------------------" + nl
    TextBox1.Text += nl

    TextBox1.Text += "Invisible Windows By Window Handle (" + _
                                    InvisibleWindowsByWindowHandle.Count.ToString + ")" + nl
    TextBox1.Text += "====================================" + nl
    For a = 0 To InvisibleWindowsByWindowHandle.Count - 1
      TextBox1.Text += InvisibleWindowsByWindowHandle(a).ToString + nl
    Next
    TextBox1.Text += "-----------------------------------" + nl
    TextBox1.Text += nl

    VisibleWindowsByWindowHandle = Nothing
    InvisibleWindowsByWindowHandle = Nothing
    VisibleWindowsByProcessHandle = Nothing
    InvisibleWindowsByProcessHandle = Nothing

  End Sub


Hope this helps.

[vampire][bat]
 
Code:
CBool(IsWindowVisible(p.MainWindowHandle))

I've been searching for that line all day! Thank you very much!

Your code worked like a charm, and I used it to confirm that it worked in mine too.. thanks much :)
 
Oh, and I did read the article you posted, but I didn't realize the difference between the process handle and the window handle... plus that mystical property mainwindowhandle that I completely overlooked.. sheesh.. it's times like this I hate oop.. playing "hunt the property" for hours on end..
 
Can we kill process?
when I run my program excel is still in the memory ... i have to end the process from the task manager or exit the program inorder to open the excel file.
 
Yes you can - if p is the process of interest then you can use p.kill to terminate the process.

However that should be an absolute last resort.

Search this forum, the problem of not being able to remove Excel has been answered several times and one of those solutions would be better than killing the process.


Hope this helps.

[vampire][bat]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top