Peter --
BringWindowToTop is subset of SetWindowPos and does nothing in this situation under 98/2000.
For whome is interesting.
A list of rectrictions for SetForegroundWindow under Windows 98, Windows 2000: (MSDN)
The system restricts which processes can set the foreground window.
A process can set the foreground window only if one of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000: No menus are active.
With this change, an application cannot force a window to the foreground while the user is working with another window.
Instead, SetForegroundWindow will activate the window (see SetActiveWindow) and call the FlashWindowEx function to notify the user.
About 95 - probably, does something, but here SetForegroundWindow exactly works.
------------------
[This message has been edited by Semen Matusovski (edited August 02, 2000).]
Announcement
Collapse
No announcement yet.
Enumerating DLLs
Collapse
X
-
Semen,
Very impressive, but why didn't you use BringWindowToTop hWnd ?
I thought it would be a bit easier to use.
Peter.
------------------
Leave a comment:
-
1) There are reasons to think, that Process32... works under Win2000.
2) I constructed a function, which activates first instance.
Code:' Based on HOWTO: List Running Processes ID: Q187913 #Compile Exe #Dim All #Register None #Include "Win32Api.Inc" '=============================== INC ============================== %TH32CS_SNAPPROCESS = &H2& Type PROCESSENTRY32 dwSize As Dword cntUsage As Dword th32ProcessID As Dword ' This process th32DefaultHeapID As Long Ptr th32ModuleID As Dword ' Associated exe cntThreads As Dword th32ParentProcessID As Dword ' This process's parent process pcPriClassBase As Long ' Base priority of process threads dwFlags As Dword szExeFile As Asciiz * %MAX_PATH End Type ' For 9x Declare Function Process32First _ (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Declare Function Process32Next _ (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Declare Function CreateToolhelp32Snapshot _ (ByVal dwFlags As Dword, ByVal th32ProcessID As Dword) As Long ' For Nt/2000 Declare Function EnumProcesses _ (lpidProcess As Dword, ByVal cb As Dword, cbNeeded As Dword) As Long Declare Function GetModuleFileNameEx _ (ByVal hProcess As Dword, ByVal hModule As Dword, ModuleName As Asciiz, ByVal nSize As Dword) As Dword Declare Function EnumProcessModules _ (ByVal hProcess As Dword, ByRef lphModule As Dword, ByVal cb As Dword, cbNeeded As Dword) As Long Global hWndOfDuplicateInstance As Long Function EnumWindowsProc (ByVal hwnd As Long, ByVal lParam As Dword) As Long Dim cProcessId As Long GetWindowThreadProcessId hwnd, cProcessId If lParam = cProcessId Then Function = %False: hWndOfDuplicateInstance = hWnd Else _ Function = %True End Function Declare Function SwitchToThisWindow(hWnd As Long, chState As Long) As Long Sub pSetForegroundWindow(hwnd As Long) Dim hSwitchToThisWindow As Dword, lResult As Long Dim lForeThreadID As Long, lThisThreadID As Long, hWndF As Long hSwitchToThisWindow = GetProcAddress(GetModuleHandle("user32.dll"), "SwitchToThisWindow") Do If IsIconic(hwnd) Then ShowWindow hwnd, %SW_RESTORE Else ShowWindow hwnd, %SW_SHOW SetForegroundWindow hwnd: Sleep 1 hWndF = GetForegroundWindow: If hwnd = hWndF Then Exit Sub lForeThreadID = GetWindowThreadProcessId(hWndF, ByVal 0&) lThisThreadID = GetWindowThreadProcessId(hwnd, ByVal 0&) If lForeThreadID <> lThisThreadID Then _ AttachThreadInput lForeThreadID, lThisThreadID, %True SetForegroundWindow hwnd: Sleep 1 If lForeThreadID <> lThisThreadID Then _ AttachThreadInput lForeThreadID, lThisThreadID, %False hWndF = GetForegroundWindow: If hwnd = hWndF Then Exit Sub Call Dword hSwitchToThisWindow Using SwitchToThisWindow(hwnd, %True) To lResult: Sleep 1 hWndF = GetForegroundWindow: If hwnd = hWndF Then Exit Sub ShowWindow hWnd, %SW_MINIMIZE Loop End Sub Function DuplicateInstance As Long Dim os As OSVERSIONINFO, Proc As PROCESSENTRY32 Dim ExeName As Asciiz * %MAX_PATH, ProcessId As Dword, _ dExeName As Asciiz * %MAX_PATH, dProcessId As Dword Dim cb As Dword, cbNeeded As Dword Dim i As Long, j As Long, nModules As Long, nProcesses As Long, hProcess As Dword, lResult As Long Dim hKernel32 As Dword, hCreateToolhelp32Snapshot As Dword, hProcess32Next As Dword, hProcess32First As Dword Dim hPsApiDll As Dword, hEnumProcesses As Dword, hGetModuleFileNameEx As Dword, hEnumProcessModules As Dword If IsFalse(GetModuleFileName (GetModuleHandle(ByVal 0&), Proc.szExeFile, SizeOf(Proc.szExeFile))) Then Exit Function If IsFalse(GetShortPathName (Proc.szExeFile, ExeName, SizeOf(ExeName))) Then Exit Function CharUpperBuff ExeName, Len(ExeName) ProcessId = GetCurrentProcessId os.dwOSVersionInfoSize = SizeOf(os) GetVersionEx ByVal VarPtr(os) If IsFalse(os.dwPlatformId = %VER_PLATFORM_WIN32_NT) Then ' Windows 95/98 hKernel32 = GetModuleHandle("kernel32.dll") hCreateToolhelp32Snapshot = GetProcAddress(hKernel32, "CreateToolhelp32Snapshot") hProcess32Next = GetProcAddress(hKernel32, "Process32Next") hProcess32First = GetProcAddress(hKernel32, "Process32First") Call Dword hCreateToolhelp32Snapshot Using _ CreateToolhelp32Snapshot (%TH32CS_SNAPPROCESS, 0&) To i If i = 0 Then Exit Function Proc.dwSize = SizeOf(Proc) Call Dword hProcess32First Using Process32First (i, Proc) To j While j If Proc.th32ProcessID = ProcessId Then ElseIf IsFalse(GetShortPathName (Proc.szExeFile, dExeName, SizeOf(dExeName))) Then ElseIf IsFalse CharUpperBuff(dExeName, Len(dExeName)) Then ElseIf ExeName = dExeName Then dProcessId = Proc.th32ProcessID End If If dProcessId Then Exit Do Call Dword hProcess32Next Using Process32Next (i, Proc) To j Wend Else ' Windows NT hPsApiDll = GetModuleHandle("psApi.dll") If hPsApiDll = 0 Then hPsApiDll = LoadLibrary("psApi.dll") hEnumProcesses = GetProcAddress(hPsApiDll, "EnumProcesses") hGetModuleFileNameEx = GetProcAddress(hPsApiDll, "GetModuleFileNameExA") hEnumProcessModules = GetProcAddress(hPsApiDll, "EnumProcessModules") cb = 100 Do ReDim ProcessIDs(1 To cb / 4) As Dword Call Dword hEnumProcesses Using EnumProcesses (ProcessIDs(1), cb, cbNeeded) To lResult If cb > cbNeeded Then Exit Do cb = cb * 2 Loop nProcesses = cbNeeded / 4 For i = 1 To nProcesses hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION Or %PROCESS_VM_READ, %False, ProcessIDs(i)) If hProcess <> 0 Then cb = 100 Do ReDim Modules(1 To cb / 4) As Dword Call Dword hEnumProcessModules Using _ EnumProcessModules (hProcess, Modules(1), cb, cbNeeded) To lResult If lResult = 0 Then cbNeeded = 0: Exit Do If cb > cbNeeded Then Exit Do Else cb = cb * 2 Loop nModules = cbNeeded / 4 ' Exe is first Call Dword hGetModuleFileNameEx Using GetModuleFileNameEx _ (hProcess, Modules(1), Proc.szExeFile, SizeOf(Proc.szExeFile)) To lResult If IsFalse(lResult) Then ElseIf ProcessIDs(i) = ProcessId Then ElseIf IsFalse(GetShortPathName (Proc.szExeFile, dExeName, SizeOf(dExeName))) Then ElseIf IsFalse CharUpperBuff(dExeName, Len(dExeName)) Then ElseIf ExeName = dExeName Then dProcessId = ProcessIDs(i) End If End If CloseHandle hProcess If dProcessId Then Exit For Next End If If IsFalse(dProcessId) Then Exit Function EnumWindows CodePtr(EnumWindowsProc), dProcessId If IsFalse(hWndOfDuplicateInstance) Then Exit Function pSetForegroundWindow hWndOfDuplicateInstance Function = %True End Function '======================================================================= Function PbMain If DuplicateInstance Then Exit Function Local hDlg As Long Dialog New 0, "Processes and modules", , , 400, 200, _ %WS_SYSMENU Or %WS_CAPTION Or %WS_MINIMIZEBOX, To hDlg Control Add TextBox, hDlg, 101, "", 10, 10, 380, 180, _ %ES_MULTILINE Or %ES_WANTRETURN, %WS_EX_CLIENTEDGE Dialog Show Modal hDlg End Function
You can test this code by starting one instance in IDE and another in Explorer.
What I don't like ... Sometimes a text within textbox is selected.
Somebody saw non-classic methods to activate ceirtain window ?
For example, by imitation mouse click on caption/task bar and so on ...
------------------
[This message has been edited by Semen Matusovski (edited August 02, 2000).]
Leave a comment:
-
Ralph --
Thanks, that you pointed this fact. A code is re-posted.
I understood "difference" between NT4 and Win2000.
In Win2000' kernel32.dll there are functions Process32... and CreateSnap...
What they are doing here ?
Hmm .. Interesting, it's necessary to investigate.
[This message has been edited by Semen Matusovski (edited August 01, 2000).]
Leave a comment:
-
Semen,
with the minor changes below your code runs on NT4 and W98 to.
Code:'/* proto */ ' same DECLARE for Process32First and Process32Next DECLARE FUNCTION Process32(BYVAL hSnapshot AS LONG, lppe AS PROCESSENTRY32) AS LONG DECLARE FUNCTION EnumProcesses(lpidProcess AS DWORD, BYVAL cb AS DWORD, cbNeeded AS DWORD) AS LONG DECLARE FUNCTION GetModuleFileNameEx(BYVAL hProcess AS DWORD, BYVAL hModule AS DWORD, ModuleName AS ASCIIZ, BYVAL nSize AS DWORD) AS DWORD DECLARE FUNCTION EnumProcessModules(BYVAL hProcess AS DWORD, BYREF lphModule AS DWORD, BYVAL cb AS DWORD, cbNeeded AS DWORD) AS LONG DECLARE FUNCTION CreateToolhelp32Snapshot(BYVAL dwFlags AS DWORD, BYVAL th32ProcessID AS DWORD) AS LONG
Code:DIM f AS LONG, sname AS STRING DIM hSnap AS LONG, proc AS PROCESSENTRY32 LOCAL hProcess32First AS DWORD, hProcess32Next AS DWORD, CrToolhlp32Snp AS DWORD, hKernelDll AS DWORD '' no err check for hKernelDll it's always loaded hKernelDll = GetModuleHandle("kernel32.dll") CrToolhlp32Snp = GetProcAddress(hKernelDll, "CreateToolhelp32Snapshot") CALL DWORD CrToolhlp32Snp USING CreateToolhelp32Snapshot(%TH32CS_SNAPPROCESS, 0) TO hSnap IF ISFALSE hSnap THEN EXIT SUB hProcess32First = GetProcAddress(hKernelDll, "Process32First") hProcess32Next = GetProcAddress(hKernelDll, "Process32Next") proc.dwSize = LEN(proc) CALL DWORD hProcess32First USING Process32 (hSnap, proc) TO f DO WHILE f LISTBOX ADD hDlg, 101, proc.szExeFile CALL DWORD hProcess32Next USING Process32 (hSnap, proc) TO f LOOP
------------------
Leave a comment:
-
Semen,
it seems W2K and WinNt ( i use NT 4 SP 6 ) are loading DLL's
in a different way. Tried your code and got the err msg:
procedure entry point "process32first" could not be found
in "kernel32.dll"
Ralph
------------------
Leave a comment:
-
Ralph --
>> very nice code.
Agree, in MSDN there are enough interesting pieces.
I wanted to correct a fragment, which searches duplicate instance of Exe.
Instead of unusful message - "this is a duplicate instance", much better to transfer control to top-level window of first instance.
To do this, it's necessary to add EnumWindows + GetWindowThreadProcessId.
>> But to run it under NT you should make the fct calls to Process32First and Process32Next indirect. Both are
not part of WinNt kernel32.dll.
It's not a problem. My main OS is Win2000 and fragment, posted above, was tested, first of all, under Y2K.
If do not call a function - under NT program doesn't call Process32First/Process32Next - no problems (because DLL is exist).
Functions in PSAPI.DLL is another question. 9x doesn't have this DLL and program doesn't start, if to use
Code:Declare ... Lib ... Alias
Or PB can simply set error code.
It's possible to avoid wrong situation (LoadLibrary ...), but very not comfortable.
------------------
Leave a comment:
-
Semen,
very nice code. But to run it under NT you should make the fct
calls to Process32First and Process32Next indirect. Both are
not part of WinNt kernel32.dll.
Ralph
------------------
Leave a comment:
-
Enumerating DLLs
I was interested to enumerate all running Exe and following code does it.
Code:' Based on HOWTO: List Running Processes ID: Q187913 #Compile Exe #Dim All #Register None #Include "Win32Api.Inc" Global hDlg As Long %TH32CS_SNAPPROCESS = &H2& Type PROCESSENTRY32 dwSize As Dword cntUsage As Dword th32ProcessID As Dword ' This process th32DefaultHeapID As Long Ptr th32ModuleID As Dword ' Associated exe cntThreads As Dword th32ParentProcessID As Dword ' This process's parent process pcPriClassBase As Long ' Base priority of process threads dwFlags As Dword szExeFile As Asciiz * %MAX_PATH End Type ' For 9x Declare Function Process32First _ (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Declare Function Process32Next _ (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Declare Function CreateToolhelp32Snapshot _ (ByVal dwFlags As Dword, ByVal th32ProcessID As Dword) As Long ' For Nt/2000 Declare Function EnumProcesses _ (lpidProcess As Dword, ByVal cb As Dword, cbNeeded As Dword) As Long Declare Function GetModuleFileNameEx _ (ByVal hProcess As Dword, ByVal hModule As Dword, ModuleName As Asciiz, ByVal nSize As Dword) As Dword Declare Function EnumProcessModules _ (ByVal hProcess As Dword, ByRef lphModule As Dword, ByVal cb As Dword, cbNeeded As Dword) As Long Sub EnumModules Dim os As OSVERSIONINFO, Proc As PROCESSENTRY32 Dim cb As Dword, cbNeeded As Dword Dim i As Long, j As Long, nModules As Long, nProcesses As Long, hProcess As Dword, lResult As Long Dim hKernel32 As Dword, hCreateToolhelp32Snapshot As Dword, hProcess32Next As Dword, hProcess32First As Dword Dim hPsApiDll As Dword, hEnumProcesses As Dword, hGetModuleFileNameEx As Dword, hEnumProcessModules As Dword os.dwOSVersionInfoSize = SizeOf(os) GetVersionEx ByVal VarPtr(os) ListBox Reset hDlg, 101 If IsFalse(os.dwPlatformId = %VER_PLATFORM_WIN32_NT) Then ' Windows 95/98 hKernel32 = GetModuleHandle("kernel32.dll") hCreateToolhelp32Snapshot = GetProcAddress(hKernel32, "CreateToolhelp32Snapshot") hProcess32Next = GetProcAddress(hKernel32, "Process32Next") hProcess32First = GetProcAddress(hKernel32, "Process32First") Call Dword hCreateToolhelp32Snapshot Using _ CreateToolhelp32Snapshot (%TH32CS_SNAPPROCESS, 0&) To i If i = 0 Then Exit Sub Proc.dwSize = SizeOf(Proc) Call Dword hProcess32First Using Process32First (i, Proc) To j While j ListBox Add hDlg, 101, Proc.szExeFile Call Dword hProcess32Next Using Process32Next (i, Proc) To j Wend Else ' Windows NT hPsApiDll = GetModuleHandle("psApi.dll") If hPsApiDll = 0 Then hPsApiDll = LoadLibrary("psApi.dll") hEnumProcesses = GetProcAddress(hPsApiDll, "EnumProcesses") hGetModuleFileNameEx = GetProcAddress(hPsApiDll, "GetModuleFileNameExA") hEnumProcessModules = GetProcAddress(hPsApiDll, "EnumProcessModules") cb = 100 Do ReDim ProcessIDs(1 To cb / 4) As Dword Call Dword hEnumProcesses Using EnumProcesses (ProcessIDs(1), cb, cbNeeded) To lResult If cb > cbNeeded Then Exit Do cb = cb * 2 Loop nProcesses = cbNeeded / 4 For i = 1 To nProcesses hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION Or %PROCESS_VM_READ, %False, ProcessIDs(i)) If hProcess <> 0 Then cb = 100 Do ReDim Modules(1 To cb / 4) As Dword Call Dword hEnumProcessModules Using _ EnumProcessModules (hProcess, Modules(1), cb, cbNeeded) To lResult If lResult = 0 Then cbNeeded = 0: Exit Do If cb > cbNeeded Then Exit Do Else cb = cb * 2 Loop nModules = cbNeeded / 4 For j = 1 To nModules Call Dword hGetModuleFileNameEx Using GetModuleFileNameEx _ (hProcess, Modules(j), Proc.szExeFile, SizeOf(Proc.szExeFile)) To lResult If lResult Then If j = 1 Then ListBox Add hDlg, 101, Proc.szExeFile Else _ ListBox Add hDlg, 101, " " + Proc.szExeFile Next CloseHandle hProcess End If Next End If End Sub CallBack Function DlgProc Select Case CbMsg Case %WM_INITDIALOG EnumModules Case %WM_SIZE Dim rc As RECT GetClientRect CbHndl, rc SetWindowPos GetDlgItem(CbHndl, 101), 0, _ 0.03 * rc.nRight, 0.02 * rc.nBottom, 0.94 * rc.nRight, _ 0.96 * rc.nBottom, %SWP_NOACTIVATE Or %SWP_NOZORDER End Select End Function Function PbMain Dialog New 0, "Processes and modules", , , 400, 200, _ %WS_SYSMENU Or %WS_CAPTION Or %WS_THICKFRAME, To hDlg Control Add ListBox, hDlg, 101, , 0, 0, 0, 0, %WS_CHILD Or %WS_VSCROLL, %WS_EX_CLIENTEDGE Dialog Show Modal hDlg Call DlgProc End Function
I thought that this knowledge can be useful, for example, to detect "gifts" in own process.
Somebody knows how to retrieve the DLL's list under 9x ?
(it's not very important and I already solved initial task, but interesting ...)
------------------
[This message has been edited by Semen Matusovski (edited August 01, 2000).]Tags: None
Leave a comment: