Process.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. //
  2. // System.Diagnostics.Process.cs
  3. //
  4. // Authors:
  5. // Dick Porter ([email protected])
  6. //
  7. // (C) 2002 Ximian, Inc.
  8. //
  9. using System;
  10. using System.IO;
  11. using System.ComponentModel;
  12. using System.Runtime.CompilerServices;
  13. using System.Runtime.InteropServices;
  14. using System.Collections;
  15. namespace System.Diagnostics {
  16. public class Process : Component {
  17. [StructLayout(LayoutKind.Sequential)]
  18. private struct ProcInfo {
  19. public IntPtr process_handle;
  20. public IntPtr thread_handle;
  21. public int pid;
  22. public int tid;
  23. };
  24. IntPtr process_handle;
  25. int pid;
  26. /* Private constructor called from other methods */
  27. private Process(IntPtr handle, int id) {
  28. process_handle=handle;
  29. pid=id;
  30. }
  31. [MonoTODO]
  32. public Process() {
  33. }
  34. [MonoTODO]
  35. public int BasePriority {
  36. get {
  37. return(0);
  38. }
  39. }
  40. [MonoTODO]
  41. public bool EnableRaisingEvents {
  42. get {
  43. return(false);
  44. }
  45. set {
  46. }
  47. }
  48. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  49. private extern static int ExitCode_internal(IntPtr handle);
  50. public int ExitCode {
  51. get {
  52. return(ExitCode_internal(process_handle));
  53. }
  54. }
  55. /* Returns the process start time in Windows file
  56. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  57. */
  58. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  59. private extern static long ExitTime_internal(IntPtr handle);
  60. public DateTime ExitTime {
  61. get {
  62. return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
  63. }
  64. }
  65. public IntPtr Handle {
  66. get {
  67. return(process_handle);
  68. }
  69. }
  70. [MonoTODO]
  71. public int HandleCount {
  72. get {
  73. return(0);
  74. }
  75. }
  76. [MonoTODO]
  77. public bool HasExited {
  78. get {
  79. return(false);
  80. }
  81. }
  82. public int Id {
  83. get {
  84. return(pid);
  85. }
  86. }
  87. [MonoTODO]
  88. public string MachineName {
  89. get {
  90. return("localhost");
  91. }
  92. }
  93. public ProcessModule MainModule {
  94. get {
  95. return(this.Modules[0]);
  96. }
  97. }
  98. [MonoTODO]
  99. public IntPtr MainWindowHandle {
  100. get {
  101. return((IntPtr)0);
  102. }
  103. }
  104. [MonoTODO]
  105. public string MainWindowTitle {
  106. get {
  107. return("null");
  108. }
  109. }
  110. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  111. private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
  112. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  113. private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
  114. /* LAMESPEC: why is this an IntPtr not a plain int? */
  115. public IntPtr MaxWorkingSet {
  116. get {
  117. if(HasExited) {
  118. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  119. }
  120. int min;
  121. int max;
  122. bool ok=GetWorkingSet_internal(process_handle, out min, out max);
  123. if(ok==false) {
  124. throw new Win32Exception();
  125. }
  126. return((IntPtr)max);
  127. }
  128. set {
  129. if(HasExited) {
  130. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  131. }
  132. bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
  133. if(ok==false) {
  134. throw new Win32Exception();
  135. }
  136. }
  137. }
  138. public IntPtr MinWorkingSet {
  139. get {
  140. if(HasExited) {
  141. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  142. }
  143. int min;
  144. int max;
  145. bool ok=GetWorkingSet_internal(process_handle, out min, out max);
  146. if(ok==false) {
  147. throw new Win32Exception();
  148. }
  149. return((IntPtr)min);
  150. }
  151. set {
  152. if(HasExited) {
  153. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  154. }
  155. bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
  156. if(ok==false) {
  157. throw new Win32Exception();
  158. }
  159. }
  160. }
  161. /* Returns the list of process modules. The main module is
  162. * element 0.
  163. */
  164. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  165. private extern ProcessModule[] GetModules_internal();
  166. private ProcessModuleCollection module_collection;
  167. public ProcessModuleCollection Modules {
  168. get {
  169. if(module_collection==null) {
  170. module_collection=new ProcessModuleCollection(GetModules_internal());
  171. }
  172. return(module_collection);
  173. }
  174. }
  175. [MonoTODO]
  176. public int NonpagedSystemMemorySize {
  177. get {
  178. return(0);
  179. }
  180. }
  181. [MonoTODO]
  182. public int PagedMemorySize {
  183. get {
  184. return(0);
  185. }
  186. }
  187. [MonoTODO]
  188. public int PagedSystemMemorySize {
  189. get {
  190. return(0);
  191. }
  192. }
  193. [MonoTODO]
  194. public int PeakPagedMemorySize {
  195. get {
  196. return(0);
  197. }
  198. }
  199. [MonoTODO]
  200. public int PeakVirtualMemorySize {
  201. get {
  202. return(0);
  203. }
  204. }
  205. [MonoTODO]
  206. public int PeakWorkingSet {
  207. get {
  208. return(0);
  209. }
  210. }
  211. [MonoTODO]
  212. public bool PriorityBoostEnabled {
  213. get {
  214. return(false);
  215. }
  216. set {
  217. }
  218. }
  219. [MonoTODO]
  220. public ProcessPriorityClass PriorityClass {
  221. get {
  222. return(ProcessPriorityClass.Normal);
  223. }
  224. set {
  225. }
  226. }
  227. [MonoTODO]
  228. public int PrivateMemorySize {
  229. get {
  230. return(0);
  231. }
  232. }
  233. [MonoTODO]
  234. public TimeSpan PrivilegedProcessorTime {
  235. get {
  236. return(new TimeSpan(0));
  237. }
  238. }
  239. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  240. private extern static string ProcessName_internal(IntPtr handle);
  241. private string process_name=null;
  242. public string ProcessName {
  243. get {
  244. if(process_name==null) {
  245. process_name=ProcessName_internal(process_handle);
  246. /* If process_name is _still_
  247. * null, assume the process
  248. * has exited
  249. */
  250. if(process_name==null) {
  251. throw new SystemException("The process has exited");
  252. }
  253. /* Strip the suffix (if it
  254. * exists) simplistically
  255. * instead of removing any
  256. * trailing \.???, so we dont
  257. * get stupid results on sane
  258. * systems
  259. */
  260. if(process_name.EndsWith(".exe") ||
  261. process_name.EndsWith(".bat") ||
  262. process_name.EndsWith(".com")) {
  263. process_name=process_name.Substring(0, process_name.Length-4);
  264. }
  265. }
  266. return(process_name);
  267. }
  268. }
  269. [MonoTODO]
  270. public IntPtr ProcessorAffinity {
  271. get {
  272. return((IntPtr)0);
  273. }
  274. set {
  275. }
  276. }
  277. [MonoTODO]
  278. public bool Responding {
  279. get {
  280. return(false);
  281. }
  282. }
  283. private StreamReader error_stream=null;
  284. public StreamReader StandardError {
  285. get {
  286. return(error_stream);
  287. }
  288. }
  289. private StreamWriter input_stream=null;
  290. public StreamWriter StandardInput {
  291. get {
  292. return(input_stream);
  293. }
  294. }
  295. private StreamReader output_stream=null;
  296. public StreamReader StandardOutput {
  297. get {
  298. return(output_stream);
  299. }
  300. }
  301. private ProcessStartInfo start_info=null;
  302. public ProcessStartInfo StartInfo {
  303. get {
  304. if(start_info==null) {
  305. start_info=new ProcessStartInfo();
  306. }
  307. return(start_info);
  308. }
  309. set {
  310. if(value==null) {
  311. throw new ArgumentException("value is null");
  312. }
  313. start_info=value;
  314. }
  315. }
  316. /* Returns the process start time in Windows file
  317. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  318. */
  319. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  320. private extern static long StartTime_internal(IntPtr handle);
  321. public DateTime StartTime {
  322. get {
  323. return(DateTime.FromFileTime(StartTime_internal(process_handle)));
  324. }
  325. }
  326. [MonoTODO]
  327. public ISynchronizeInvoke SynchronizingObject {
  328. get {
  329. return(null);
  330. }
  331. set {
  332. }
  333. }
  334. [MonoTODO]
  335. public ProcessThreadCollection Threads {
  336. get {
  337. return(null);
  338. }
  339. }
  340. [MonoTODO]
  341. public TimeSpan TotalProcessorTime {
  342. get {
  343. return(new TimeSpan(0));
  344. }
  345. }
  346. [MonoTODO]
  347. public TimeSpan UserProcessorTime {
  348. get {
  349. return(new TimeSpan(0));
  350. }
  351. }
  352. [MonoTODO]
  353. public int VirtualMemorySize {
  354. get {
  355. return(0);
  356. }
  357. }
  358. [MonoTODO]
  359. public int WorkingSet {
  360. get {
  361. return(0);
  362. }
  363. }
  364. [MonoTODO]
  365. public void Close() {
  366. }
  367. [MonoTODO]
  368. public bool CloseMainWindow() {
  369. return(false);
  370. }
  371. [MonoTODO]
  372. public static void EnterDebugMode() {
  373. }
  374. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  375. private extern static IntPtr GetProcess_internal(int pid);
  376. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  377. private extern static int GetPid_internal();
  378. public static Process GetCurrentProcess() {
  379. int pid=GetPid_internal();
  380. IntPtr proc=GetProcess_internal(pid);
  381. if(proc==IntPtr.Zero) {
  382. throw new SystemException("Can't find current process");
  383. }
  384. return(new Process(proc, pid));
  385. }
  386. public static Process GetProcessById(int processId) {
  387. IntPtr proc=GetProcess_internal(processId);
  388. if(proc==IntPtr.Zero) {
  389. throw new ArgumentException("Can't find process with ID " + processId.ToString());
  390. }
  391. return(new Process(proc, processId));
  392. }
  393. [MonoTODO]
  394. public static Process GetProcessById(int processId, string machineName) {
  395. throw new NotImplementedException();
  396. }
  397. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  398. private extern static int[] GetProcesses_internal();
  399. public static Process[] GetProcesses() {
  400. int[] pids=GetProcesses_internal();
  401. ArrayList proclist=new ArrayList();
  402. for(int i=0; i<pids.Length; i++) {
  403. try {
  404. proclist.Add(GetProcessById(pids[i]));
  405. } catch (SystemException) {
  406. /* The process might exit
  407. * between
  408. * GetProcesses_internal and
  409. * GetProcessById
  410. */
  411. }
  412. }
  413. return((Process[])proclist.ToArray(typeof(Process)));
  414. }
  415. [MonoTODO]
  416. public static Process[] GetProcesses(string machineName) {
  417. throw new NotImplementedException();
  418. }
  419. public static Process[] GetProcessesByName(string processName) {
  420. Process[] procs=GetProcesses();
  421. ArrayList proclist=new ArrayList();
  422. for(int i=0; i<procs.Length; i++) {
  423. /* Ignore case */
  424. if(String.Compare(processName,
  425. procs[i].ProcessName,
  426. true)==0) {
  427. proclist.Add(procs[i]);
  428. }
  429. }
  430. return((Process[])proclist.ToArray(typeof(Process)));
  431. }
  432. [MonoTODO]
  433. public static Process[] GetProcessesByName(string processName, string machineName) {
  434. throw new NotImplementedException();
  435. }
  436. [MonoTODO]
  437. public void Kill() {
  438. }
  439. [MonoTODO]
  440. public static void LeaveDebugMode() {
  441. }
  442. [MonoTODO]
  443. public void Refresh() {
  444. }
  445. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  446. private extern static bool Start_internal(string cmd,
  447. string dir,
  448. IntPtr stdin,
  449. IntPtr stdout,
  450. IntPtr stderr,
  451. ref ProcInfo proc_info);
  452. private static bool Start_common(ProcessStartInfo startInfo,
  453. Process process) {
  454. ProcInfo proc_info=new ProcInfo();
  455. IntPtr stdin_rd, stdin_wr;
  456. IntPtr stdout_rd, stdout_wr;
  457. IntPtr stderr_rd, stderr_wr;
  458. bool ret;
  459. if(startInfo.FileName == "") {
  460. throw new InvalidOperationException("File name has not been set");
  461. }
  462. if(startInfo.RedirectStandardInput==true) {
  463. ret=MonoIO.CreatePipe(out stdin_rd,
  464. out stdin_wr);
  465. } else {
  466. stdin_rd=MonoIO.ConsoleInput;
  467. /* This is required to stop the
  468. * &$*£ing stupid compiler moaning
  469. * that stdin_wr is unassigned, below.
  470. */
  471. stdin_wr=(IntPtr)0;
  472. }
  473. if(startInfo.RedirectStandardOutput==true) {
  474. ret=MonoIO.CreatePipe(out stdout_rd,
  475. out stdout_wr);
  476. } else {
  477. stdout_rd=(IntPtr)0;
  478. stdout_wr=MonoIO.ConsoleOutput;
  479. }
  480. if(startInfo.RedirectStandardError==true) {
  481. ret=MonoIO.CreatePipe(out stderr_rd,
  482. out stderr_wr);
  483. } else {
  484. stderr_rd=(IntPtr)0;
  485. stderr_wr=MonoIO.ConsoleError;
  486. }
  487. ret=Start_internal(startInfo.FileName + " " +
  488. startInfo.Arguments,
  489. startInfo.WorkingDirectory,
  490. stdin_rd, stdout_wr, stderr_wr,
  491. ref proc_info);
  492. process.process_handle=proc_info.process_handle;
  493. process.pid=proc_info.pid;
  494. MonoIOError error;
  495. if(startInfo.RedirectStandardInput==true) {
  496. MonoIO.Close(stdin_rd, out error);
  497. process.input_stream=new StreamWriter(new FileStream(stdin_wr, FileAccess.Write, true));
  498. process.input_stream.AutoFlush=true;
  499. }
  500. if(startInfo.RedirectStandardOutput==true) {
  501. MonoIO.Close(stdout_wr, out error);
  502. process.output_stream=new StreamReader(new FileStream(stdout_rd, FileAccess.Read, true));
  503. }
  504. if(startInfo.RedirectStandardError==true) {
  505. MonoIO.Close(stderr_wr, out error);
  506. process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
  507. }
  508. return(ret);
  509. }
  510. public bool Start() {
  511. bool ret;
  512. ret=Start_common(start_info, this);
  513. return(ret);
  514. }
  515. public static Process Start(ProcessStartInfo startInfo) {
  516. Process process=new Process();
  517. bool ret;
  518. ret=Start_common(startInfo, process);
  519. if(ret==true) {
  520. return(process);
  521. } else {
  522. return(null);
  523. }
  524. }
  525. public static Process Start(string fileName) {
  526. return Start(new ProcessStartInfo(fileName));
  527. }
  528. public static Process Start(string fileName,
  529. string arguments) {
  530. return Start(new ProcessStartInfo(fileName, arguments));
  531. }
  532. public override string ToString() {
  533. return(base.ToString() +
  534. " (" + this.ProcessName + ")");
  535. }
  536. /* Waits up to ms milliseconds for process 'handle' to
  537. * exit. ms can be <0 to mean wait forever.
  538. */
  539. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  540. private extern bool WaitForExit_internal(IntPtr handle,
  541. int ms);
  542. public void WaitForExit() {
  543. WaitForExit_internal(process_handle, -1);
  544. }
  545. public bool WaitForExit(int milliseconds) {
  546. return(WaitForExit_internal(process_handle,
  547. milliseconds));
  548. }
  549. [MonoTODO]
  550. public bool WaitForInputIdle() {
  551. return(false);
  552. }
  553. [MonoTODO]
  554. public bool WaitForInputIdle(int milliseconds) {
  555. return(false);
  556. }
  557. [MonoTODO]
  558. public event EventHandler Exited;
  559. // Closes the system process handle
  560. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  561. private extern void Process_free_internal(IntPtr handle);
  562. private bool disposed = false;
  563. protected override void Dispose(bool disposing) {
  564. // Check to see if Dispose has already been called.
  565. if(this.disposed) {
  566. this.disposed=true;
  567. // If this is a call to Dispose,
  568. // dispose all managed resources.
  569. if(disposing) {
  570. // Do stuff here
  571. }
  572. // Release unmanaged resources
  573. lock(this) {
  574. if(process_handle!=IntPtr.Zero) {
  575. Process_free_internal(process_handle);
  576. process_handle=IntPtr.Zero;
  577. }
  578. }
  579. }
  580. base.Dispose (disposing);
  581. }
  582. [MonoTODO]
  583. protected void OnExited() {
  584. }
  585. }
  586. }