Process.cs 26 KB

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