itljl 发表于 2009-5-6 14:22:56

谁能将GetModuleFileName 开成AU3的?谢谢

本帖最后由 itljl 于 2009-5-23 16:59 编辑

GetModuleFileName   
函数说明:   
Unit   
Windows.Pas   
   
Syntax   
GetModuleFileName(   
hModule:   HINST; {a   handle   to   the   module}   
lpFilename:   PChar; {pointer   to   a   null   terminated   string   buffer}   
nSize:   DWORD {the   size   of   the   lpFilename   buffer}   
):   DWORD; {returns   the   number   of   characters   copied   to   the   buffer}   
   
Description   
This   function   retrieves   the   full   path   and   filename   of   the   module   identified   by   the   handle   in   the   hModule   parameter.   
   
Parameters   
hModule:   A   handle   to   the   module   whose   full   path   and   filename   are   to   be   retrieved.   If   this   parameter   is   set   to   zero,   the   function   returns   the   full   path   and   filename   of   the   calling   process.   
   
lpFilename:   A   pointer   to   a   null   terminated   string   buffer   that   receives   the   path   and   filename.   
   
nSize:   Specifies   the   size   of   the   buffer   pointed   to   by   the   lpFilename   parameter,   in   characters.   If   the   returned   path   and   filename   is   larger   than   this   value,   the   string   is   truncated.   
   
Return   Value   
If   the   function   succeeds,   it   returns   the   number   of   characters   copied   to   the   buffer   pointed   to   by   the   lpFilename   parameter;   otherwise   it   returns   zero.   To   get   extended   error   information,   call   the   GetLastError   function.   
   
The   Tomes   of   Delphi   3:   Win32   Core   API   Help   File   by   Larry   Diehl   
例子:   
library   Example;   
   
uses   
      SysUtils,   
      Classes,   
      Windows,   
      Dialogs,   
      DLLAboutForm   in   'DLLAboutForm.pas'   {AboutBox};   
   
{the   exported   functions}   
exports   
      ShowAboutBox   name   'ShowAboutBox';   
   
{the   DLL   entry   point   procedure.   this   procedure   will   fire   every   time   a   
    process   or   thread   attaches   to   the   DLL.   if   a   process   has   attached   to   a   DLL,   
    any   newly   created   threads   will   automatically   attach   themselves}   
procedure   DLLMain(AttachFlag:   DWORD);   
   
    begin   
      {display   attachement   type}   
      case   AttachFlag   of   
          DLL_PROCESS_ATTACH:   MessageBox(0,   'Process:   Attaching',   'Alert',   MB_OK);   
          DLL_PROCESS_DETACH:   MessageBox(0,   'Process:   Detaching',   'Alert',   MB_OK);   
          DLL_THREAD_ATTACH:   MessageBox(0,   'Thread:   Attaching'   ,   'Alert',   MB_OK);   
          DLL_THREAD_DETACH:   MessageBox(0,   'Thread:   Detaching'   ,   'Alert',   MB_OK);   
      end;   
end;   
   
begin   
      {initialize   the   DLL   entry   function}   
   
      DLLProc   :=   @DLLMain;   
   
      {call   the   entry   function   upon   DLL   initialization}   
      DLLMain(DLL_PROCESS_ATTACH);   
end.   
   
Unit   2   
   
{the   prototype   for   the   exported   function}   
      function   ShowAboutBox(ExampleName,   Comments:   ShortString):   Boolean;   export;   
   
var   
      AboutBox:   TAboutBox;   
   
implementation   
   
{$R   *.DFM}   
   
function   ShowAboutBox(ExampleName,   Comments:   ShortString):   Boolean;   
   
begin   
      {initialize   the   function   results}   
      Result   :=   FALSE;   
   
      {create   the   about   box   form}   
      AboutBox   :=   TAboutBox.Create(Application);   
   
      {initialize   labels   from   the   supplied   strings}   
      AboutBox.ProductName.Caption   :=   ExampleName;   
      AboutBox.Comments.Caption   :=   Comments;   
   
      {show   a   modal   about   box}   
      AboutBox.ShowModal;   
   
      {release   the   form}   
      AboutBox.Release;   
   
      {indicate   that   the   function   completed}   
   
      Result   :=   TRUE;   
end;   
   
Loading   The   Example   Dynamic   Link   Library   
   
procedure   TForm1.Button1Click(Sender:   TObject);   
var   
      hMod:   THandle;                                                   //   holds   the   DLL   handle   
      ModuleFileName:   array   of   char;   //   holds   the   DLL   name   
   
      {this   is   the   prototype   for   the   function   imported   from   the   DLL}   
      MyFunction:   function(ExampleName,   Comments:   ShortString):   Boolean;   
   
begin   
      {explicitly   load   the   DLL}   
      hMod   :=   LoadLibrary('EXAMPLE.DLL');   
      if   (hMod=0)   then   Exit;   
   
      {retrieve   the   address   of   the   desired   function}   
      @MyFunction   :=   GetProcAddress(hMod,   'ShowAboutBox'   );   
   
      {if   the   address   was   returned...}   
      if   (@MyFunction<>nil)   then   
      begin   
            {call   the   function   to   display   an   about   box}   
            MyFunction('LoadLibrary   Example','This   example   demonstrates   loading   '+   
   
                                  'a   dynamic   link   library   via   the   LoadLibrary   function.');   
   
            {retrieve   the   module   filename}   
            GetModuleFileName(GetModuleHandle('EXAMPLE.DLL'),   @ModuleFileName,   
                                                SizeOf(ModuleFileName));   
   
            {display   the   DLLs   name}   
            ShowMessage('The   loaded   DLL   was:   '+ModuleFileName);   
      end   
      else   
            {indicate   an   error}   
            ShowMessage('GetProcAddress   Failed');   
   
   
      {free   the   DLL}   
      FreeLibrary(hMod);   
end;

pusofalse 发表于 2009-5-6 14:45:10

#include <WinAPI.au3>

$hModule = _WinAPI_GetModuleHandle("user32.dll")
$sFileName = _GetModuleFileName($hModule)
MsgBox(0, $hModule, $sFileName)

Func _GetModuleFileName($hModule)
        Local $sFileName

        $sFileName = DllCall("Kernel32.dll", "int", "GetModuleFileName", _
                        "hWnd", $hModule, "str", "", "int", 260)
        Return $sFileName
EndFunc        ;==>_GetModuleFileName()

itljl 发表于 2009-5-8 17:19:40

谢谢楼上的朋友啊!!!你是大好人.我现在来测试一下

itljl 发表于 2009-5-8 17:23:46

这个函数我是用来检测一个程序的启动目录的.
但发现不行啊...我检测了一个EXE文件.显示模块错误.

pusofalse 发表于 2009-5-8 18:21:45

RE: 谁能将GetModuleFileName 开成AU3的?谢谢

4# itljl

你所需要的函数不是GetModuleFileName,而是GetModuleFileNameEx。#include <WinAPI.au3>

Func _QueryProcessExecutablePath($iProcessId)
        Local $hProcess, $iResult

        $iProcessId = ProcessExists($iProcessId)
        If not $iProcessId Then Return SetError(2, 0, "")
        $hProcess = _WinAPI_OpenProcess(0x400 + 0x10, 0, $iProcessId)
        $iResult = DllCall("psapi.dll", "int", "GetModuleFileNameEx", _
                        "hWnd", $hProcess, "hWnd", 0, "str", "", "int", 260)
        _WinAPI_CloseHandle($hProcess)
        Return SetError(Not $iResult, 0, $iResult)
EndFunc        ;==>_QueryProcessExecutablePath()

Msgbox(0, "", _QueryProcessExecutablePath("Notepad.exe"))

itljl 发表于 2009-5-21 18:50:01

谢谢楼上这位朋友这么热心的解答,你这个是获取进程的路径.

仍然不是我需要的,获取进程的启动目录.

在这里,进程的启动目录指的是.

比如程序a.exe在c:\ 而a.exe启动了 d:\b.exe
b.exe的启动目录就是c:\
而不是文件所有目录d:\b.exe

再次感谢.

pusofalse 发表于 2009-5-21 21:08:18

本帖最后由 pusofalse 于 2009-5-21 21:50 编辑

Re itljl:
这样也好办,只是一个获取父进程的过程,代码如下。#include <File.au3>
#include <File.au3>
#include <WinAPI.au3>

$tagProcessEntry =        "dword dwSize;dword cntUsage;" & _
                "dword th32ProcessID;ulong_ptr th32DefaultHeapID;" & _
                "dword th32ModuleID;dword cntThreads;" & _
                "dword th32ParentProcessID;long pcPriClassBase;" & _
                "dword dwFlags;char szExeFile"

Func _CreateToolhelp32Snapshot($iProcessId, $iFlag)
        Local $hSnap
        $iProcessId = ProcessExists($iProcessId)

        $hSnap = DllCall("kernel32.dll", "hWnd", "CreateToolhelp32Snapshot", _
                        "dword", $iFlag, "dword", $iProcessId)
        Return $hSnap
EndFunc        ;==>_CreateToolhelp32Snapshot()


Func _Process32First($hSnap)
        Local $tProcessEntry = DllStructCreate($tagProcessEntry)
        DllStructSetData($tProcessEntry, 1, DllStructGetSize($tProcessEntry))

        DllCall("kernel32.dll", "int", "Process32First", _
                        "hWnd", $hSnap, _
                        "ptr", DllStructGetPtr($tProcessEntry))
        Return $tProcessEntry
EndFunc        ;==>_Process32First()


Func _Process32Next(ByRef $hSnap, ByRef $tProcessEntry)
        Local $iResult
        $iResult = DllCall("kernel32.dll", "int", "Process32Next", _
                        "hWnd", $hSnap, _
                        "ptr", DllStructGetPtr($tProcessEntry))
        Return SetError(Not $iResult, 0, $iResult)
EndFunc        ;==>_Process32Next()



Func _EnumChildProcesses($iProcessId)
        Local $hSnap, $tProcessEntry, $aResult, $iProcess, $iParent

        $hSnap = _CreateToolhelp32Snapshot(0, 2)
        $tProcessEntry = _Process32First($hSnap)
        $iProcessId = ProcessExists($iProcessId)
        If not $iProcessId Then Return SetError(@error, 0, 0)
        While True
                _Process32Next($hSnap, $tProcessEntry)
                If @error Then ExitLoop
                $iProcess = DllStructGetData($tProcessEntry, "th32ProcessID")
                $iParent = DllStructGetData($tProcessEntry, "th32ParentProcessID")
                If $iParent = $iProcessId Then
                        $aResult = $iProcess
                        Redim $aResult
                EndIf
        WEnd
        $tProcessEntry = 0
        _WinAPI_CloseHandle($hSnap)
        If Ubound($aResult) = 1 Then Return SetError(2, 0, 0)
        Redim $aResult
        Return SetError(0, Ubound($aResult), $aResult)
EndFunc        ;==>_EnumChildProcesses()

Func _QueryParentProcess($iChildProcessId, $lparam = 0)
        Local $iResult, $tProcess, $pProcess, $hSnap
        Local $sResult, $sDrive, $sPath, $sName, $sExt

        $iChildProcessId = ProcessExists($iChildProcessId)
        If Not $iChildProcessId Then Return SetError(2, 0, 0)

        $hSnap = _CreateToolhelp32Snapshot(0, 2)
        $tProcess = _Process32First($hSnap)
        While True
                _Process32Next($hSnap, $tProcess)
                If @error Then ExitLoop
                $iProcessId = DllStructGetData($tProcess, "th32ProcessId")
                $iParentId = DllStructGetData($tProcess, "th32ParentProcessID")
                If $iProcessId = $iChildProcessId And $lparam = 0 Then
                        _WinAPI_CloseHandle($hSnap)
                        $sResult = _QueryParentProcess($iParentId, 1)
                        If $sResult Then Return $sResult
                        $sResult = _GetModuleFileNameEx($iProcessId)
                        _PathSplit($sResult, $sDrive, $sPath, $sName, $sExt)
                        Return $sDrive & $sPath
                ElseIf $lparam = 1 And $iProcessId = $iChildProcessId Then
                        _WinAPI_CloseHandle($hSnap)
                        $sResult = _GetModuleFileNameEx($iProcessId)
                        _PathSplit($sResult, $sDrive, $sPath, $sName, $sExt)
                        Return $sDrive & $sPath
                EndIf
        WEnd
EndFunc        ;==>_QueryParentProcess()


Func _GetModuleFileNameEx($iProcessId)
        Local $iResult, $hProcess

        $iProcessId = ProcessExists($iProcessId)
        If Not $iProcessId Then Return SetError(2, 0, "")
        $hProcess = _WinAPI_OpenProcess(0x400+0x10, 0, $iProcessId)

        $iResult = DllCall("psapi.dll", "int", "GetModuleFileNameEx", _
                        "hWnd", $hProcess, "hWnd", 0, "str", "", "int", 260)

        _WinAPI_CloseHandle($hProcess)
        Return SetError(Not $iResult, 0, $iResult)
EndFunc        ;==>_GetModuleFileNameEx()


Msgbox(0, _QueryParentProcess("qq.exe"), @error)

itljl 发表于 2009-5-21 21:32:05

感谢楼上这位朋友的热心.
我运行后提示_CloseHandle($hSnap)
函数没有.
于是我用_WinAPI_CloseHandle($hSnap)
代替.
但发现只有极少数能得到目录,iexplore.exe是可以的.
其它好多程序都不行的.如qq.exe

pusofalse 发表于 2009-5-21 21:52:27

Re itljl:
确实是很大的BUG,对于没有父进程的进程,会返回空值。
已经修改,若有父进程,则返回父进程的目录,否则返回此进程的所在目录。

itljl 发表于 2009-5-23 00:53:07

谢谢这位朋友,这问题,我都问得有点不好意思了。经过你的修改,问题确实已经解决。

我还想再问问,你是怎么学习写出这些API函数的。
我一般是通过GOOGLE。BAIDU相关的函数,还有就是MSDN。绝大部份资料都是在MSDN,全英文的。
相信你英文一定很好吧。
另外API还有地方和方法适合英文不好的我看懂吗?

sanhen 发表于 2009-5-23 01:07:53

其实需要获取进程目录的,用AU3调用API来实现,感觉确实够复杂的。简单点的用WMI,非常实用。当然有些进程是需要权限,还要用API提取权限。

itljl 发表于 2009-5-23 01:21:45

11# sanhen


有相关的WMI例子吗?谢谢.

sanhen 发表于 2009-5-23 01:24:28

以前我记得发过在论坛的,不知现在还有没有了。记得也有其他兄弟发过的。

pusofalse 发表于 2009-5-23 08:59:50

10# itljl
我也是在这3个地方学习的。说来惭愧,msdn中一半的单词看不懂,看不懂的函数再去csdn查下。越来越觉得英语的确重要,学习API函数,算上csdn,至少是中文的。没事常去这几个地方逛下,肯定大有收获。
页: [1]
查看完整版本: 谁能将GetModuleFileName 开成AU3的?谢谢