怎样实现调用DLL的程序退出后,DLL能继续执行(200分)

  • 主题发起人 主题发起人 Sunny18
  • 开始时间 开始时间
S

Sunny18

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一个程序用loadlibrary调用的一个DLL,我想在我的程序退出后,我所调用的DLL还能<br>在内存中继续执行。请高手帮忙!<br>又:如果我下次执行我的程序时,怎么得到我上次loadlibrary进来的dll的handle!<br>谢谢!
 
不可能吧?
 
rundll32.exe 可以装入一个dll, 并运行其中的函数,<br><br>dll 装入后有一个计数器,记录Dll被加载的次数,次数 =0 时装入 dll 次数 +1,<br>次数 &gt;0 时 LoadLibary 自动取dll的句柄,同时次数 +1(不再重复装入)<br>相反释放时 次数 -1 ,到 次数=0 时才真正释放 dll 占用的资源...
 
我的意思是我在一个程序时Loadlibrary后,不Free就退出我的程序,能不能保持该DLL在内<br>存中继续运行,下次我再进入这个程序时可以用某种办法取得它的Handle然后必要时把它<br>free掉(从内存里卸掉)!<br>也就是把DLL做成一个service,然后通过一个程序来管理!<br>可现在的情况是我一退出我的程序,load进来的dll也随着就被卸掉了!<br>请各位大侠帮忙!!!!!!!<br>
 
试试看Hook系统进程……???
 
记得在delphiboy, codelphi, cooldelphi,要么是csdn上,看见过如下解决方案:<br>运行YourApp.exe, YourApp调用 One.DLL, 然后用 One.DLL 调用 Two.DLL, 让Two.DLL<br>作为explore的服务存在,就满足你的要求了。<br>具体实现要看以前的笔记了 :(
 
不能用动态调用,而采用静态调用才能解决问题!
 
给你这个参考一下<br><br>//在指定的进程中插入一个DLL文件<br>function AttachToProcess(const HostFile, GuestFile : string;const PID:DWORD=0):DWORD;<br>//HostFile为要绑定的宿主文件(Exe文件),GuestFile为要嵌入的客户文件(Dll文件)<br>//如AttachToProcess('D:/TESTDLL.DLL','Notepad.exe') ;<br>var<br>&nbsp; hRemoteProcess: THandle;<br>&nbsp; dwRemoteProcessId:DWORD;<br>&nbsp; cb:DWORD;<br>&nbsp; pszLibFileRemote: Pointer;<br>&nbsp; iReturnCode:Boolean;<br>&nbsp; TempVar:DWORD;<br>&nbsp; pfnStartAddr:TFNThreadStartRoutine;<br>&nbsp; pszLibAFilename: PwideChar;<br>begin<br>&nbsp; Result:=0;<br>&nbsp; EnabledDebugPrivilege(True);<br>&nbsp; Getmem(pszLibAFilename,Length(GuestFile)*2+1);<br>&nbsp; StringToWideChar(GuestFile,pszLibAFilename,Length(GuestFile)*2+1);<br>&nbsp; if PID&gt;0 then dwRemoteProcessID:=PID else FindAProcess(HostFile,False,dwRemoteProcessID);<br>&nbsp; //由于我们后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请<br>&nbsp; //足够的权限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。<br>&nbsp; //然后,我们可以建立LoadLibraryW函数这个线程来启动我们的DLL,LoadLibraryW<br>&nbsp; //函数是在kernel32.dll中定义的,用来加载DLL文件,它只有一个参数,就是DLL<br>&nbsp; //文件的绝对路径名pszLibAFilename,(也就是DLL的全路径文件名),但是由于<br>&nbsp; //DLL是在远程进程内调用的,所以我们首先还需要将这个文件名复制到远程地址空<br>&nbsp; //间:(否则远程线程是无法读到这个参数的)<br>&nbsp; hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + //允许远程创建线程<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PROCESS_VM_OPERATION+ //允许远程VM操作<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PROCESS_VM_WRITE,//允许远程VM写<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FALSE, dwRemoteProcessId);<br><br>&nbsp; //计算DLL路径名需要的内存空间<br>&nbsp; cb := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);<br>&nbsp; //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区<br>&nbsp; pszLibFileRemote := PWIDESTRING( VirtualAllocEx( hRemoteProcess, nil, cb, MEM_COMMIT, PAGE_READWRITE));<br>&nbsp; //使用WriteProcessMemory函数将DLL的路径名复制到远程进程的内存空间<br>&nbsp; TempVar:=0;<br>&nbsp; iReturnCode := WriteProcessMemory(hRemoteProcess,pszLibFileRemote, pszLibAFilename, cb, TempVar);<br>&nbsp; if iReturnCode then<br>&nbsp; begin<br>&nbsp; &nbsp; //计算LoadLibraryW的入口地址<br>&nbsp; &nbsp; pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');<br>&nbsp; &nbsp; //OK,万事俱备,我们通过建立远程线程时的地址pfnStartAddr(实际上就是LoadLibraryW<br>&nbsp; &nbsp; //的入口地址)和传递的参数 &nbsp;pszLibFileRemote(实际上是我们复制过去的DLL的全路<br>&nbsp; &nbsp; //径文件名)在远程进程内启动我们的DLL:<br>&nbsp; &nbsp; //启动远程线程LoadLibraryW,通过远程线程调用用户的DLL文件<br>&nbsp; &nbsp; TempVar:=0;<br>&nbsp; &nbsp; Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);<br>&nbsp; end;<br>&nbsp; Freemem(pszLibAFilename);<br>end;<br><br>//查找指定的进程,然后返回进程ID<br>procedure FindAProcess(const AFilename:string; const PathMatch:Boolean; var ProcessID: DWORD);<br>//AFilename为要查找(进程ID)的文件名(可以包行路径)<br>//PathMatch为查找的时候是否匹配路径<br>var<br>&nbsp; lppe:TProcessEntry32;<br>&nbsp; SsHandle:Thandle;<br>&nbsp; FoundAProc, FoundOK:boolean;<br>begin<br>&nbsp; SsHandle &nbsp; := CreateToolHelp32SnapShot(TH32CS_SNAPALL,0);<br>&nbsp; FoundAProc := Process32First(Sshandle,lppe);<br>&nbsp; while FoundAProc do<br>&nbsp; begin<br>&nbsp; &nbsp; if PathMatch then<br>&nbsp; &nbsp; &nbsp; &nbsp;FoundOK:=AnsiStricomp(lppe.szExefile,PChar(AFilename))=0<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp;FoundOK:=AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)),PChar(ExtractFilename(AFilename)))=0;<br><br>&nbsp; &nbsp; if FoundOK then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ProcessID:=lppe.th32ProcessID;<br>&nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FoundAProc :=Process32Next(SsHandle,lppe);<br>&nbsp; end;<br>// &nbsp;if not FoundAProc then showmessage(SysErrorMessage(GetLastError));<br>&nbsp; CloseHandle(SsHandle);<br>end;<br><br>//激活或者停止指定的权限 [ Winnt Win2000 ]<br>function EnabledDebugPrivilege(const bEnabled: Boolean):Boolean;<br>var<br>&nbsp; hToken: THandle;<br>&nbsp; tp: TOKEN_PRIVILEGES;<br>&nbsp; a: DWORD;<br>const<br>&nbsp; SE_DEBUG_NAME = 'SeDebugPrivilege';<br>begin<br>&nbsp; Result:=False;<br>&nbsp; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken)) then<br>&nbsp; begin<br>&nbsp; &nbsp; tp.PrivilegeCount :=1;<br>&nbsp; &nbsp; LookupPrivilegeValue(nil,SE_DEBUG_NAME ,tp.Privileges[0].Luid);<br>&nbsp; &nbsp; if bEnabled then<br>&nbsp; &nbsp; &nbsp; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; tp.Privileges[0].Attributes := 0;<br>&nbsp; &nbsp; a:=0;<br>&nbsp; &nbsp; AdjustTokenPrivileges(hToken,False,tp,SizeOf(tp),nil,a);<br>&nbsp; &nbsp; Result:= GetLastError = ERROR_SUCCESS;<br>&nbsp; &nbsp; CloseHandle(hToken);<br>&nbsp; end;<br>end;<br><br><br>
 
谢谢各位的关注,不过还有几个疑问:<br>1.CreateRemoteThread只有在NT下才能用,在95/98下有没有什么替代方法?<br>2。用CreateRemoteThread所建产的RemoteThread是不是在loadlibraryw后就终止了?<br>&nbsp; &nbsp;那我以后怎样才能得到load进来的dll的Handle呢?(想在必要时free掉它和调<br>&nbsp; &nbsp;用它里面的函数)。<br>3.我该怎样调用在RemoteThread里load的dll中的函数呢?<br>&nbsp; 谢谢!最好能有代码示例。
 
dll需要一个进程,你的程序退出,进程也就结束,dll也就结束
 
不用那么复杂吧?<br><br>应用程序loadLibrary以后不free?真是会想!!!<br><br>你可以建立一个第三方Service程序来保存dll句柄的吗,应用程序建立以后先查询它不就完了。
 
在DLL资源中放一个EXE,DLL初始化的时候,把这个EXE释放到一个临时文件中,运行他<br>//EXE调用这个DLL
 
把exe文件放到资源里面干吗?<br>dll自己调用CreateProcess ShellExecute之类的函数创建一个进程不是轻而易举的吗?<br>放到initialization part
 
谢谢各位的帮肋!<br>这么久了也该结束了!<br>多谢多谢!
 
后退
顶部