diff --git a/Source/script/imports/simba/simba.import_process.pas b/Source/script/imports/simba/simba.import_process.pas index f4796a784..eae107aba 100644 --- a/Source/script/imports/simba/simba.import_process.pas +++ b/Source/script/imports/simba/simba.import_process.pas @@ -61,6 +61,16 @@ procedure _LapeGetProcessMemUsage(const Params: PParamArray; const Result: Point PInt64(Result)^ := SimbaProcess.GetProcessMemUsage(PProcessID(Params^[0])^); end; +procedure _LapeGetProcessStartTime(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +begin + PDateTime(Result)^ := SimbaProcess.GetProcessStartTime(PProcessID(Params^[0])^); +end; + +procedure _LapeGetProcessRunningTime(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +begin + PUInt64(Result)^ := SimbaProcess.GetProcessRunnningTime(PProcessID(Params^[0])^); +end; + procedure _LapeTerminateProcess(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin SimbaProcess.TerminateProcess(PProcessID(Params^[0])^); @@ -78,6 +88,8 @@ procedure ImportProcess(Compiler: TSimbaScript_Compiler); addGlobalFunc('function IsProcess64Bit(PID: TProcessID): Boolean', @_LapeIsProcess64Bit); addGlobalFunc('function GetProcessPath(PID: TProcessID): String', @_LapeGetProcessPath); addGlobalFunc('function GetProcessMemUsage(PID: TProcessID): Int64', @_LapeGetProcessMemUsage); + addGlobalFunc('function GetProcessStartTime(PID: TProcessID): TDateTime', @_LapeGetProcessStartTime); + addGlobalFunc('function GetProcessRunnningTime(PID: TProcessID): UInt64', @_LapeGetProcessRunningTime); addGlobalFunc('procedure TerminateProcess(PID: TProcessID)', @_LapeTerminateProcess); addGlobalFunc('function RunCommandInDir(Directory, Executable: String; Commands: TStringArray; out Output: String): TProcessExitStatus; overload', @_LapeRunCommandInDirOutput); addGlobalFunc('function RunCommandInDir(Directory, Executable: String; Commands: TStringArray): TProcessID; overload', @_LapeRunCommandInDir); diff --git a/Source/simba.nativeinterface.pas b/Source/simba.nativeinterface.pas index 76f6b7734..f2257d3f4 100644 --- a/Source/simba.nativeinterface.pas +++ b/Source/simba.nativeinterface.pas @@ -38,6 +38,7 @@ TSimbaNativeInterface = class procedure KeyDown(Key: KeyCode); virtual; abstract; procedure KeyUp(Key: KeyCode); virtual; abstract; + function GetProcessStartTime(PID: SizeUInt): TDateTime; virtual; abstract; function GetProcessMemUsage(PID: SizeUInt): Int64; virtual; abstract; function GetProcessPath(PID: SizeUInt): String; virtual; abstract; function IsProcess64Bit(PID: SizeUInt): Boolean; virtual; abstract; diff --git a/Source/simba.nativeinterface_darwin.pas b/Source/simba.nativeinterface_darwin.pas index 993e3bc97..2f1523170 100644 --- a/Source/simba.nativeinterface_darwin.pas +++ b/Source/simba.nativeinterface_darwin.pas @@ -68,6 +68,7 @@ TKeyMapItem = record procedure KeyDown(Key: KeyCode); override; procedure KeyUp(Key: KeyCode); override; + function GetProcessStartTime(PID: SizeUInt): TDateTime; override; function GetProcessMemUsage(PID: SizeUInt): Int64; override; function GetProcessPath(PID: SizeUInt): String; override; function IsProcess64Bit(PID: SizeUInt): Boolean; override; @@ -105,7 +106,7 @@ TKeyMapItem = record implementation uses - baseunix, unix, lcltype, cocoaall, cocoautils, + BaseUnix, Unix, LCLType, CocoaAll, CocoaUtils, DateUtils, simba.process, simba.darwin_axui, simba.windowhandle; type @@ -125,14 +126,13 @@ function mach_timebase_info(var TimebaseInfoData: TTimebaseInfoData): Int64; cde function mach_absolute_time: QWORD; cdecl; external 'libc'; type - TProcTaskInfo = record + proc_taskinfo = record virtual_size: uint64; resident_size: uint64; total_user: uint64; total_system: uint64; threads_user: uint64; threads_system: uint64; - policy: int32; faults: int32; pageins: int32; @@ -147,7 +147,33 @@ TProcTaskInfo = record priority: int32; end; + proc_bsdinfo = record + pbi_flags: uint32; + pbi_status: uint32; + pbi_xstatus: uint32; + pbi_pid: uint32; + pbi_ppid: uint32; + pbi_uid: int32; + pbi_gid: int32; + pbi_ruid: int32; + pbi_rgid: int32; + pbi_svuid: int32; + pbi_svgid: int32; + rfu_1: uint32; + pbi_comm: array[1..16] of Char; + pbi_name: array[1..32] of Char; + pbi_nfiles: uint32; + pbi_pgid: uint32; + pbi_pjobc: uint32; + e_tdev: uint32; + e_tpgid: uint32; + pbi_nice: int32; + pbi_start_tvsec: uint64; + pbi_start_tvusec: uint64; + end; + const + PROC_PIDTBSDINFO = 3; PROC_PIDTASKINFO = 4; function proc_pidpath(pid: longint; buffer: pbyte; bufferSize: longword): longint; cdecl; external 'libproc'; @@ -524,13 +550,23 @@ function TSimbaNativeInterface_Darwin.GetNativeKeyCodeAndModifiers(Character: Ch end end; +function TSimbaNativeInterface_Darwin.GetProcessStartTime(PID: SizeUInt): TDateTime; +var + info: proc_bsdinfo; +begin + Result := 0; + + if proc_pidinfo(PID, PROC_PIDTBSDINFO, 0, @info, sizeof(proc_bsdinfo)) > 0 then + Result := UnixToDateTime(info.pbi_start_tvsec) +end; + function TSimbaNativeInterface_Darwin.GetProcessMemUsage(PID: SizeUInt): Int64; var - info: TProcTaskInfo; + info: proc_taskinfo; begin Result := 0; - if proc_pidinfo(PID, PROC_PIDTASKINFO, 0, @info, SizeOf(TProcTaskInfo)) > 0 then + if proc_pidinfo(PID, PROC_PIDTASKINFO, 0, @info, SizeOf(proc_taskinfo)) > 0 then Result := info.resident_size; end; diff --git a/Source/simba.nativeinterface_linux.pas b/Source/simba.nativeinterface_linux.pas index 4c3acbdf8..08a115c51 100644 --- a/Source/simba.nativeinterface_linux.pas +++ b/Source/simba.nativeinterface_linux.pas @@ -40,6 +40,7 @@ TSimbaNativeInterface_Linux = class(TSimbaNativeInterface) procedure KeyDown(Key: KeyCode); override; procedure KeyUp(Key: KeyCode); override; + function GetProcessStartTime(PID: SizeUInt): TDateTime; override; function GetProcessMemUsage(PID: SizeUInt): Int64; override; function GetProcessPath(PID: SizeUInt): String; override; function IsProcess64Bit(PID: SizeUInt): Boolean; override; @@ -491,6 +492,16 @@ procedure TSimbaNativeInterface_Linux.KeyUp(Key: KeyCode); SimbaXLib.XSync(False); end; +function TSimbaNativeInterface_Linux.GetProcessStartTime(PID: SizeUInt): TDateTime; +var + Info: stat; +begin + Result := 0; + + if (fpstat('/proc/' + IntToStr(PID), Info) = 0) then + Result := FileDateToDateTime(Info.st_ctime); +end; + function TSimbaNativeInterface_Linux.GetProcessMemUsage(PID: SizeUInt): Int64; var List: TStringList; diff --git a/Source/simba.nativeinterface_windows.pas b/Source/simba.nativeinterface_windows.pas index ac28e0916..13e31ad2b 100644 --- a/Source/simba.nativeinterface_windows.pas +++ b/Source/simba.nativeinterface_windows.pas @@ -51,6 +51,7 @@ TSimbaNativeInterface_Windows = class(TSimbaNativeInterface) procedure KeyDown(Key: KeyCode); override; procedure KeyUp(Key: KeyCode); override; + function GetProcessStartTime(PID: SizeUInt): TDateTime; override; function GetProcessMemUsage(PID: SizeUInt): Int64; override; function GetProcessPath(PID: SizeUInt): String; override; function IsProcess64Bit(PID: SizeUInt): Boolean; override; @@ -511,6 +512,25 @@ procedure TSimbaNativeInterface_Windows.KeyUp(Key: KeyCode); SendInput(1, @Input, SizeOf(Input)); end; +function TSimbaNativeInterface_Windows.GetProcessStartTime(PID: SizeUInt): TDateTime; +var + CreationTime, ExitTime, KernelTime, UserTime: TFileTime; + FileTime: TFileTime; + SystemTime: TSystemTime; + Handle: THandle; +begin + Result := 0; + + Handle := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, PID); + if (Handle = 0) then + Exit; + if GetProcessTimes(Handle, CreationTime, ExitTime, KernelTime, UserTime) then + if FileTimeToLocalFileTime(CreationTime, FileTime) and FileTimeToSystemTime(FileTime, SystemTime) then + Result := SystemTimeToDateTime(SystemTime); + + CloseHandle(Handle); +end; + function TSimbaNativeInterface_Windows.GetProcessMemUsage(PID: SizeUInt): Int64; var Handle: THandle; diff --git a/Source/simba.process.pas b/Source/simba.process.pas index 581f6fdcb..8a0d07642 100644 --- a/Source/simba.process.pas +++ b/Source/simba.process.pas @@ -29,6 +29,8 @@ TSimbaProcess = record function IsProcessRunning(PID: TProcessID): Boolean; function GetProcessPath(PID: TProcessID): String; function GetProcessMemUsage(PID: TProcessID): Int64; + function GetProcessStartTime(PID: TProcessID): TDateTime; + function GetProcessRunnningTime(PID: TProcessID): UInt64; procedure TerminateProcess(PID: TProcessID); function RunCommandInDir(Directory, Executable: String; Commands: TStringArray; out Output: String): TProcessExitStatus; overload; @@ -52,7 +54,7 @@ TSimbaProcess = record implementation uses - forms, process, lazloggerbase, + Forms, Process, DateUtils, simba.env, simba.files, simba.nativeinterface; type @@ -136,6 +138,16 @@ function TSimbaProcess.GetProcessMemUsage(PID: TProcessID): Int64; Result := SimbaNativeInterface.GetProcessMemUsage(PID); end; +function TSimbaProcess.GetProcessStartTime(PID: TProcessID): TDateTime; +begin + Result := SimbaNativeInterface.GetProcessStartTime(PID); +end; + +function TSimbaProcess.GetProcessRunnningTime(PID: TProcessID): UInt64; +begin + Result := MillisecondsBetween(GetProcessStartTime(PID), Now()); +end; + procedure TSimbaProcess.TerminateProcess(PID: TProcessID); begin SimbaNativeInterface.TerminateProcess(PID);