delphi 关于窗口句柄,进程等操作

转帖http://hi.baidu.com/ck85124/blog/item/d44ad17e9c1a163e0cd7da9e.html

uses TLHelp32,PsAPI;

(1)显示进程列表:
procedure TForm1.Button1Click(Sender: TObject);
var
ProcessName: string;
ProcessID: integer;
ListLoop: Boolean;
FsnapShotHandle: Thandle;
FProcessEntry32: TProcessEntry32;
begin
ListBox1.Clear;
Fsnapshothandle := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwsize := SizeOF(FProcessEntry32);
Listloop := Process32First(FSnapshotHandle, FProcessEntry32);
while Listloop do begin
    ProcessName := FprocessEntry32.szExeFile;
    ProcessID := FProcessEntry32.th32ProcessID;
// 我写到列表框中了,你可以根据需要自己改
    listbox1.Items.Add(ProcessNAme+':'+IntToStr(ProcessID));
    ListLoop := Process32Next(FSnapshotHandle, FprocessEntry32);
end;

end;

(2)杀死某进程:
procedure TForm1.Button2Click(Sender: TObject);
var
   lppe: TProcessEntry32;
   found : boolean;
   Hand : THandle;
   P:DWORD;
   ph: THandle;
   ExitCode: DWORD;
   sExeFile,sSelect:string;
   killed:boolean;
begin
temp:= ListBox1.Items.strings[ListBox1.itemindex];
temp:=copy(temp,pos(':',temp)+1,length(temp));
p :=DWORD(StrToInt(temp));
if P<>0 then
begin
    ph:=OpenProcess(PROCESS_TERMINATE,False,P);
    GetExitCodeProcess(ph, ExitCode);
    killed := TerminateProcess(ph,ExitCode);
    if not killed then
      messagebox(self.handle,pchar(sExeFile+'无法杀死!'),'提示',MB_OK or MB_ICONWARNING)
    else
      ListBox1.Items.Delete(ListBox1.ItemIndex);
end;

end;


(3)取得某进程EXE路径:
procedure TForm1.Button3Click(Sender: TObject);
var
h:THandle; fileName:string;
iLen:integer;
hMod:HMODULE;
cbNeeded,p:DWORD;
begin
temp:= ListBox1.Items.strings[ListBox1.itemindex];
temp:=copy(temp,pos(':',temp)+1,length(temp));
p :=DWORD(StrToInt(temp));
h := OpenProcess(PROCESS_ALL_ACCESS, false, p);      //p 为 进程ID
if h > 0 then
begin
    if EnumProcessModules( h, @hMod, sizeof(hMod), cbNeeded) then
    begin
      SetLength(fileName, MAX_PATH);
      iLen := GetModuleFileNameEx(h, hMod, PCHAR(fileName), MAX_PATH);
      if iLen <> 0 then
      begin
        SetLength(fileName, StrLen(PCHAR(fileName)));
        Memo1.Lines.Add(fileName);
      end;
    end;
    CloseHandle(h);
end;

end;


(4)取得窗口列表:
procedure TForm1.Button4Click(Sender: TObject);
var
hCurrentWindow: HWnd;
szText: array[0..254] of char;
begin
Listbox1.Clear;
//EnumWindows(@EnumWindowsProc, 0); 写了个回调 EnumWindowsProc没效果
hCurrentWindow := GetWindow(Handle, GW_HWNDFIRST);
while hCurrentWindow <> 0 do
begin
    if GetWindowText(hCurrentWindow, @szText, 255) > 0 then
      listbox1.items.Add(StrPas(@szText));
    hCurrentWindow := GetWindow(hCurrentWindow, GW_HWNDNEXT);
end;
end;

(5)杀死窗口进程:
procedure TForm1.Button5Click(Sender: TObject);
var
H:THandle;
P:DWORD;
s:string;
killed:boolean;
begin
s := ListBox1.Items[ListBox1.ItemIndex];
H:=FindWindow(nil,pchar(s));
if H<>0 then
begin
   GetWindowThreadProcessId(H,@P);
   if P<>0 then
     killed:=TerminateProcess(OpenProcess(PROCESS_TERMINATE,False,P),$FFFFFFFF);
   if not killed then
     messagebox(self.handle,pchar(s+'无法杀死!'),'提示',MB_OK or MB_ICONWARNING)
   else
     ListBox1.Items.Delete(ListBox1.ItemIndex);
end;

end;


(6)取得窗口进程路径:
procedure TForm1.Button6Click(Sender: TObject);
var
H:THandle;
P,cbNeeded:DWORD;
s,fileName:string;
iLen:integer;
hMod:HMODULE;
begin
s := ListBox1.Items[ListBox1.ItemIndex];
H:=FindWindow(nil,pchar(s));

if H<>0 then
begin
   GetWindowThreadProcessId(H,@P);
   if P<>0 then
   begin
     h := OpenProcess(PROCESS_ALL_ACCESS, false, p);      //p 为 进程ID
     if h > 0 then
     begin
       if EnumProcessModules( h, @hMod, sizeof(hMod), cbNeeded) then
       begin
       SetLength(fileName, MAX_PATH);
       iLen := GetModuleFileNameEx(h, hMod, PCHAR(fileName), MAX_PATH);
       if iLen <> 0 then
       begin
             SetLength(fileName, StrLen(PCHAR(fileName)));
       end;
       end;
       CloseHandle(h);
     end;
   end;
end;
Memo1.Lines.Add(fileName);

end;


(7)文件属性:
function   CovFileDate(Fd:_FileTime):TDateTime;  
{   转换文件的时间格式   }  
var  
Tct:_SystemTime;  
Temp:_FileTime;  
begin  
FileTimeToLocalFileTime(Fd,Temp);  
FileTimeToSystemTime(Temp,Tct);  
CovFileDate:=SystemTimeToDateTime(Tct);  
end;


procedure TForm1.Button7Click(Sender: TObject);
var
SR: TSearchRec;
V1, V2, V3, V4: integer ;
const
dtFmt:string = 'YYYY-MM-DD HH:NN:SS';
begin
// ============== 方法一 ==================== //
if FindFirst(edit1.Text, faAnyFile, SR) = 0 then
begin
    Memo1.Lines.Add('文件属性:' + intToStr(SR.Attr) );    //文件属性
    Memo1.Lines.Add('文件大小:' + intToStr(SR.Size) );    //文件大小
    Memo1.Lines.Add('创建时间:' + FormatDateTime(dtFmt,CovFileDate(SR.FindData.ftCreationTime)) );    //创建时间
    Memo1.Lines.Add('最后修改时间:' + FormatDateTime(dtFmt,CovFileDate(SR.FindData.ftLastWriteTime)) ); //最后修改时间
    Memo1.Lines.Add('最后访问时间:' + FormatDateTime(dtFmt,CovFileDate(SR.FindData.ftLastAccessTime)) ); //最后访问时间

    if SR.Attr and faHidden <> 0 then
      FileSetAttr(edit1.Text, SR.Attr-faHidden);
    FindClose(SR);
end;
end;

procedure TForm1.Button8Click(Sender: TObject);
// ============== 方法二 ==================== //
var
Attrs: Word;
f: file of Byte;    // 文件大小 必须要 定义为" file of byte" ,这样才能取出 bytes
size: Longint;
//文件属性
begin
//此方法是打开文件读取字节计算,测试exe的文件必须是未运行状态 否则会报io 103错误
Attrs:=FileGetAttr(edit1.text);
Memo1.Lines.Add('文件属性:' + intToStr(Attrs));

//文件大小
try
   AssignFile(f, edit1.text);
   Reset(f);
   size := FileSize(f);
   Memo1.Lines.Add('文件大小:' + intToStr(size));
finally
   CloseFile(f);
end;

end;


(8)判断程序是否在运行:
procedure TForm1.Button9Click(Sender: TObject);
var
PrevInstHandle:Thandle;
AppTitle:pchar;
begin
AppTitle := pchar(edit2.Text);
PrevInstHandle := FindWindow(nil, AppTitle);
   if PrevInstHandle <> 0 then begin
     if IsIconic(PrevInstHandle) then
      ShowWindow(PrevInstHandle, SW_RESTORE)
     else
      BringWindowToTop(PrevInstHandle);
     SetForegroundWindow(PrevInstHandle);
   end;

end;

{
CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。

HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);

参数:
dwFlags
[输入]指定快照中包含的系统内容,这个参数能够使用下列数值(变量)中的一个。

     TH32CS_INHERIT - 声明快照句柄是可继承的。
     TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。
     TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。
     TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。
     TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。
     TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。

th32ProcessID
[输入]指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或TH32CS_SNAPMOUDLE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照
}

{
//声明:

返回进程的句柄
OpenProcess(
dwDesiredAccess: DWORD; 访问选项
bInheritHandle: BOOL;    能否继承; True 表示能用 CreateProcess 继承句柄创建新进程
dwProcessId: DWORD       指定进程 ID
): THandle;                成功会返回进程句柄; 失败返回 0

//dwDesiredAccess 可选值:
PROCESS_TERMINATE         = $0001; 允许 TerminateProcess 使用进程句柄来关闭进程
PROCESS_CREATE_THREAD     = $0002; 允许 CreateRemoteThread 使用进程句柄来创建线程
PROCESS_VM_OPERATION      = $0008; 允许 VirtualProtectEx 使用进程句柄来改变进程的虚拟内存
PROCESS_VM_READ           = $0010; 允许 ReadProcessMemory 使用进程句柄从进程的虚拟内存中读取数据
PROCESS_VM_WRITE          = $0020; 允许 WriteProcessMemory 使用进程句柄向进程的虚拟内存中写入数据
PROCESS_DUP_HANDLE        = $0040; 允许 DuplicateHandle 把进程句柄当作源句柄或目标句柄进行复制
PROCESS_CREATE_PROCESS    = $0080; 默认值
PROCESS_SET_QUOTA         = $0100; 允许 SetProcessWorkingSetSize 使用进程句柄来来设置虚拟内存的上限值
PROCESS_SET_INFORMATION   = $0200; 允许 SetPriorityClass 使用进程句柄来设置进程优先级
PROCESS_QUERY_INFORMATION = $0400; 允许 GetExitCodeProcess 或 GetPriorityClass 通过进程句柄读取进程信息
SYNCHRONIZE               = $00100000; 允许任何等待的函数使用进程句柄
PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $FFF); 允许所有权限
--------------------------------------------------------------------------------

获取指定进程的退出码
GetExitCodeProcess(
hProcess: THandle;    进程句柄
var lpExitCode: DWORD 接收退出码
): BOOL;
--------------------------------------------------------------------------------

强制结束(其他)进程
TerminateProcess(
hProcess: THandle; 进程句柄
uExitCode: UINT    退出码
): BOOL;

//提示: 关闭其他程序一般应该是向其主窗口发送 WM_CLOSE 消息, 不行再用这个, 因为它不能关闭其关联的 DLL.


}

{
GetWindow
函数功能:该函数返回与指定窗口有特定关系(如Z序或所有者)的窗口句柄。
函数原型:HWND GetWindow(HWND hWnd,UNIT nCmd);
参数:
hWnd:窗口句柄。要获得的窗口句柄是依据nCmd参数值相对于这个窗口的句柄。
nCmd:说明指定窗口与要获得句柄的窗口之间的关系。该参数值可以是下列之一:
GW_CHILD:如果指定窗口是父窗口,则获得的是在Z序顶端的子窗口的句柄,否则为NULL。函数仅检查指定父窗口的子窗口,不检查继承窗口。
GW_ENABLEDPOUP:(WindowsNT 5.0)返回的句柄标识了属于指定窗口的处于使能状态弹出式窗口(检索使用第一个由GW_HWNDNEXT 查找到的满足前述条件的窗口);如果无使能窗口,则获得的句柄与指定窗口相同。
GW_HWNDFIRST:返回的句柄标识了在Z序最高端的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在Z序最高端的最高端窗口;如果指定窗口是顶层窗口,则该句柄标识了在z序最高端的顶层窗口:如果指定窗口是子窗口,则句柄标识了在Z序最高端的同属窗口。
GW_HWNDLAST:返回的句柄标识了在z序最低端的相同类型的窗口。如果指定窗口是最高端窗口,则该柄标识了在z序最低端的最高端窗口:如果指定窗口是顶层窗口,则该句柄标识了在z序最低端的顶层窗口;如果指定窗口是子窗口,则句柄标识了在Z序最低端的同属窗口。
GW_HWNDNEXT:返回的句柄标识了在Z序中指定窗口下的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在指定窗口下的最高端窗口:如果指定窗口是顶层窗口,则该句柄标识了在指定窗口下的顶层窗口;如果指定窗口是子窗口,则句柄标识了在指定窗口下的同属窗口。
GW HWNDPREV:返回的句柄标识了在Z序中指定窗口上的相同类型的窗口。如果指定窗口是最高端窗口,则该句柄标识了在指定窗口上的最高端窗口;如果指定窗口是顶层窗口,则该句柄标识了在指定窗口上的顶层窗口;如果指定窗口是子窗口,则句柄标识了在指定窗口上的同属窗口。
GW_OWNER:返回的句柄标识了指定窗口的所有者窗口(如果存在)。
返回值:如果函数成功,返回值为窗口句柄;如果与指定窗口有特定关系的窗口不存在,则返回值为NULL。
若想获得更多错误信息,请调用GetLastError函数。
备注:在循环体中调用函数EnumChildWindow比调用GetWindow函数可靠。调用GetWindow函数实现该任务的应用程序可能会陷入死循环或退回一个已被销毁的窗口句柄。
速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:1.0以上版本;头文件:winuser.h;库文件:user32.lib。
}

{
函数功能:该函数将指定的窗口设置到Z序的顶部。如果窗口为顶层窗口,则该窗口被激活;如果窗口为子窗口,则相应的顶级父窗口被激活。

    函数原型:B00L BringWindowToTop(HWND,hWnd);

    参数:

    hWnd: 设置到Z序的顶部的窗口句柄。

    返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

    备注:使用BringWindowToTop函数显示出被其他窗口部分或全部遮盖的窗口。

    调用这个函数类似于调用SetWindowPos函数来改变窗口在Z序中的位置,但是BringWindowToTop函数并不能使一个窗口成为顶层窗口。

    如果应用程序不在前台中而想设置在前台中,可以调用SetForegroundWindow函数。

}


program Project1; //{$APPTYPE CONSOLE} uses windows, SysUtils, tlhelp32, accctrl, aclapi; procedure SetPrivilege; var OldTokenPrivileges, TokenPrivileges: TTokenPrivileges; ReturnLength: dword; hToken: THandle; Luid: int64; begin OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken); LookupPrivilegeValue(nil, 'SeDebugPrivilege', Luid); TokenPrivileges.Privileges[0].luid := Luid; TokenPrivileges.PrivilegeCount := 1; TokenPrivileges.Privileges[0].Attributes := 0; AdjustTokenPrivileges(hToken, False, TokenPrivileges, SizeOf(TTokenPrivileges), OldTokenPrivileges, ReturnLength); OldTokenPrivileges.Privileges[0].luid := Luid; OldTokenPrivileges.PrivilegeCount := 1; OldTokenPrivileges.Privileges[0].Attributes := TokenPrivileges.Privileges[0].Attributes or SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, False, OldTokenPrivileges, ReturnLength, PTokenPrivileges(nil)^, ReturnLength); end; function GetProcessID(EXE_Name: PChar): THandle; var s: string; ok: Bool; ProcessListHandle: THandle; ProcessStruct: TProcessEntry32; begin Result := 0; //获得进程列表句柄 ProcessListHandle := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); try ProcessStruct.dwSize := SizeOf(ProcessStruct); //获得第一个进程句柄 ok := Process32First(ProcessListHandle, ProcessStruct); while ok do begin s := ExtractFileName(ProcessStruct.szExeFile);//获取进程的可执行文件名称 if AnsiCompareText(Trim(s), EXE_Name)=0 then//如果是HL程序名,表示找到游戏进程。 begin Result := ProcessStruct.th32ProcessID;//保留游戏进程句柄 break; end; ok := Process32Next(ProcessListHandle, ProcessStruct);//获取下一个进程信息。 end; finally CloseHandle(ProcessListHandle);//关闭进程列表句柄 end; end; ///////////////////////////////////////////////////////////////// Function CreateSystemProcess(szProcessName: LPTSTR): BOOL; Var hProcess: THANDLE; hToken, hNewToken: THANDLE; dwPid: DWORD; pOldDAcl: PACL; pNewDAcl: PACL; bDAcl: BOOL; bDefDAcl: BOOL; dwRet: DWORD; pSacl: PACL; pSidOwner: PSID; pSidPrimary: PSID; dwAclSize: DWORD; dwSaclSize: DWORD; dwSidOwnLen: DWORD; dwSidPrimLen: DWORD; dwSDLen: DWORD; ea: EXPLICIT_ACCESS; pOrigSd: PSECURITY_DESCRIPTOR; pNewSd: PSECURITY_DESCRIPTOR; si: STARTUPINFO; pi: PROCESS_INFORMATION; bError: BOOL; Label Cleanup; begin pOldDAcl:= nil; pNewDAcl:= nil; pSacl:= nil; pSidOwner:= nil; pSidPrimary:= nil; dwAclSize:= 0; dwSaclSize:= 0; dwSidOwnLen:= 0; dwSidPrimLen:= 0; pOrigSd:= nil; pNewSd:= nil; SetPrivilege; // 选择 WINLOGON 进程 dwPid := GetProcessId('WINLOGON.EXE'); If dwPid = High(Cardinal) Then begin bError := TRUE; Goto Cleanup; end; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,dwPid); If hProcess = 0 Then begin bError := TRUE; Goto Cleanup; end; If not OpenProcessToken(hProcess,READ_CONTROL or WRITE_DAC,hToken) Then begin bError := TRUE; Goto Cleanup; end; // 设置 ACE 具有所有访问权限 ZeroMemory(@ea, Sizeof(EXPLICIT_ACCESS)); BuildExplicitAccessWithName(@ea, 'Everyone', TOKEN_ALL_ACCESS, GRANT_ACCESS, 0); If not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, 0, dwSDLen) Then begin {第一次调用给出的参数肯定返回这个错误,这样做的目的是 为了得到原安全描述符 pOrigSd 的长度} // HEAP_ZERO_MEMORY = 8;HEAP_GENERATE_EXCEPTIONS = &H4 If GetLastError = ERROR_INSUFFICIENT_BUFFER Then begin pOrigSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen); If pOrigSd = nil Then begin bError := TRUE; Goto Cleanup; end; // 再次调用才正确得到安全描述符 pOrigSd If not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, dwSDLen, dwSDLen) Then begin bError := TRUE; Goto Cleanup; end; end Else begin bError := TRUE; Goto Cleanup; end; end;//GetKernelObjectSecurity() // 得到原安全描述符的访问控制列表 ACL If not GetSecurityDescriptorDacl(pOrigSd,bDAcl,pOldDAcl,bDefDAcl) Then begin bError := TRUE; goto Cleanup; end; // 生成新 ACE 权限的访问控制列表 ACL dwRet := SetEntriesInAcl(1,@ea,pOldDAcl,pNewDAcl); If dwRet ERROR_SUCCESS Then begin pNewDAcl := nil; bError := TRUE; goto Cleanup; end; If not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) Then begin {第一次调用给出的参数肯定返回这个错误,这样做的目的是 为了创建新的安全描述符 pNewSd 而得到各项的长度} If GetLastError = ERROR_INSUFFICIENT_BUFFER Then begin pOldDAcl := HeapAlloc(GetProcessHeap(), $00000008, dwAclSize); pSacl := HeapAlloc(GetProcessHeap(), $00000008, dwSaclSize); pSidOwner := HeapAlloc(GetProcessHeap(), $00000008, dwSidOwnLen); pSidPrimary := HeapAlloc(GetProcessHeap(), $00000008, dwSidPrimLen); pNewSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen); If (pOldDAcl = nil) or (pSacl = nil) or (pSidOwner = nil) or (pSidPrimary = nil) or (pNewSd = nil) Then begin bError := TRUE; goto Cleanup; end; {再次调用才可以成功创建新的安全描述符 pNewSd 但新的安全描述符仍然是原访问控制列表 ACL} If not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) Then begin bError := TRUE; goto Cleanup; end; end Else begin bError := TRUE; goto Cleanup; end; end; {将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的 安全描述符 pNewSd 中} If not SetSecurityDescriptorDacl(pNewSd,bDAcl,pNewDAcl,bDefDAcl) Then begin bError := TRUE; goto Cleanup; end; // 将新的安全描述符加到 TOKEN 中 If not SetKernelObjectSecurity(hToken,DACL_SECURITY_INFORMATION,pNewSd) Then begin bError := TRUE; goto Cleanup; end; // 再次打开 WINLOGON 进程的 TOKEN,这时已经具有所有访问权限 If not OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,hToken) Then begin bError := TRUE; goto Cleanup; end; // 复制一份具有相同访问权限的 TOKEN If not DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nil, SecurityImpersonation, TokenPrimary, hNewToken) Then begin bError := TRUE; goto Cleanup; end; ZeroMemory(@si,Sizeof(STARTUPINFO)); si.cb := Sizeof(STARTUPINFO); {不虚拟登陆用户的话,创建新进程会提示 1314 客户没有所需的特权错误} ImpersonateLoggedOnUser(hNewToken); {我们仅仅是需要建立高权限进程,不用切换用户 所以也无需设置相关桌面,有了新 TOKEN 足够} // 利用具有所有权限的 TOKEN,创建高权限进程 If not CreateProcessAsUser(hNewToken, nil, szProcessName, nil, nil, FALSE, 0, nil, nil, si, pi) Then begin bError := TRUE; goto Cleanup; end; bError := FALSE; Cleanup: If pOrigSd = nil Then HeapFree(GetProcessHeap(),0,pOrigSd); If pNewSd = nil Then HeapFree(GetProcessHeap(),0,pNewSd); If pSidPrimary = nil Then HeapFree(GetProcessHeap(),0,pSidPrimary); If pSidOwner = nil Then HeapFree(GetProcessHeap(),0,pSidOwner); If pSacl = nil Then HeapFree(GetProcessHeap(),0,pSacl); If pOldDAcl = nil Then HeapFree(GetProcessHeap(),0,pOldDAcl); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hToken); CloseHandle(hNewToken); //CloseHandle(hProcess); If bError Then Result := FALSE Else Result := True; end; begin CreateSystemProcess('test.exe'); { TODO -oUser -cConsole Main : Insert code here } end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值