Process.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. //
  2. // System.Diagnostics.Process.cs
  3. //
  4. // Authors:
  5. // Dick Porter ([email protected])
  6. // Andreas Nahr ([email protected])
  7. //
  8. // (C) 2002 Ximian, Inc.
  9. // (C) 2003 Andreas Nahr
  10. //
  11. using System;
  12. using System.IO;
  13. using System.ComponentModel;
  14. using System.ComponentModel.Design;
  15. using System.Runtime.CompilerServices;
  16. using System.Runtime.InteropServices;
  17. using System.Collections;
  18. using System.Threading;
  19. namespace System.Diagnostics {
  20. [DefaultEvent ("Exited"), DefaultProperty ("StartInfo")]
  21. [Designer ("System.Diagnostics.Design.ProcessDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
  22. public class Process : Component
  23. {
  24. [StructLayout(LayoutKind.Sequential)]
  25. private struct ProcInfo
  26. {
  27. public IntPtr process_handle;
  28. public IntPtr thread_handle;
  29. public int pid; // Contains -GetLastError () on failure.
  30. public int tid;
  31. public string [] envKeys;
  32. public string [] envValues;
  33. public bool useShellExecute;
  34. };
  35. IntPtr process_handle;
  36. int pid;
  37. bool enableRaisingEvents;
  38. /* Private constructor called from other methods */
  39. private Process(IntPtr handle, int id) {
  40. process_handle=handle;
  41. pid=id;
  42. }
  43. [MonoTODO]
  44. public Process() {
  45. }
  46. [MonoTODO]
  47. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  48. [MonitoringDescription ("Base process priority.")]
  49. public int BasePriority {
  50. get {
  51. return(0);
  52. }
  53. }
  54. [MonoTODO]
  55. [DefaultValue (false), Browsable (false)]
  56. [MonitoringDescription ("Check for exiting of the process to raise the apropriate event.")]
  57. public bool EnableRaisingEvents {
  58. get {
  59. return enableRaisingEvents;
  60. }
  61. set {
  62. if (process_handle != IntPtr.Zero)
  63. throw new InvalidOperationException ("The process is already started.");
  64. enableRaisingEvents = value;
  65. }
  66. }
  67. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  68. private extern static int ExitCode_internal(IntPtr handle);
  69. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  70. [MonitoringDescription ("The exit code of the process.")]
  71. public int ExitCode {
  72. get {
  73. if (process_handle == IntPtr.Zero)
  74. throw new InvalidOperationException ("Process has not been started.");
  75. int code = ExitCode_internal (process_handle);
  76. if (code == 259)
  77. throw new InvalidOperationException ("The process must exit before " +
  78. "getting the requested information.");
  79. return code;
  80. }
  81. }
  82. /* Returns the process start time in Windows file
  83. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  84. */
  85. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  86. private extern static long ExitTime_internal(IntPtr handle);
  87. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  88. [MonitoringDescription ("The exit time of the process.")]
  89. public DateTime ExitTime {
  90. get {
  91. if (process_handle == IntPtr.Zero)
  92. throw new InvalidOperationException ("Process has not been started.");
  93. if (!HasExited)
  94. throw new InvalidOperationException ("The process must exit before " +
  95. "getting the requested information.");
  96. return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
  97. }
  98. }
  99. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  100. [MonitoringDescription ("Handle for this process.")]
  101. public IntPtr Handle {
  102. get {
  103. return(process_handle);
  104. }
  105. }
  106. [MonoTODO]
  107. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  108. [MonitoringDescription ("Handles for this process.")]
  109. public int HandleCount {
  110. get {
  111. return(0);
  112. }
  113. }
  114. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  115. [MonitoringDescription ("Determines if the process is still running.")]
  116. public bool HasExited {
  117. get {
  118. int exitcode = ExitCode_internal (process_handle);
  119. if(exitcode==259) {
  120. /* STILL_ACTIVE */
  121. return(false);
  122. } else {
  123. return(true);
  124. }
  125. }
  126. }
  127. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  128. [MonitoringDescription ("Process identifier.")]
  129. public int Id {
  130. get {
  131. return(pid);
  132. }
  133. }
  134. [MonoTODO]
  135. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  136. [MonitoringDescription ("The name of the computer running the process.")]
  137. public string MachineName {
  138. get {
  139. return("localhost");
  140. }
  141. }
  142. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  143. [MonitoringDescription ("The main module of the process.")]
  144. public ProcessModule MainModule {
  145. get {
  146. return(this.Modules[0]);
  147. }
  148. }
  149. [MonoTODO]
  150. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  151. [MonitoringDescription ("The handle of the main window of the process.")]
  152. public IntPtr MainWindowHandle {
  153. get {
  154. return((IntPtr)0);
  155. }
  156. }
  157. [MonoTODO]
  158. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  159. [MonitoringDescription ("The title of the main window of the process.")]
  160. public string MainWindowTitle {
  161. get {
  162. return("null");
  163. }
  164. }
  165. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  166. private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
  167. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  168. private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
  169. /* LAMESPEC: why is this an IntPtr not a plain int? */
  170. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  171. [MonitoringDescription ("The maximum working set for this process.")]
  172. public IntPtr MaxWorkingSet {
  173. get {
  174. if(HasExited) {
  175. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  176. }
  177. int min;
  178. int max;
  179. bool ok=GetWorkingSet_internal(process_handle, out min, out max);
  180. if(ok==false) {
  181. throw new Win32Exception();
  182. }
  183. return((IntPtr)max);
  184. }
  185. set {
  186. if(HasExited) {
  187. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  188. }
  189. bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
  190. if(ok==false) {
  191. throw new Win32Exception();
  192. }
  193. }
  194. }
  195. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  196. [MonitoringDescription ("The minimum working set for this process.")]
  197. public IntPtr MinWorkingSet {
  198. get {
  199. if(HasExited) {
  200. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  201. }
  202. int min;
  203. int max;
  204. bool ok=GetWorkingSet_internal(process_handle, out min, out max);
  205. if(ok==false) {
  206. throw new Win32Exception();
  207. }
  208. return((IntPtr)min);
  209. }
  210. set {
  211. if(HasExited) {
  212. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  213. }
  214. bool ok=SetWorkingSet_internal(process_handle, value.ToInt32(), 0, true);
  215. if(ok==false) {
  216. throw new Win32Exception();
  217. }
  218. }
  219. }
  220. /* Returns the list of process modules. The main module is
  221. * element 0.
  222. */
  223. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  224. private extern ProcessModule[] GetModules_internal();
  225. private ProcessModuleCollection module_collection;
  226. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  227. [MonitoringDescription ("The modules that are loaded as part of this process.")]
  228. public ProcessModuleCollection Modules {
  229. get {
  230. if(module_collection==null) {
  231. module_collection=new ProcessModuleCollection(GetModules_internal());
  232. }
  233. return(module_collection);
  234. }
  235. }
  236. [MonoTODO]
  237. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  238. [MonitoringDescription ("The number of bytes that are not pageable.")]
  239. public int NonpagedSystemMemorySize {
  240. get {
  241. return(0);
  242. }
  243. }
  244. [MonoTODO]
  245. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  246. [MonitoringDescription ("The number of bytes that are paged.")]
  247. public int PagedMemorySize {
  248. get {
  249. return(0);
  250. }
  251. }
  252. [MonoTODO]
  253. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  254. [MonitoringDescription ("The amount of paged system memory in bytes.")]
  255. public int PagedSystemMemorySize {
  256. get {
  257. return(0);
  258. }
  259. }
  260. [MonoTODO]
  261. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  262. [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
  263. public int PeakPagedMemorySize {
  264. get {
  265. return(0);
  266. }
  267. }
  268. [MonoTODO]
  269. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  270. [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
  271. public int PeakVirtualMemorySize {
  272. get {
  273. return(0);
  274. }
  275. }
  276. [MonoTODO]
  277. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  278. [MonitoringDescription ("The maximum amount of system memory used by this process.")]
  279. public int PeakWorkingSet {
  280. get {
  281. return(0);
  282. }
  283. }
  284. [MonoTODO]
  285. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  286. [MonitoringDescription ("Process will be of higher priority while it is actively used.")]
  287. public bool PriorityBoostEnabled {
  288. get {
  289. return(false);
  290. }
  291. set {
  292. }
  293. }
  294. [MonoTODO]
  295. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  296. [MonitoringDescription ("The relative process priority.")]
  297. public ProcessPriorityClass PriorityClass {
  298. get {
  299. return(ProcessPriorityClass.Normal);
  300. }
  301. set {
  302. }
  303. }
  304. [MonoTODO]
  305. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  306. [MonitoringDescription ("The amount of memory exclusively used by this process.")]
  307. public int PrivateMemorySize {
  308. get {
  309. return(0);
  310. }
  311. }
  312. [MonoTODO]
  313. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  314. [MonitoringDescription ("The amount of processing time spent is the OS core for this process.")]
  315. public TimeSpan PrivilegedProcessorTime {
  316. get {
  317. return(new TimeSpan(0));
  318. }
  319. }
  320. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  321. private extern static string ProcessName_internal(IntPtr handle);
  322. private string process_name=null;
  323. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  324. [MonitoringDescription ("The name of this process.")]
  325. public string ProcessName {
  326. get {
  327. if(process_name==null) {
  328. process_name=ProcessName_internal(process_handle);
  329. /* If process_name is _still_
  330. * null, assume the process
  331. * has exited
  332. */
  333. if(process_name==null) {
  334. throw new SystemException("The process has exited");
  335. }
  336. /* Strip the suffix (if it
  337. * exists) simplistically
  338. * instead of removing any
  339. * trailing \.???, so we dont
  340. * get stupid results on sane
  341. * systems
  342. */
  343. if(process_name.EndsWith(".exe") ||
  344. process_name.EndsWith(".bat") ||
  345. process_name.EndsWith(".com")) {
  346. process_name=process_name.Substring(0, process_name.Length-4);
  347. }
  348. }
  349. return(process_name);
  350. }
  351. }
  352. [MonoTODO]
  353. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  354. [MonitoringDescription ("Allowed processor that can be used by this process.")]
  355. public IntPtr ProcessorAffinity {
  356. get {
  357. return((IntPtr)0);
  358. }
  359. set {
  360. }
  361. }
  362. [MonoTODO]
  363. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  364. [MonitoringDescription ("Is this process responsive.")]
  365. public bool Responding {
  366. get {
  367. return(false);
  368. }
  369. }
  370. private StreamReader error_stream=null;
  371. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  372. [MonitoringDescription ("The standard error stream of this process.")]
  373. public StreamReader StandardError {
  374. get {
  375. return(error_stream);
  376. }
  377. }
  378. private StreamWriter input_stream=null;
  379. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  380. [MonitoringDescription ("The standard input stream of this process.")]
  381. public StreamWriter StandardInput {
  382. get {
  383. return(input_stream);
  384. }
  385. }
  386. private StreamReader output_stream=null;
  387. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  388. [MonitoringDescription ("The standard output stream of this process.")]
  389. public StreamReader StandardOutput {
  390. get {
  391. return(output_stream);
  392. }
  393. }
  394. private ProcessStartInfo start_info=null;
  395. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  396. [MonitoringDescription ("Information for the start of this process.")]
  397. public ProcessStartInfo StartInfo {
  398. get {
  399. if(start_info==null) {
  400. start_info=new ProcessStartInfo();
  401. }
  402. return(start_info);
  403. }
  404. set {
  405. if(value==null) {
  406. throw new ArgumentException("value is null");
  407. }
  408. start_info=value;
  409. }
  410. }
  411. /* Returns the process start time in Windows file
  412. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  413. */
  414. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  415. private extern static long StartTime_internal(IntPtr handle);
  416. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  417. [MonitoringDescription ("The time this process started.")]
  418. public DateTime StartTime {
  419. get {
  420. return(DateTime.FromFileTime(StartTime_internal(process_handle)));
  421. }
  422. }
  423. [MonoTODO]
  424. [DefaultValue (null), Browsable (false)]
  425. [MonitoringDescription ("The object that is used to synchronize event handler calls for this process.")]
  426. public ISynchronizeInvoke SynchronizingObject {
  427. get {
  428. return(null);
  429. }
  430. set {
  431. }
  432. }
  433. [MonoTODO]
  434. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  435. [MonitoringDescription ("The number of threads of this process.")]
  436. public ProcessThreadCollection Threads {
  437. get {
  438. return(null);
  439. }
  440. }
  441. [MonoTODO]
  442. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  443. [MonitoringDescription ("The total CPU time spent for this process.")]
  444. public TimeSpan TotalProcessorTime {
  445. get {
  446. return(new TimeSpan(0));
  447. }
  448. }
  449. [MonoTODO]
  450. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  451. [MonitoringDescription ("The CPU time spent for this process in user mode.")]
  452. public TimeSpan UserProcessorTime {
  453. get {
  454. return(new TimeSpan(0));
  455. }
  456. }
  457. [MonoTODO]
  458. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  459. [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
  460. public int VirtualMemorySize {
  461. get {
  462. return(0);
  463. }
  464. }
  465. [MonoTODO]
  466. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  467. [MonitoringDescription ("The amount of physical memory currently used for this process.")]
  468. public int WorkingSet {
  469. get {
  470. return(0);
  471. }
  472. }
  473. [MonoTODO]
  474. public void Close() {
  475. }
  476. [MonoTODO]
  477. public bool CloseMainWindow() {
  478. return(false);
  479. }
  480. [MonoTODO]
  481. public static void EnterDebugMode() {
  482. }
  483. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  484. private extern static IntPtr GetProcess_internal(int pid);
  485. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  486. private extern static int GetPid_internal();
  487. public static Process GetCurrentProcess() {
  488. int pid=GetPid_internal();
  489. IntPtr proc=GetProcess_internal(pid);
  490. if(proc==IntPtr.Zero) {
  491. throw new SystemException("Can't find current process");
  492. }
  493. return(new Process(proc, pid));
  494. }
  495. public static Process GetProcessById(int processId) {
  496. IntPtr proc=GetProcess_internal(processId);
  497. if(proc==IntPtr.Zero) {
  498. throw new ArgumentException("Can't find process with ID " + processId.ToString());
  499. }
  500. return(new Process(proc, processId));
  501. }
  502. [MonoTODO]
  503. public static Process GetProcessById(int processId, string machineName) {
  504. throw new NotImplementedException();
  505. }
  506. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  507. private extern static int[] GetProcesses_internal();
  508. public static Process[] GetProcesses() {
  509. int[] pids=GetProcesses_internal();
  510. ArrayList proclist=new ArrayList();
  511. for(int i=0; i<pids.Length; i++) {
  512. try {
  513. proclist.Add(GetProcessById(pids[i]));
  514. } catch (SystemException) {
  515. /* The process might exit
  516. * between
  517. * GetProcesses_internal and
  518. * GetProcessById
  519. */
  520. }
  521. }
  522. return((Process[])proclist.ToArray(typeof(Process)));
  523. }
  524. [MonoTODO]
  525. public static Process[] GetProcesses(string machineName) {
  526. throw new NotImplementedException();
  527. }
  528. public static Process[] GetProcessesByName(string processName) {
  529. Process[] procs=GetProcesses();
  530. ArrayList proclist=new ArrayList();
  531. for(int i=0; i<procs.Length; i++) {
  532. /* Ignore case */
  533. if(String.Compare(processName,
  534. procs[i].ProcessName,
  535. true)==0) {
  536. proclist.Add(procs[i]);
  537. }
  538. }
  539. return((Process[])proclist.ToArray(typeof(Process)));
  540. }
  541. [MonoTODO]
  542. public static Process[] GetProcessesByName(string processName, string machineName) {
  543. throw new NotImplementedException();
  544. }
  545. [MonoTODO]
  546. public void Kill() {
  547. }
  548. [MonoTODO]
  549. public static void LeaveDebugMode() {
  550. }
  551. [MonoTODO]
  552. public void Refresh() {
  553. }
  554. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  555. private extern static bool Start_internal(string cmd,
  556. string dir,
  557. IntPtr stdin,
  558. IntPtr stdout,
  559. IntPtr stderr,
  560. ref ProcInfo proc_info);
  561. private static bool Start_common(ProcessStartInfo startInfo,
  562. Process process) {
  563. ProcInfo proc_info=new ProcInfo();
  564. IntPtr stdin_rd, stdin_wr;
  565. IntPtr stdout_rd, stdout_wr;
  566. IntPtr stderr_rd, stderr_wr;
  567. bool ret;
  568. if(startInfo.FileName == "") {
  569. throw new InvalidOperationException("File name has not been set");
  570. }
  571. proc_info.useShellExecute = startInfo.UseShellExecute;
  572. if (startInfo.HaveEnvVars) {
  573. if (startInfo.UseShellExecute)
  574. throw new InvalidOperationException ("UseShellExecute must be false in order " +
  575. "to use environment variables.");
  576. string [] strs = new string [startInfo.EnvironmentVariables.Count];
  577. startInfo.EnvironmentVariables.Keys.CopyTo (strs, 0);
  578. proc_info.envKeys = strs;
  579. strs = new string [startInfo.EnvironmentVariables.Count];
  580. startInfo.EnvironmentVariables.Values.CopyTo (strs, 0);
  581. proc_info.envValues = strs;
  582. }
  583. if(startInfo.RedirectStandardInput==true) {
  584. ret=MonoIO.CreatePipe(out stdin_rd,
  585. out stdin_wr);
  586. } else {
  587. stdin_rd=MonoIO.ConsoleInput;
  588. /* This is required to stop the
  589. * &$*£ing stupid compiler moaning
  590. * that stdin_wr is unassigned, below.
  591. */
  592. stdin_wr=(IntPtr)0;
  593. }
  594. if(startInfo.RedirectStandardOutput==true) {
  595. ret=MonoIO.CreatePipe(out stdout_rd,
  596. out stdout_wr);
  597. } else {
  598. stdout_rd=(IntPtr)0;
  599. stdout_wr=MonoIO.ConsoleOutput;
  600. }
  601. if(startInfo.RedirectStandardError==true) {
  602. ret=MonoIO.CreatePipe(out stderr_rd,
  603. out stderr_wr);
  604. } else {
  605. stderr_rd=(IntPtr)0;
  606. stderr_wr=MonoIO.ConsoleError;
  607. }
  608. ret=Start_internal(startInfo.FileName + " " +
  609. startInfo.Arguments,
  610. startInfo.WorkingDirectory,
  611. stdin_rd, stdout_wr, stderr_wr,
  612. ref proc_info);
  613. MonoIOError error;
  614. if (!ret) {
  615. if (startInfo.RedirectStandardInput == true)
  616. MonoIO.Close (stdin_rd, out error);
  617. if (startInfo.RedirectStandardOutput == true)
  618. MonoIO.Close (stdout_wr, out error);
  619. if (startInfo.RedirectStandardError == true)
  620. MonoIO.Close (stderr_wr, out error);
  621. throw new Win32Exception (-proc_info.pid);
  622. }
  623. if (process.enableRaisingEvents && process.Exited != null) {
  624. WaitOrTimerCallback cb = new WaitOrTimerCallback (CBOnExit);
  625. ProcessWaitHandle h = new ProcessWaitHandle (proc_info.process_handle);
  626. ThreadPool.RegisterWaitForSingleObject (h, cb, process, -1, true);
  627. }
  628. process.process_handle=proc_info.process_handle;
  629. process.pid=proc_info.pid;
  630. if(startInfo.RedirectStandardInput==true) {
  631. MonoIO.Close(stdin_rd, out error);
  632. process.input_stream=new StreamWriter(new FileStream(stdin_wr, FileAccess.Write, true));
  633. process.input_stream.AutoFlush=true;
  634. }
  635. if(startInfo.RedirectStandardOutput==true) {
  636. MonoIO.Close(stdout_wr, out error);
  637. process.output_stream=new StreamReader(new FileStream(stdout_rd, FileAccess.Read, true));
  638. }
  639. if(startInfo.RedirectStandardError==true) {
  640. MonoIO.Close(stderr_wr, out error);
  641. process.error_stream=new StreamReader(new FileStream(stderr_rd, FileAccess.Read, true));
  642. }
  643. return(ret);
  644. }
  645. public bool Start() {
  646. bool ret;
  647. ret=Start_common(start_info, this);
  648. return(ret);
  649. }
  650. public static Process Start(ProcessStartInfo startInfo) {
  651. Process process=new Process();
  652. bool ret;
  653. ret=Start_common(startInfo, process);
  654. if(ret==true) {
  655. return(process);
  656. } else {
  657. return(null);
  658. }
  659. }
  660. public static Process Start(string fileName) {
  661. return Start(new ProcessStartInfo(fileName));
  662. }
  663. public static Process Start(string fileName,
  664. string arguments) {
  665. return Start(new ProcessStartInfo(fileName, arguments));
  666. }
  667. public override string ToString() {
  668. return(base.ToString() +
  669. " (" + this.ProcessName + ")");
  670. }
  671. /* Waits up to ms milliseconds for process 'handle' to
  672. * exit. ms can be <0 to mean wait forever.
  673. */
  674. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  675. private extern bool WaitForExit_internal(IntPtr handle,
  676. int ms);
  677. public void WaitForExit() {
  678. WaitForExit_internal(process_handle, -1);
  679. }
  680. public bool WaitForExit(int milliseconds) {
  681. if (milliseconds == int.MaxValue)
  682. milliseconds = -1;
  683. return WaitForExit_internal (process_handle, milliseconds);
  684. }
  685. [MonoTODO]
  686. public bool WaitForInputIdle() {
  687. return(false);
  688. }
  689. [MonoTODO]
  690. public bool WaitForInputIdle(int milliseconds) {
  691. return(false);
  692. }
  693. [Category ()]
  694. [MonitoringDescription ("Raised when this process exits.")]
  695. public event EventHandler Exited;
  696. // Closes the system process handle
  697. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  698. private extern void Process_free_internal(IntPtr handle);
  699. private bool disposed = false;
  700. protected override void Dispose(bool disposing) {
  701. // Check to see if Dispose has already been called.
  702. if(this.disposed) {
  703. this.disposed=true;
  704. // If this is a call to Dispose,
  705. // dispose all managed resources.
  706. if(disposing) {
  707. // Do stuff here
  708. }
  709. // Release unmanaged resources
  710. lock(this) {
  711. if(process_handle!=IntPtr.Zero) {
  712. Process_free_internal(process_handle);
  713. process_handle=IntPtr.Zero;
  714. }
  715. }
  716. }
  717. base.Dispose (disposing);
  718. }
  719. static void CBOnExit (object state, bool unused)
  720. {
  721. Process p = (Process) state;
  722. p.OnExited ();
  723. }
  724. protected void OnExited()
  725. {
  726. if (Exited != null)
  727. Exited (this, EventArgs.Empty);
  728. }
  729. class ProcessWaitHandle : WaitHandle
  730. {
  731. public ProcessWaitHandle (IntPtr handle)
  732. {
  733. Handle = handle;
  734. }
  735. }
  736. }
  737. }