昨天发了个贴,竟然没分重发过!!!!!!
RT,我们可以通过一系列的API获取进程的路径,但是如果是像记事本,WORD文档,EXECL文档,WINDOWS图片浏览器等程序,我们得到的只是系统目录下的程序 
如:NODEPAD。EXE ,返回来的结果是 c:\windows\notepad.exe,那有没有一种办法可以得知这个记事本到底是哪个目录下的哪个文件? 
比如我打开的是e:\a.txt,通过枚举得来的却是 c:\windows\notepad.exe  这个路径,能不能得到 e:\a.txt这个路径? function  GetPathFileofModule(ModuleName:String):String;  
var  hProcSnap:  THandle;  
      pProcess:  THandle;  
      pe32:  TProcessEntry32;  
      s:  string;  
      buf:array[0..MAX_PATH]  of  char;  
      hMod:HMODULE;  
      cbNeeded:DWORD;  
begin  
  hProcSnap:=CreateToolHelp32SnapShot(TH32CS_SNAPALL,  0);  
  if  hProcSnap=INVALID_HANDLE_VALUE  then  Exit;  
  pe32.dwSize:=SizeOf(ProcessEntry32);  
  if  Process32First(hProcSnap,pe32)=True then  
      while  Process32Next(hProcSnap,pe32)=True  do  
      begin  
          if  uppercase(pe32.szExeFile)=uppercase(ModuleName)  then  
          begin  
            pProcess:=OpenProcess(PROCESS_QUERY_INFORMATION  or  PROCESS_VM_READ,FALSE, pe32.th32ProcessID);                                                      
            if  pProcess <>0  then  
            begin  
                if  EnumProcessModules(  pProcess,@hMod,sizeof(hMod),cbNeeded)  then  
                begin  
                  ZeroMemory(@buf,MAX_PATH+1);  
                  GetModuleFileNameEx(pProcess,  hMod,buf,MAX_PATH+1);  
                  Result:=strpas(buf);  
                end;  
            end;  
          end;  
      end;  
      CloseHandle(hProcSnap);  
  end; 
这个函数返回的无法实现我的要求!!!

解决方案 »

  1.   


    给你一段参考代码,获得进程及模块的树形结构,放到TV控件中,可以显示文件名uses Tlhelp32; procedure ProcessEnum(TV:TTreeView);
    var
      ProcessList :Thandle;
      pe :TPROCESSENTRY32;
      node :TTreenode;
      processnumber :integer;
      procedure ModuleEnum(processid:Dword);
      var
        ModuleList :Thandle;
        pm :TMODULEENTRY32;
      begin
        ModuleList:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processID);
        pm.dwSize:=sizeof(TMODULEENTRY32);
        if module32first(ModuleList,pm) then
        begin
          TV.Items.addchild(node,pm.szexepath);
          while module32next(ModuleList,pm) do
            TV.items.addchild(node,pm.szexepath);
        end;
      CloseHandle(ModuleList);
      end; // ModuleEnumbegin // ProcessEnum
      processnumber:=0;
      TV.Items.Clear;
      ProcessList:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
      pe.dwSize:=sizeof(TPROCESSENTRY32);
      if process32first(ProcessList,pe) then
      begin
        node:=TV.Items.Add(nil,pe.szexefile);
        ModuleEnum(pe.th32ProcessID);
        inc(processnumber);
        while process32next(ProcessList,pe) do
        begin
          node:=TV.Items.Add(nil,pe.szexefile);
          ModuleEnum(pe.th32ProcessID);
          inc(processnumber);
        end;
      end;
    //edit1.text:=’系统进程:’+inttostr(processnumber);
      CloseHandle(ProcessList);
    end;
      

  2.   

    你的方法只能获取 宿主程序exe 所在的路径。
    对exe所加载的文件 所在路径 ,无法取得。从目前 系统提供的 进程信息,是无法知道 其加载的文件路径的。可以通过取得进程的 工作路径 ,来得知 其所加载的文件路径。
      

  3.   

    之所以考虑取得工作路径,以e:\a.txt为例子,当我们开启这个txt时,os会先去创建notepad.exe,同时会传入e:\ 路径和文件名,这样就可以正确加载文件了。猜测系统是调用createprocess,‘e:\ ’应该会被作为 工作路径参数传进去。详情,请参考createprocess的参数介绍。
      

  4.   

    楼主你的问题很模糊
    是要获取固定一个进程所打开的文件路径还是进程本身路径,如果是前者,只能HOOK openfile or createfile 等API来提取.
      

  5.   


    是前者....
    通过API HOOK 来实现,.应该可以,不过估计难底挺大,我还不知道如何让其它程序挂载自己的DLL进行API HOOK 呢.....
      

  6.   

    HOOK不存在即时性,也就是说打开之后,调用OpenProcess过程已经结束了,这个时侯再去HOOK为时已晚
      

  7.   

    是去 HOOK openfile ,createfile OpenProcess 这类的函数,不过个人认为没多大作用,在打开时取回文件路径和文件名,但如果之后用户关闭了该程序...又要怎么判断?HOOK到的路径能否和相应的进程名联系起来?
      

  8.   

    HOOK不存在即时性,也就是说打开之后,调用OpenProcess过程已经结束了,这个时侯再去HOOK为时已晚
      

  9.   

    时刻监视所有的文件访问。如果没有监视,一个txt文件被读取了,过后你再去查是谁读的,那是不可能的。
      

  10.   

    网络上搜索“进程参数”,或看看GetCommandLine的用法。
      

  11.   


    就是说就算用 API HOOK,也起不到作用?
      

  12.   

    对于记事本类的软件,有两种情况:
    1、通过双击 a.txt 打开,此时可以看到他的命令行 "C:\WINDOWS\notepad.exe" F:\a.txt,直接分析可得。
    2、对于通过记事本通过打开菜单打开的文件,其命令行是不可见的,此时有两个办法:
       2.1 有些软件有最近打开的文件类别,直接读取最近的一个。
       2.2 可以从最近打开的文档中获取最近的文件。以上办法对于多个进程,打开多次文件的操作 会有问题
      

  13.   

    你的要求其实是要求获得其他进程打开文件的路径,这种要求可以说是侵犯了其他进程的隐私,这里可以考虑采取DLL使用全局的API HOOK去截获Createfile, Openfile、CloseFile等此类API来获得打开或被关闭的文件诸如此类的信息,而针对Open "a.txt" 这类处理,还需要获取系统环境路径,当前进程路径搜索来获得该文件的绝对路径。至于全局API HOOK,到处都是此类文章,不必赘述。
      

  14.   

    看看LongHorn版的任务管理器吧,里面就有这个功能。
      

  15.   

    看下撒!!!鼎易瞎!
       
       (__) 
      /oo\\________
      \ /     \---\
       \/    /  \  \
        \\_|___\\_|/  *
          ||  YY|  
          ||  ||   
      

  16.   


    function GetINIDir: string ;
    function GetDir(str: string): string ;
    var m, n: Integer ;
        tmp: string[1];
    begin
      m := Length(str);
      for n:=m downto 1 do
      begin
        tmp := Copy(str, n, n);
        if tmp = '\' then Break ;
      end;
      Result := Copy(str, 1, n);
    end;
    //--------------------------------
    var
      pid:integer;
      phd:thandle;
      handle: HWND;
      filename:array [0..1024] of char;
    begin
      handle := FindWindow('TxFmain', nil);  //目标程序的窗口标题.
      GetWindowThreadProcessId(handle,@pid); //这里,HANDLE为你的窗口句柄
      phd:=OpenProcess(PROCESS_ALL_ACCESS ,true,pid);
      GetModuleFileNameExA(phd, 0, filename, 1024);   //需要声明.
      Result := GetDir(filename);
      CloseHandle(phd);
    end;
      

  17.   

    我认为HOOK不存在即时性,说打开之后,OpenProcess过程已经结束,再去HOOK已经晚了
      

  18.   

    楼主要实现的功能暂时没有想到可以直接实现的办法,但是可以变通实现:模拟另存为菜单,然后取当前路径+当前默认保存的名字,就是你目前所用NOTEPAD打开的实际文件。因为模拟另存为需要弹出对话框有些不爽,但我可以栏截实现不显示隐藏调用。注意:文件另存为的时候默认的目标就是文件当前地址 
      

  19.   

    这个问题有多种情况:
    1最简单, 在c盘1.txt右键选择打开方式的时候选择用notepad打开.
    种情况,可以取得带参数的映象路径,该参数就是c:\1.txt.2 比较复杂,打开Notepad,在用notepad打开c:\1.txt.
    取得映象路径里面不带参数,只有notepad的路径.
    这种情况不知道怎么解决.3更复杂的情况,程序支持多页面浏览,比如word,notepad++等,一次可以打开n个文档,但进程只有一个.
    程序可能用了自己的数据结构保存了已经打开文件的列表,这种程序基本没法写出通用的解法取得路径.基本没法实现.上面有人说用hook,我觉得不如去实现一个filemon,检测任何文件变动.但这样也有缺点,
    就是被打开的文件不变就没法检测了.
      

  20.   

    没接口,直接获取加载文件的路径,是几乎不可能呢,因为这个信息没必要对外公布出来,保存在变量,除非你去手工分析内存了.不过,有另一个思路------分析标题栏大多程序都把加载文件的路径放标题栏或者application.title,这两个数据有句柄是可以得到的,但不一定每个程序都支持,而且分析程序只针对一个软件,但我想楼主最终目的可能只是想获取某一个软件的文件加载信息吧.
      

  21.   

    编写一个独立的DLL,然后注入目标进程,调用GetCommandLine()就能获取到目标参数
      

  22.   

    不知楼主使用过FileMonitor没有,这个工具软件可以查看到什么进程正在操作什么文件之类的。不过这个应该和文件驱动层有一定关系
      

  23.   

    没想到这么多人关注,,,
    大家都讨论都很多,个人认为API HOOK 无法达到要求,像各位所说的,即时性的东西,打开后就跟进程没任何关联了,再去找也找不到任何珠丝马迹...
      

  24.   

    在目标进程的内存空间里执行GetCommandLine即可.参考:http://www.vckbase.com/document/viewdoc/?id=1685很简单的代码,却是不错的思路.我改了一个VB版的,你自己改成DELPHI版吧.
      

  25.   

    哈,错了,是直接读GetCommandLine函数相关的内存......
      

  26.   

    FileMon.exe, 是一个出色系统文件监视工具,可以监视应用程序进行的文件读写操作