Announcement

Collapse
No announcement yet.

Enumerating DLLs

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Semen Matusovski
    replied
    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).]

    Leave a comment:


  • Peter Manders
    replied
    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:


  • Semen Matusovski
    replied
    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
    Warning: it's not final code.

    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:


  • Semen Matusovski
    replied
    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:


  • Ralph Berger
    replied
    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
    changes in false branch of EnumModules

    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
    Ralph


    ------------------

    Leave a comment:


  • Ralph Berger
    replied
    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:


  • Semen Matusovski
    replied
    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
    By the way, a suggesstion for further releases - to do like in VB, which resolves a reference, when you call a function only.
    Or PB can simply set error code.

    It's possible to avoid wrong situation (LoadLibrary ...), but very not comfortable.

    ------------------

    Leave a comment:


  • Ralph Berger
    replied
    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:


  • Semen Matusovski
    started a topic Enumerating DLLs

    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
    But I found, that under NT/2000 it's possible to retrieve also DLL's list.
    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).]
Working...
X