PDA

View Full Version : list all running programs



afslaughter
03-22-2011, 09:34 AM
I want to populate a combobox with a list of all running programs. I found a code that works well, but its list everything. I just need a list of the visible programs like when using Alt-Tab. Thanks for any help. Here is what I have:


Public Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Const MAX_LEN = 260
Public Function EnumWinProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
Dim lRet As Long
Dim strBuffer As String

If IsWindowVisible(hwnd) Then
strBuffer = Space(MAX_LEN)
lRet = GetWindowText(hwnd, strBuffer, Len(strBuffer))
If lRet Then
UserForm1.ComboBox1.AddItem Left(strBuffer & " " & hwnd, lRet)
End If
End If

EnumWinProc = 1
End Function

mdmackillop
03-22-2011, 03:39 PM
Does this help (http://www.vbaexpress.com/forum/showthread.php?t=36318)

Kenneth Hobs
03-22-2011, 04:35 PM
Here is one method using what I explained in the referenced thread. Of course these are not all "visible" in Task Manager.

Sub Test_AllRunningApps()
Dim apps() As Variant
apps() = AllRunningApps
Range("A1").Resize(UBound(apps), 1).Value2 = WorksheetFunction.Transpose(apps)
Range("A:A").Columns.AutoFit
End Sub

'Similar to: http://msdn.microsoft.com/en-us/library/aa393618%28VS.85%29.aspx
Public Function AllRunningApps() As Variant
Dim strComputer As String
Dim objServices As Object, objProcessSet As Object, Process As Object
Dim oDic As Object, a() As Variant
Set oDic = CreateObject("Scripting.Dictionary")
strComputer = "."
Set objServices = GetObject("winmgmts:\\" _
& strComputer & "\root\CIMV2")
Set objProcessSet = objServices.ExecQuery _
("SELECT Name FROM Win32_Process", , 48)
For Each Process In objProcessSet
If Not oDic.exists(Process.Name) Then oDic.Add Process.Name, Process.Name
Next
a() = oDic.keys
Set objProcessSet = Nothing
Set oDic = Nothing
AllRunningApps = a()
End Function

afslaughter
03-23-2011, 05:06 AM
Thank you for the quick and informative replies, but I can't figure out how to filter the output to show only visible apps. Is there some tag or ID that indicates whether an app is in the visible in the taskmaager. If so how can I extract that information. Thanks again for any assistance.

Kenneth Hobs
03-23-2011, 06:25 AM
Are you just wanting the caption titles as shown in the Application tab in Task Manager or do you want handles to those windows for use in other tasks?

I don't have time right now to convert this but you might be able to adapt your code to what was done in this c# code. http://www.neowin.net/forum/topic/369213-c%23-list-running-applications/

From your API code, I don't see what you did to call your function. You would need to get the handle and lParam for the Desktop Window I am thinking.

afslaughter
03-23-2011, 09:20 AM
It would be great to get the caption value. I think it my help if I include the full scope of my project. I want to create a drop down list that a user can choose the correct window to copy data to. I can’t do a CreateObject("Myapp.Application") and control it from the start, so this is the next best option. The only problem is the app list that I have now may be too long and technical for a not so computer savvy user ("which is most of the people using it") The EnumWindows is call with a command button and brings up a Userform that loads the Combo box with the output. When the program is selected from the list they can send the data in the Userform to that App with a click of the button. You can probably tell from my code that I am still a beginner on this stuff so I apologize if I can’t understand the more complicated programming. This is everything:


Start Button:
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
Set myRange = ActiveSheet.Range("A:A")
Answer = Application.WorksheetFunction.CountIf(myRange, "<>")
If Answer = 0 Then GoTo NoSel
If Answer = 1 Then GoTo Good
Application.ScreenUpdating = True
MsgBox " Only 1 selection can be used."
Exit Sub
NoSel:
Application.ScreenUpdating = True
MsgBox " No selection Made."
Exit Sub
Good:
Application.EnableEvents = False
ActiveSheet.Range("A:A").Select
Selection.Find(What:=">").Select
Application.EnableEvents = True
Application.ScreenUpdating = True
TransferForm.Show
End Sub

I already posted the Find Programs Code

UserForm Open
Private Sub UserForm_Activate()
Dim SYM, WUC, DIS, SO, TOR, TASK, wd, TM, AT, HM, WC, EID

Application.ScreenUpdating = False
Sheets("Discrepancy List").Select
SYM = ActiveCell.Offset(0, 1).Resize(1, 1).Value
WUC = ActiveCell.Offset(0, 2).Resize(1, 1).Value
DIS = ActiveCell.Offset(0, 3).Resize(1, 1).Value
SO = ActiveCell.Offset(0, 4).Resize(1, 1).Value
TOR = ActiveCell.Offset(0, 5).Resize(1, 1).Value
TASK = ActiveCell.Offset(0, 6).Resize(1, 1).Value
wd = ActiveCell.Offset(0, 7).Resize(1, 1).Value
TM = ActiveCell.Offset(0, 8).Resize(1, 1).Value
AT = ActiveCell.Offset(0, 9).Resize(1, 1).Value
HM = ActiveCell.Offset(0, 10).Resize(1, 1).Value

WC = Sheets("Data").Range("O4").Value
EID = Sheets("Data").Range("O9").Value

Application.ScreenUpdating = True

Application.Visible = False
Call EnumWindows(AddressOf EnumWinProc, 0)

SYMTextBox.Value = SYM
WUCTextBox.Value = WUC
DISTextBox.Value = DIS
CATextBox.Value = SO & " I.A.W. " & TOR & " " & TASK
WDTextBox.Value = wd
TMTextBox.Value = TM
ATTextBox.Value = AT
HMTextBox.Value = HM
WCTextBox.Value = WC
EIDTextBox.Value = EID

End Sub


The Send Button:
Private Sub SendButton_Click()
Dim MyAppData As DataObject
Dim MyApp
Set MyAppData = New DataObject
MyApp = ComboBox.Value
MyAppData.SetText SYMTextBox.Text
MyAppData.PutInClipboard
AppActivate MyApp
SendKeys "^{v}"
ActiveSheet.Activate

Kenneth Hobs
03-23-2011, 10:33 AM
I guess that I don't see the problem. Your code seems to do what you wanted.

afslaughter
03-23-2011, 10:44 AM
Yes it does work, but the problem was to try and trim down the program list to just the visible apps "like in the task manager". To make the list less confusing for the user.

Kenneth Hobs
03-23-2011, 10:59 AM
That is what shows for me. I currently have 46 unique process names and 8 applications shown in the combobox with 7 in the Applications tab in Windows Task Manager. The difference is that Program Manager is shown in the combobox but not in the Task Manager or Task Manager is shown in the combobox if it is open.

afslaughter
03-23-2011, 12:26 PM
OK maybe I’m doing something wrong. In my combo box I get:

Start
NetBanner
UserForm1
Clock
Weather
AppBar Bullet
Calendar
Windows Sidebar
list all running programs - VBA Express Forum - Internet Explorer
Inbox - Microsoft Outlook
Program Manager


But when I do an ALT-TAB I only see

UserForm1
list all running programs - VBA Express Forum - Internet Explorer
Inbox - Microsoft Outlook
Desktop

Which is all that I want in the combo box.

afslaughter
03-24-2011, 05:22 AM
I was doing more testing on this code and I am finding the AppActivate MyApp is not very reliable. Is there anything I can do to make it more stable.

Kenneth Hobs
03-24-2011, 06:26 AM
It seems ok to me for what it is intended. There are cases where it will fail though. e.g. If you have the VBE Toolbox open, it is listed in the combobox using your code. However, if you use ALT+TAB, it will not be listed nor is it listed in Windows Task Manager. Be sure to use True as the 2nd parameter for AppActivate.

afslaughter
03-24-2011, 08:20 AM
Ok, thank you so much for the help. I really appreciate it. If I can ask just one last question? With the code I have now when I call for the AppActivate can I add something to the parameters to set the ActiveWindow.WindowState to xlNormal or xlMaximized. To make sure the user doesn’t have the window Minimized. If they do the project will not work. I tried MyApp.ActiveWindow.WindowState = xlNormal and this does not work.

Kenneth Hobs
03-28-2011, 05:48 AM
In a Module:
Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Declare Function GetForegroundWindow Lib "user32" () As Long

' ShowWindow() Commands
Public Const SW_HIDE = 0
Public Const SW_SHOWNORMAL = 1
Public Const SW_NORMAL = 1
Public Const SW_SHOWMINIMIZED = 2
Public Const SW_SHOWMAXIMIZED = 3
Public Const SW_MAXIMIZE = 3
Public Const SW_SHOWNOACTIVATE = 4
Public Const SW_SHOW = 5
Public Const SW_MINIMIZE = 6
Public Const SW_SHOWMINNOACTIVE = 7
Public Const SW_SHOWNA = 8
Public Const SW_RESTORE = 9
Public Const SW_SHOWDEFAULT = 10
Public Const SW_MAX = 10

In the Userform:
Private Sub CommandButton1_Click()
AppActivate ComboBox1.Value, True
ShowWindow GetForegroundWindow, SW_SHOWMAXIMIZED
Unload Me
End Sub