library ISTask; uses SysUtils, Classes, Windows, Tlhelp32, Psapi, FileCtrl; {$R *.RES} var SaveExit: Pointer; procedure LibExit; begin // library exit code ExitProc := SaveExit; // restore exit procedure chain end; procedure ExecConsoleApp(CommandLine: String; Output: TStringList; Errors: TStringList); stdcall; var sa: TSECURITYATTRIBUTES; si: TSTARTUPINFO; pi: TPROCESSINFORMATION; hPipeOutputRead: THANDLE; hPipeOutputWrite: THANDLE; hPipeErrorsRead: THANDLE; hPipeErrorsWrite: THANDLE; Res, bTest: Boolean; env: array[0..100] of Char; szBuffer: array[0..256] of Char; dwNumberOfBytesRead: DWORD; Stream: TMemoryStream; begin sa.nLength := sizeof(sa); sa.bInheritHandle := true; sa.lpSecurityDescriptor := nil; CreatePipe(hPipeOutputRead, hPipeOutputWrite, @sa, 0); CreatePipe(hPipeErrorsRead, hPipeErrorsWrite, @sa, 0); ZeroMemory(@env, SizeOf(env)); ZeroMemory(@si, SizeOf(si)); ZeroMemory(@pi, SizeOf(pi)); si.cb := SizeOf(si); si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; si.wShowWindow := SW_HIDE; si.hStdInput := 0; si.hStdOutput := hPipeOutputWrite; si.hStdError := hPipeErrorsWrite; (* Remember that if you want to execute an app with no parameters you nil the second parameter and use the first, you can also leave it as is with no problems. *) Res := CreateProcess(nil, pchar(CommandLine), nil, nil, true, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, nil, si, pi); // Procedure will exit if CreateProcess fail if not Res then begin CloseHandle(hPipeOutputRead); CloseHandle(hPipeOutputWrite); CloseHandle(hPipeErrorsRead); CloseHandle(hPipeErrorsWrite); Exit; end; CloseHandle(hPipeOutputWrite); CloseHandle(hPipeErrorsWrite); //Read output pipe Stream := TMemoryStream.Create; try while true do begin bTest := ReadFile(hPipeOutputRead, szBuffer, 256, dwNumberOfBytesRead, nil); if not bTest then begin break; end; Stream.Write(szBuffer, dwNumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; //Read error pipe Stream := TMemoryStream.Create; try while true do begin bTest := ReadFile(hPipeErrorsRead, szBuffer, 256, dwNumberOfBytesRead, nil); if not bTest then begin break; end; Stream.Write(szBuffer, dwNumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(hPipeOutputRead); CloseHandle(hPipeErrorsRead); end; function ExecConsoleAppX(str: PChar): PChar; stdcall; var OutP: TStringList; ErrorP: TStringList; begin OutP := TStringList.Create; ErrorP := TstringList.Create; ExecConsoleApp(str, OutP, ErrorP); Result:= OutP.GetText; OutP.Free; ErrorP.Free; end; procedure CreateWin9xProcessList(List: TstringList); var hSnapShot: THandle; ProcInfo: TProcessEntry32; begin if List = nil then Exit; hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapShot <> THandle(-1)) then begin ProcInfo.dwSize := SizeOf(ProcInfo); if (Process32First(hSnapshot, ProcInfo)) then begin List.Add(ProcInfo.szExeFile); while (Process32Next(hSnapShot, ProcInfo)) do List.Add(ProcInfo.szExeFile); end; CloseHandle(hSnapShot); end; end; procedure CreateWinNTProcessList(List: TstringList); var PIDArray: array [0..1023] of DWORD; cb: DWORD; I: Integer; ProcCount: Integer; hMod: HMODULE; hProcess: THandle; ModuleName: array [0..300] of Char; begin if List = nil then Exit; EnumProcesses(@PIDArray, SizeOf(PIDArray), cb); ProcCount := cb div SizeOf(DWORD); for I := 0 to ProcCount - 1 do begin hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PIDArray[I]); if (hProcess <> 0) then begin EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb); GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName)); List.Add(ModuleName); CloseHandle(hProcess); end; end; end; procedure GetProcessList(var List: TstringList); var ovi: TOSVersionInfo; begin if List = nil then Exit; ovi.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(ovi); case ovi.dwPlatformId of VER_PLATFORM_WIN32_WINDOWS: CreateWin9xProcessList(List); VER_PLATFORM_WIN32_NT: CreateWinNTProcessList(List); end end; function RunTask(FileName: string; bFullpath: Boolean): Boolean; stdcall; var i: Integer; MyProcList: TstringList; begin MyProcList := TStringList.Create; try GetProcessList(MyProcList); Result := False; if MyProcList = nil then Exit; for i := 0 to MyProcList.Count - 1 do begin if not bFullpath then begin if CompareText(ExtractFileName(MyProcList.Strings[i]), FileName) = 0 then Result := True end else if CompareText(MyProcList.strings[i], FileName) = 0 then Result := True; if Result then Break; end; finally MyProcList.Free; end; end; function KillTask(ExeFileName: PChar): integer; stdcall; const PROCESS_TERMINATE=$0001; var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin result := 0; FSnapshotHandle := CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := Sizeof(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32); while integer(ContinueLoop) <> 0 do begin if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then Result := Integer(TerminateProcess(OpenProcess( PROCESS_TERMINATE, BOOL(0), FProcessEntry32.th32ProcessID), 0)); ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); end; CloseHandle(FSnapshotHandle); end; exports ExecConsoleAppX, KillTask, RunTask; begin // library initialization code SaveExit := ExitProc; // save exit procedure chain ExitProc := @LibExit; // install LibExit exit procedure end. |