Process.cs 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614
  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,2005,2006 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.IO;
  34. using System.Text;
  35. using System.ComponentModel;
  36. using System.ComponentModel.Design;
  37. using System.Runtime.CompilerServices;
  38. using System.Runtime.InteropServices;
  39. using System.Runtime.Remoting.Messaging;
  40. using System.Security.Permissions;
  41. using System.Collections.Generic;
  42. using System.Security;
  43. using System.Threading;
  44. using Microsoft.Win32.SafeHandles;
  45. namespace System.Diagnostics {
  46. [DefaultEvent ("Exited"), DefaultProperty ("StartInfo")]
  47. [Designer ("System.Diagnostics.Design.ProcessDesigner, " + Consts.AssemblySystem_Design)]
  48. [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
  49. [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
  50. [MonitoringDescription ("Represents a system process")]
  51. public class Process : Component
  52. {
  53. [StructLayout(LayoutKind.Sequential)]
  54. private struct ProcInfo
  55. {
  56. public IntPtr process_handle;
  57. /* If thread_handle is ever needed for
  58. * something, take out the CloseHandle() in
  59. * the Start_internal icall in
  60. * mono/metadata/process.c
  61. */
  62. public IntPtr thread_handle;
  63. public int pid; // Contains -GetLastError () on failure.
  64. public int tid;
  65. public string [] envKeys;
  66. public string [] envValues;
  67. public string UserName;
  68. public string Domain;
  69. public IntPtr Password;
  70. public bool LoadUserProfile;
  71. };
  72. IntPtr process_handle;
  73. int pid;
  74. int enable_raising_events;
  75. Thread background_wait_for_exit_thread;
  76. ISynchronizeInvoke synchronizingObject;
  77. EventHandler exited_event;
  78. /* Private constructor called from other methods */
  79. private Process(IntPtr handle, int id) {
  80. process_handle = handle;
  81. pid=id;
  82. }
  83. public Process ()
  84. {
  85. }
  86. [MonoTODO]
  87. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  88. [MonitoringDescription ("Base process priority.")]
  89. public int BasePriority {
  90. get { return 0; }
  91. }
  92. [DefaultValue (false), Browsable (false)]
  93. [MonitoringDescription ("Check for exiting of the process to raise the apropriate event.")]
  94. public bool EnableRaisingEvents {
  95. get {
  96. return enable_raising_events == 1;
  97. }
  98. set {
  99. if (value && Interlocked.Exchange (ref enable_raising_events, 1) == 0)
  100. StartBackgroundWaitForExit ();
  101. }
  102. }
  103. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  104. private extern static int ExitCode_internal(IntPtr handle);
  105. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  106. [MonitoringDescription ("The exit code of the process.")]
  107. public int ExitCode {
  108. get {
  109. if (process_handle == IntPtr.Zero)
  110. throw new InvalidOperationException ("Process has not been started.");
  111. int code = ExitCode_internal (process_handle);
  112. if (code == 259)
  113. throw new InvalidOperationException ("The process must exit before getting the requested information.");
  114. return code;
  115. }
  116. }
  117. /* Returns the process start time in Windows file
  118. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  119. */
  120. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  121. private extern static long ExitTime_internal(IntPtr handle);
  122. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  123. [MonitoringDescription ("The exit time of the process.")]
  124. public DateTime ExitTime {
  125. get {
  126. if (process_handle == IntPtr.Zero)
  127. throw new InvalidOperationException ("Process has not been started.");
  128. if (!HasExited)
  129. throw new InvalidOperationException ("The process must exit before " +
  130. "getting the requested information.");
  131. return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
  132. }
  133. }
  134. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  135. [MonitoringDescription ("Handle for this process.")]
  136. public IntPtr Handle {
  137. get {
  138. if (process_handle == IntPtr.Zero)
  139. throw new InvalidOperationException ("No process is associated with this object.");
  140. return(process_handle);
  141. }
  142. }
  143. [MonoTODO]
  144. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  145. [MonitoringDescription ("Handles for this process.")]
  146. public int HandleCount {
  147. get {
  148. return(0);
  149. }
  150. }
  151. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  152. [MonitoringDescription ("Determines if the process is still running.")]
  153. public bool HasExited {
  154. get {
  155. if (process_handle == IntPtr.Zero)
  156. throw new InvalidOperationException ("Process has not been started.");
  157. int exitcode = ExitCode_internal (process_handle);
  158. if(exitcode==259) {
  159. /* STILL_ACTIVE */
  160. return(false);
  161. } else {
  162. return(true);
  163. }
  164. }
  165. }
  166. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  167. [MonitoringDescription ("Process identifier.")]
  168. public int Id {
  169. get {
  170. if (pid == 0)
  171. throw new InvalidOperationException ("Process ID has not been set.");
  172. return(pid);
  173. }
  174. }
  175. [MonoTODO]
  176. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  177. [MonitoringDescription ("The name of the computer running the process.")]
  178. public string MachineName {
  179. get {
  180. return("localhost");
  181. }
  182. }
  183. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  184. [MonitoringDescription ("The main module of the process.")]
  185. public ProcessModule MainModule {
  186. get {
  187. return(this.Modules[0]);
  188. }
  189. }
  190. [MonoTODO]
  191. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  192. [MonitoringDescription ("The handle of the main window of the process.")]
  193. public IntPtr MainWindowHandle {
  194. get {
  195. return((IntPtr)0);
  196. }
  197. }
  198. [MonoTODO]
  199. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  200. [MonitoringDescription ("The title of the main window of the process.")]
  201. public string MainWindowTitle {
  202. get {
  203. return("null");
  204. }
  205. }
  206. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  207. private extern static bool GetWorkingSet_internal(IntPtr handle, out int min, out int max);
  208. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  209. private extern static bool SetWorkingSet_internal(IntPtr handle, int min, int max, bool use_min);
  210. /* LAMESPEC: why is this an IntPtr not a plain int? */
  211. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  212. [MonitoringDescription ("The maximum working set for this process.")]
  213. public IntPtr MaxWorkingSet {
  214. get {
  215. if(HasExited)
  216. throw new InvalidOperationException(
  217. "The process " + ProcessName +
  218. " (ID " + Id + ") has exited");
  219. int min;
  220. int max;
  221. bool ok=GetWorkingSet_internal(process_handle, out min, out max);
  222. if(ok==false) {
  223. throw new Win32Exception();
  224. }
  225. return((IntPtr)max);
  226. }
  227. set {
  228. if(HasExited) {
  229. throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
  230. }
  231. bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
  232. if(ok==false) {
  233. throw new Win32Exception();
  234. }
  235. }
  236. }
  237. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  238. [MonitoringDescription ("The minimum working set for this process.")]
  239. public IntPtr MinWorkingSet {
  240. get {
  241. if(HasExited)
  242. throw new InvalidOperationException(
  243. "The process " + ProcessName +
  244. " (ID " + Id + ") has exited");
  245. int min;
  246. int max;
  247. bool ok= GetWorkingSet_internal (process_handle, out min, out max);
  248. if(!ok)
  249. throw new Win32Exception();
  250. return ((IntPtr) min);
  251. }
  252. set {
  253. if(HasExited)
  254. throw new InvalidOperationException(
  255. "The process " + ProcessName +
  256. " (ID " + Id + ") has exited");
  257. bool ok = SetWorkingSet_internal (process_handle, value.ToInt32(), 0, true);
  258. if (!ok)
  259. throw new Win32Exception();
  260. }
  261. }
  262. /* Returns the list of process modules. The main module is
  263. * element 0.
  264. */
  265. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  266. private extern ProcessModule[] GetModules_internal(IntPtr handle);
  267. private ProcessModuleCollection module_collection;
  268. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  269. [MonitoringDescription ("The modules that are loaded as part of this process.")]
  270. public ProcessModuleCollection Modules {
  271. get {
  272. if (module_collection == null)
  273. module_collection = new ProcessModuleCollection(
  274. GetModules_internal (process_handle));
  275. return(module_collection);
  276. }
  277. }
  278. /* data type is from the MonoProcessData enum in mono-proclib.h in the runtime */
  279. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  280. private extern static long GetProcessData (int pid, int data_type, out int error);
  281. [MonoTODO]
  282. [Obsolete ("Use NonpagedSystemMemorySize64")]
  283. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  284. [MonitoringDescription ("The number of bytes that are not pageable.")]
  285. public int NonpagedSystemMemorySize {
  286. get {
  287. return(0);
  288. }
  289. }
  290. [Obsolete ("Use PagedMemorySize64")]
  291. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  292. [MonitoringDescription ("The number of bytes that are paged.")]
  293. public int PagedMemorySize {
  294. get {
  295. return(int)PagedMemorySize64;
  296. }
  297. }
  298. [Obsolete ("Use PagedSystemMemorySize64")]
  299. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  300. [MonitoringDescription ("The amount of paged system memory in bytes.")]
  301. public int PagedSystemMemorySize {
  302. get {
  303. return(int)PagedMemorySize64;
  304. }
  305. }
  306. [MonoTODO]
  307. [Obsolete ("Use PeakPagedMemorySize64")]
  308. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  309. [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
  310. public int PeakPagedMemorySize {
  311. get {
  312. return(0);
  313. }
  314. }
  315. [Obsolete ("Use PeakVirtualMemorySize64")]
  316. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  317. [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
  318. public int PeakVirtualMemorySize {
  319. get {
  320. int error;
  321. return (int)GetProcessData (pid, 8, out error);
  322. }
  323. }
  324. [Obsolete ("Use PeakWorkingSet64")]
  325. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  326. [MonitoringDescription ("The maximum amount of system memory used by this process.")]
  327. public int PeakWorkingSet {
  328. get {
  329. int error;
  330. return (int)GetProcessData (pid, 5, out error);
  331. }
  332. }
  333. [MonoTODO]
  334. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  335. [MonitoringDescription ("The number of bytes that are not pageable.")]
  336. [ComVisible (false)]
  337. public long NonpagedSystemMemorySize64 {
  338. get {
  339. return(0);
  340. }
  341. }
  342. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  343. [MonitoringDescription ("The number of bytes that are paged.")]
  344. [ComVisible (false)]
  345. public long PagedMemorySize64 {
  346. get {
  347. int error;
  348. return GetProcessData (pid, 12, out error);
  349. }
  350. }
  351. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  352. [MonitoringDescription ("The amount of paged system memory in bytes.")]
  353. [ComVisible (false)]
  354. public long PagedSystemMemorySize64 {
  355. get {
  356. return PagedMemorySize64;
  357. }
  358. }
  359. [MonoTODO]
  360. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  361. [MonitoringDescription ("The maximum amount of paged memory used by this process.")]
  362. [ComVisible (false)]
  363. public long PeakPagedMemorySize64 {
  364. get {
  365. return(0);
  366. }
  367. }
  368. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  369. [MonitoringDescription ("The maximum amount of virtual memory used by this process.")]
  370. [ComVisible (false)]
  371. public long PeakVirtualMemorySize64 {
  372. get {
  373. int error;
  374. return GetProcessData (pid, 8, out error);
  375. }
  376. }
  377. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  378. [MonitoringDescription ("The maximum amount of system memory used by this process.")]
  379. [ComVisible (false)]
  380. public long PeakWorkingSet64 {
  381. get {
  382. int error;
  383. return GetProcessData (pid, 5, out error);
  384. }
  385. }
  386. [MonoTODO]
  387. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  388. [MonitoringDescription ("Process will be of higher priority while it is actively used.")]
  389. public bool PriorityBoostEnabled {
  390. get {
  391. return(false);
  392. }
  393. set {
  394. }
  395. }
  396. [MonoLimitation ("Under Unix, only root is allowed to raise the priority.")]
  397. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  398. [MonitoringDescription ("The relative process priority.")]
  399. public ProcessPriorityClass PriorityClass {
  400. get {
  401. if (process_handle == IntPtr.Zero)
  402. throw new InvalidOperationException ("Process has not been started.");
  403. int error;
  404. int prio = GetPriorityClass (process_handle, out error);
  405. if (prio == 0)
  406. throw new Win32Exception (error);
  407. return (ProcessPriorityClass) prio;
  408. }
  409. set {
  410. if (!Enum.IsDefined (typeof (ProcessPriorityClass), value))
  411. throw new InvalidEnumArgumentException (
  412. "value", (int) value,
  413. typeof (ProcessPriorityClass));
  414. if (process_handle == IntPtr.Zero)
  415. throw new InvalidOperationException ("Process has not been started.");
  416. int error;
  417. if (!SetPriorityClass (process_handle, (int) value, out error)) {
  418. CheckExited ();
  419. throw new Win32Exception (error);
  420. }
  421. }
  422. }
  423. void CheckExited () {
  424. if (HasExited)
  425. throw new InvalidOperationException (String.Format ("Cannot process request because the process ({0}) has exited.", Id));
  426. }
  427. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  428. static extern int GetPriorityClass (IntPtr handle, out int error);
  429. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  430. static extern bool SetPriorityClass (IntPtr handle, int priority, out int error);
  431. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  432. [MonitoringDescription ("The amount of memory exclusively used by this process.")]
  433. [Obsolete ("Use PrivateMemorySize64")]
  434. public int PrivateMemorySize {
  435. get {
  436. int error;
  437. return (int)GetProcessData (pid, 6, out error);
  438. }
  439. }
  440. [MonoNotSupported ("")]
  441. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  442. [MonitoringDescription ("The session ID for this process.")]
  443. public int SessionId {
  444. get { throw new NotImplementedException (); }
  445. }
  446. /* the meaning of type is as follows: 0: user, 1: system, 2: total */
  447. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  448. private extern static long Times (IntPtr handle, int type);
  449. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  450. [MonitoringDescription ("The amount of processing time spent in the OS core for this process.")]
  451. public TimeSpan PrivilegedProcessorTime {
  452. get {
  453. return new TimeSpan (Times (process_handle, 1));
  454. }
  455. }
  456. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  457. private extern static string ProcessName_internal(IntPtr handle);
  458. private string process_name=null;
  459. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  460. [MonitoringDescription ("The name of this process.")]
  461. public string ProcessName {
  462. get {
  463. if(process_name==null) {
  464. if (process_handle == IntPtr.Zero)
  465. throw new InvalidOperationException ("No process is associated with this object.");
  466. process_name=ProcessName_internal(process_handle);
  467. /* If process_name is _still_
  468. * null, assume the process
  469. * has exited
  470. */
  471. if (process_name == null)
  472. throw new InvalidOperationException ("Process has exited, so the requested information is not available.");
  473. /* Strip the suffix (if it
  474. * exists) simplistically
  475. * instead of removing any
  476. * trailing \.???, so we dont
  477. * get stupid results on sane
  478. * systems
  479. */
  480. if(process_name.EndsWith(".exe") ||
  481. process_name.EndsWith(".bat") ||
  482. process_name.EndsWith(".com")) {
  483. process_name=process_name.Substring(0, process_name.Length-4);
  484. }
  485. }
  486. return(process_name);
  487. }
  488. }
  489. [MonoTODO]
  490. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  491. [MonitoringDescription ("Allowed processor that can be used by this process.")]
  492. public IntPtr ProcessorAffinity {
  493. get {
  494. return((IntPtr)0);
  495. }
  496. set {
  497. }
  498. }
  499. [MonoTODO]
  500. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  501. [MonitoringDescription ("Is this process responsive.")]
  502. public bool Responding {
  503. get {
  504. return(false);
  505. }
  506. }
  507. #if MONO_FEATURE_PROCESS_START
  508. private StreamReader error_stream=null;
  509. bool error_stream_exposed;
  510. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  511. [MonitoringDescription ("The standard error stream of this process.")]
  512. public StreamReader StandardError {
  513. get {
  514. if (error_stream == null)
  515. throw new InvalidOperationException("Standard error has not been redirected");
  516. if ((async_mode & AsyncModes.AsyncError) != 0)
  517. throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
  518. async_mode |= AsyncModes.SyncError;
  519. error_stream_exposed = true;
  520. return(error_stream);
  521. }
  522. }
  523. private StreamWriter input_stream=null;
  524. bool input_stream_exposed;
  525. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  526. [MonitoringDescription ("The standard input stream of this process.")]
  527. public StreamWriter StandardInput {
  528. get {
  529. if (input_stream == null)
  530. throw new InvalidOperationException("Standard input has not been redirected");
  531. input_stream_exposed = true;
  532. return(input_stream);
  533. }
  534. }
  535. private StreamReader output_stream=null;
  536. bool output_stream_exposed;
  537. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden), Browsable (false)]
  538. [MonitoringDescription ("The standard output stream of this process.")]
  539. public StreamReader StandardOutput {
  540. get {
  541. if (output_stream == null)
  542. throw new InvalidOperationException("Standard output has not been redirected");
  543. if ((async_mode & AsyncModes.AsyncOutput) != 0)
  544. throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
  545. async_mode |= AsyncModes.SyncOutput;
  546. output_stream_exposed = true;
  547. return(output_stream);
  548. }
  549. }
  550. private ProcessStartInfo start_info=null;
  551. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content), Browsable (false)]
  552. [MonitoringDescription ("Information for the start of this process.")]
  553. public ProcessStartInfo StartInfo {
  554. get {
  555. if (start_info == null)
  556. start_info = new ProcessStartInfo();
  557. return start_info;
  558. }
  559. set {
  560. if (value == null)
  561. throw new ArgumentNullException("value");
  562. start_info = value;
  563. }
  564. }
  565. #else
  566. [Obsolete ("Process.StandardError is not supported on the current platform.", true)]
  567. public StreamReader StandardError {
  568. get { throw new PlatformNotSupportedException ("Process.StandardError is not supported on the current platform."); }
  569. }
  570. [Obsolete ("Process.StandardInput is not supported on the current platform.", true)]
  571. public StreamWriter StandardInput {
  572. get { throw new PlatformNotSupportedException ("Process.StandardInput is not supported on the current platform."); }
  573. }
  574. [Obsolete ("Process.StandardOutput is not supported on the current platform.", true)]
  575. public StreamReader StandardOutput {
  576. get { throw new PlatformNotSupportedException ("Process.StandardOutput is not supported on the current platform."); }
  577. }
  578. [Obsolete ("Process.StartInfo is not supported on the current platform.", true)]
  579. public ProcessStartInfo StartInfo {
  580. get { throw new PlatformNotSupportedException ("Process.StartInfo is not supported on the current platform."); }
  581. set { throw new PlatformNotSupportedException ("Process.StartInfo is not supported on the current platform."); }
  582. }
  583. #endif // MONO_FEATURE_PROCESS_START
  584. /* Returns the process start time in Windows file
  585. * times (ticks from DateTime(1/1/1601 00:00 GMT))
  586. */
  587. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  588. private extern static long StartTime_internal(IntPtr handle);
  589. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  590. [MonitoringDescription ("The time this process started.")]
  591. public DateTime StartTime {
  592. get {
  593. return(DateTime.FromFileTime(StartTime_internal(process_handle)));
  594. }
  595. }
  596. [DefaultValue (null), Browsable (false)]
  597. [MonitoringDescription ("The object that is used to synchronize event handler calls for this process.")]
  598. public ISynchronizeInvoke SynchronizingObject {
  599. get { return synchronizingObject; }
  600. set { synchronizingObject = value; }
  601. }
  602. [MonoTODO]
  603. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  604. [MonitoringDescription ("The number of threads of this process.")]
  605. public ProcessThreadCollection Threads {
  606. get {
  607. // This'll return a correctly-sized array of empty ProcessThreads for now.
  608. int error;
  609. return new ProcessThreadCollection(new ProcessThread[GetProcessData (pid, 0, out error)]);
  610. }
  611. }
  612. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  613. [MonitoringDescription ("The total CPU time spent for this process.")]
  614. public TimeSpan TotalProcessorTime {
  615. get {
  616. return new TimeSpan (Times (process_handle, 2));
  617. }
  618. }
  619. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  620. [MonitoringDescription ("The CPU time spent for this process in user mode.")]
  621. public TimeSpan UserProcessorTime {
  622. get {
  623. return new TimeSpan (Times (process_handle, 0));
  624. }
  625. }
  626. [Obsolete ("Use VirtualMemorySize64")]
  627. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  628. [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
  629. public int VirtualMemorySize {
  630. get {
  631. int error;
  632. return (int)GetProcessData (pid, 7, out error);
  633. }
  634. }
  635. [Obsolete ("Use WorkingSet64")]
  636. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  637. [MonitoringDescription ("The amount of physical memory currently used for this process.")]
  638. public int WorkingSet {
  639. get {
  640. int error;
  641. return (int)GetProcessData (pid, 4, out error);
  642. }
  643. }
  644. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  645. [MonitoringDescription ("The amount of memory exclusively used by this process.")]
  646. [ComVisible (false)]
  647. public long PrivateMemorySize64 {
  648. get {
  649. int error;
  650. return GetProcessData (pid, 6, out error);
  651. }
  652. }
  653. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  654. [MonitoringDescription ("The amount of virtual memory currently used for this process.")]
  655. [ComVisible (false)]
  656. public long VirtualMemorySize64 {
  657. get {
  658. int error;
  659. return GetProcessData (pid, 7, out error);
  660. }
  661. }
  662. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  663. [MonitoringDescription ("The amount of physical memory currently used for this process.")]
  664. [ComVisible (false)]
  665. public long WorkingSet64 {
  666. get {
  667. int error;
  668. return GetProcessData (pid, 4, out error);
  669. }
  670. }
  671. public void Close()
  672. {
  673. Dispose (true);
  674. }
  675. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  676. extern static bool Kill_internal (IntPtr handle, int signo);
  677. /* int kill -> 1 KILL, 2 CloseMainWindow */
  678. bool Close (int signo)
  679. {
  680. if (process_handle == IntPtr.Zero)
  681. throw new SystemException ("No process to kill.");
  682. int exitcode = ExitCode_internal (process_handle);
  683. if (exitcode != 259)
  684. throw new InvalidOperationException ("The process already finished.");
  685. return Kill_internal (process_handle, signo);
  686. }
  687. public bool CloseMainWindow ()
  688. {
  689. return Close (2);
  690. }
  691. [MonoTODO]
  692. public static void EnterDebugMode() {
  693. }
  694. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  695. private extern static IntPtr GetProcess_internal(int pid);
  696. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  697. private extern static int GetPid_internal();
  698. public static Process GetCurrentProcess()
  699. {
  700. int pid = GetPid_internal();
  701. IntPtr proc = GetProcess_internal(pid);
  702. if (proc == IntPtr.Zero)
  703. throw new SystemException("Can't find current process");
  704. return (new Process (proc, pid));
  705. }
  706. public static Process GetProcessById(int processId)
  707. {
  708. IntPtr proc = GetProcess_internal(processId);
  709. if (proc == IntPtr.Zero)
  710. throw new ArgumentException ("Can't find process with ID " + processId.ToString ());
  711. return (new Process (proc, processId));
  712. }
  713. [MonoTODO ("There is no support for retrieving process information from a remote machine")]
  714. public static Process GetProcessById(int processId, string machineName) {
  715. if (machineName == null)
  716. throw new ArgumentNullException ("machineName");
  717. if (!IsLocalMachine (machineName))
  718. throw new NotImplementedException ();
  719. return GetProcessById (processId);
  720. }
  721. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  722. private extern static int[] GetProcesses_internal();
  723. public static Process[] GetProcesses ()
  724. {
  725. int [] pids = GetProcesses_internal ();
  726. if (pids == null)
  727. return new Process [0];
  728. var proclist = new List<Process> (pids.Length);
  729. for (int i = 0; i < pids.Length; i++) {
  730. try {
  731. proclist.Add (GetProcessById (pids [i]));
  732. } catch (SystemException) {
  733. /* The process might exit
  734. * between
  735. * GetProcesses_internal and
  736. * GetProcessById
  737. */
  738. }
  739. }
  740. return proclist.ToArray ();
  741. }
  742. [MonoTODO ("There is no support for retrieving process information from a remote machine")]
  743. public static Process[] GetProcesses(string machineName) {
  744. if (machineName == null)
  745. throw new ArgumentNullException ("machineName");
  746. if (!IsLocalMachine (machineName))
  747. throw new NotImplementedException ();
  748. return GetProcesses ();
  749. }
  750. public static Process[] GetProcessesByName(string processName)
  751. {
  752. int [] pids = GetProcesses_internal ();
  753. if (pids == null)
  754. return new Process [0];
  755. var proclist = new List<Process> (pids.Length);
  756. for (int i = 0; i < pids.Length; i++) {
  757. try {
  758. Process p = GetProcessById (pids [i]);
  759. if (String.Compare (processName, p.ProcessName, true) == 0)
  760. proclist.Add (p);
  761. } catch (SystemException) {
  762. /* The process might exit
  763. * between
  764. * GetProcesses_internal and
  765. * GetProcessById
  766. */
  767. }
  768. }
  769. return proclist.ToArray ();
  770. }
  771. [MonoTODO]
  772. public static Process[] GetProcessesByName(string processName, string machineName) {
  773. throw new NotImplementedException();
  774. }
  775. public void Kill ()
  776. {
  777. Close (1);
  778. }
  779. [MonoTODO]
  780. public static void LeaveDebugMode() {
  781. }
  782. public void Refresh ()
  783. {
  784. // FIXME: should refresh any cached data we might have about
  785. // the process (currently we have none).
  786. }
  787. #if MONO_FEATURE_PROCESS_START
  788. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  789. private extern static bool ShellExecuteEx_internal(ProcessStartInfo startInfo,
  790. ref ProcInfo proc_info);
  791. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  792. private extern static bool CreateProcess_internal(ProcessStartInfo startInfo,
  793. IntPtr stdin,
  794. IntPtr stdout,
  795. IntPtr stderr,
  796. ref ProcInfo proc_info);
  797. private static bool Start_shell (ProcessStartInfo startInfo, Process process)
  798. {
  799. ProcInfo proc_info=new ProcInfo();
  800. bool ret;
  801. if (startInfo.RedirectStandardInput ||
  802. startInfo.RedirectStandardOutput ||
  803. startInfo.RedirectStandardError) {
  804. throw new InvalidOperationException ("UseShellExecute must be false when redirecting I/O.");
  805. }
  806. if (startInfo.HaveEnvVars)
  807. throw new InvalidOperationException ("UseShellExecute must be false in order to use environment variables.");
  808. FillUserInfo (startInfo, ref proc_info);
  809. try {
  810. ret = ShellExecuteEx_internal (startInfo,
  811. ref proc_info);
  812. } finally {
  813. if (proc_info.Password != IntPtr.Zero)
  814. Marshal.ZeroFreeBSTR (proc_info.Password);
  815. proc_info.Password = IntPtr.Zero;
  816. }
  817. if (!ret) {
  818. throw new Win32Exception (-proc_info.pid);
  819. }
  820. process.process_handle = proc_info.process_handle;
  821. process.pid = proc_info.pid;
  822. process.StartBackgroundWaitForExit ();
  823. return(ret);
  824. }
  825. //
  826. // Creates a pipe with read and write descriptors
  827. //
  828. static void CreatePipe (out IntPtr read, out IntPtr write, bool writeDirection)
  829. {
  830. MonoIOError error;
  831. //
  832. // Creates read/write pipe from parent -> child perspective
  833. // a child process uses same descriptors after fork. That's
  834. // 4 descriptors in total where only 2. One in child, one in parent
  835. // should be active and the other 2 closed. Which ones depends on
  836. // comunication direction
  837. //
  838. // parent --------> child (parent can write, child can read)
  839. //
  840. // read: closed read: used
  841. // write: used write: closed
  842. //
  843. //
  844. // parent <-------- child (parent can read, child can write)
  845. //
  846. // read: used read: closed
  847. // write: closed write: used
  848. //
  849. // It can still be tricky for predefined descriptiors http://unixwiz.net/techtips/remap-pipe-fds.html
  850. //
  851. if (!MonoIO.CreatePipe (out read, out write, out error))
  852. throw MonoIO.GetException (error);
  853. if (IsWindows) {
  854. const int DUPLICATE_SAME_ACCESS = 0x00000002;
  855. var tmp = writeDirection ? write : read;
  856. if (!MonoIO.DuplicateHandle (Process.GetCurrentProcess ().Handle, tmp, Process.GetCurrentProcess ().Handle, out tmp, 0, 0, DUPLICATE_SAME_ACCESS, out error))
  857. throw MonoIO.GetException (error);
  858. if (writeDirection) {
  859. if (!MonoIO.Close (write, out error))
  860. throw MonoIO.GetException (error);
  861. write = tmp;
  862. } else {
  863. if (!MonoIO.Close (read, out error))
  864. throw MonoIO.GetException (error);
  865. read = tmp;
  866. }
  867. }
  868. }
  869. static bool Start_noshell (ProcessStartInfo startInfo, Process process)
  870. {
  871. var proc_info = new ProcInfo ();
  872. if (startInfo.HaveEnvVars) {
  873. string [] strs = new string [startInfo.EnvironmentVariables.Count];
  874. startInfo.EnvironmentVariables.Keys.CopyTo (strs, 0);
  875. proc_info.envKeys = strs;
  876. strs = new string [startInfo.EnvironmentVariables.Count];
  877. startInfo.EnvironmentVariables.Values.CopyTo (strs, 0);
  878. proc_info.envValues = strs;
  879. }
  880. MonoIOError error;
  881. IntPtr stdin_read = IntPtr.Zero, stdin_write = IntPtr.Zero;
  882. IntPtr stdout_read = IntPtr.Zero, stdout_write = IntPtr.Zero;
  883. IntPtr stderr_read = IntPtr.Zero, stderr_write = IntPtr.Zero;
  884. try {
  885. if (startInfo.RedirectStandardInput) {
  886. CreatePipe (out stdin_read, out stdin_write, true);
  887. } else {
  888. stdin_read = MonoIO.ConsoleInput;
  889. stdin_write = IntPtr.Zero;
  890. }
  891. if (startInfo.RedirectStandardOutput) {
  892. CreatePipe (out stdout_read, out stdout_write, false);
  893. } else {
  894. stdout_read = IntPtr.Zero;
  895. stdout_write = MonoIO.ConsoleOutput;
  896. }
  897. if (startInfo.RedirectStandardError) {
  898. CreatePipe (out stderr_read, out stderr_write, false);
  899. } else {
  900. stderr_read = IntPtr.Zero;
  901. stderr_write = MonoIO.ConsoleError;
  902. }
  903. FillUserInfo (startInfo, ref proc_info);
  904. //
  905. // FIXME: For redirected pipes we need to send descriptors of
  906. // stdin_write, stdout_read, stderr_read to child process and
  907. // close them there (fork makes exact copy of parent's descriptors)
  908. //
  909. if (!CreateProcess_internal (startInfo, stdin_read, stdout_write, stderr_write, ref proc_info)) {
  910. throw new Win32Exception (-proc_info.pid,
  911. "ApplicationName='" + startInfo.FileName +
  912. "', CommandLine='" + startInfo.Arguments +
  913. "', CurrentDirectory='" + startInfo.WorkingDirectory +
  914. "', Native error= " + Win32Exception.W32ErrorMessage (-proc_info.pid));
  915. }
  916. } catch {
  917. if (startInfo.RedirectStandardInput) {
  918. if (stdin_read != IntPtr.Zero)
  919. MonoIO.Close (stdin_read, out error);
  920. if (stdin_write != IntPtr.Zero)
  921. MonoIO.Close (stdin_write, out error);
  922. }
  923. if (startInfo.RedirectStandardOutput) {
  924. if (stdout_read != IntPtr.Zero)
  925. MonoIO.Close (stdout_read, out error);
  926. if (stdout_write != IntPtr.Zero)
  927. MonoIO.Close (stdout_write, out error);
  928. }
  929. if (startInfo.RedirectStandardError) {
  930. if (stderr_read != IntPtr.Zero)
  931. MonoIO.Close (stderr_read, out error);
  932. if (stderr_write != IntPtr.Zero)
  933. MonoIO.Close (stderr_write, out error);
  934. }
  935. throw;
  936. } finally {
  937. if (proc_info.Password != IntPtr.Zero) {
  938. Marshal.ZeroFreeBSTR (proc_info.Password);
  939. proc_info.Password = IntPtr.Zero;
  940. }
  941. }
  942. process.process_handle = proc_info.process_handle;
  943. process.pid = proc_info.pid;
  944. if (startInfo.RedirectStandardInput) {
  945. //
  946. // FIXME: The descriptor needs to be closed but due to wapi io-layer
  947. // not coping with duplicated descriptors any StandardInput write fails
  948. //
  949. // MonoIO.Close (stdin_read, out error);
  950. #if MOBILE
  951. var stdinEncoding = Encoding.Default;
  952. #else
  953. var stdinEncoding = Console.InputEncoding;
  954. #endif
  955. process.input_stream = new StreamWriter (new FileStream (stdin_write, FileAccess.Write, true, 8192), stdinEncoding) {
  956. AutoFlush = true
  957. };
  958. }
  959. if (startInfo.RedirectStandardOutput) {
  960. MonoIO.Close (stdout_write, out error);
  961. Encoding stdoutEncoding = startInfo.StandardOutputEncoding ?? Console.Out.Encoding;
  962. process.output_stream = new StreamReader (new FileStream (stdout_read, FileAccess.Read, true, 8192), stdoutEncoding, true);
  963. }
  964. if (startInfo.RedirectStandardError) {
  965. MonoIO.Close (stderr_write, out error);
  966. Encoding stderrEncoding = startInfo.StandardErrorEncoding ?? Console.Out.Encoding;
  967. process.error_stream = new StreamReader (new FileStream (stderr_read, FileAccess.Read, true, 8192), stderrEncoding, true);
  968. }
  969. process.StartBackgroundWaitForExit ();
  970. return true;
  971. }
  972. // Note that ProcInfo.Password must be freed.
  973. private static void FillUserInfo (ProcessStartInfo startInfo, ref ProcInfo proc_info)
  974. {
  975. if (startInfo.UserName.Length != 0) {
  976. proc_info.UserName = startInfo.UserName;
  977. proc_info.Domain = startInfo.Domain;
  978. if (startInfo.Password != null)
  979. proc_info.Password = Marshal.SecureStringToBSTR (startInfo.Password);
  980. else
  981. proc_info.Password = IntPtr.Zero;
  982. proc_info.LoadUserProfile = startInfo.LoadUserProfile;
  983. }
  984. }
  985. private static bool Start_common (ProcessStartInfo startInfo,
  986. Process process)
  987. {
  988. if (startInfo.FileName.Length == 0)
  989. throw new InvalidOperationException("File name has not been set");
  990. if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError)
  991. throw new InvalidOperationException ("StandardErrorEncoding is only supported when standard error is redirected");
  992. if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput)
  993. throw new InvalidOperationException ("StandardOutputEncoding is only supported when standard output is redirected");
  994. if (startInfo.UseShellExecute) {
  995. if (startInfo.UserName.Length != 0)
  996. throw new InvalidOperationException ("UseShellExecute must be false if an explicit UserName is specified when starting a process");
  997. return (Start_shell (startInfo, process));
  998. } else {
  999. return (Start_noshell (startInfo, process));
  1000. }
  1001. }
  1002. public bool Start ()
  1003. {
  1004. if (process_handle != IntPtr.Zero) {
  1005. Process_free_internal (process_handle);
  1006. process_handle = IntPtr.Zero;
  1007. }
  1008. return Start_common(start_info, this);
  1009. }
  1010. public static Process Start (ProcessStartInfo startInfo)
  1011. {
  1012. if (startInfo == null)
  1013. throw new ArgumentNullException ("startInfo");
  1014. Process process = new Process();
  1015. process.StartInfo = startInfo;
  1016. if (Start_common(startInfo, process) && process.process_handle != IntPtr.Zero)
  1017. return process;
  1018. return null;
  1019. }
  1020. public static Process Start (string fileName)
  1021. {
  1022. return Start (new ProcessStartInfo (fileName));
  1023. }
  1024. public static Process Start(string fileName, string arguments)
  1025. {
  1026. return Start (new ProcessStartInfo (fileName, arguments));
  1027. }
  1028. public static Process Start(string fileName, string username, SecureString password, string domain) {
  1029. return Start(fileName, null, username, password, domain);
  1030. }
  1031. public static Process Start(string fileName, string arguments, string username, SecureString password, string domain) {
  1032. ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments);
  1033. psi.UserName = username;
  1034. psi.Password = password;
  1035. psi.Domain = domain;
  1036. psi.UseShellExecute = false;
  1037. return Start(psi);
  1038. }
  1039. #else
  1040. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1041. public bool Start ()
  1042. {
  1043. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1044. }
  1045. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1046. public static Process Start (ProcessStartInfo startInfo)
  1047. {
  1048. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1049. }
  1050. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1051. public static Process Start (string fileName)
  1052. {
  1053. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1054. }
  1055. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1056. public static Process Start(string fileName, string arguments)
  1057. {
  1058. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1059. }
  1060. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1061. public static Process Start(string fileName, string username, SecureString password, string domain)
  1062. {
  1063. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1064. }
  1065. [Obsolete ("Process.Start is not supported on the current platform.", true)]
  1066. public static Process Start(string fileName, string arguments, string username, SecureString password, string domain)
  1067. {
  1068. throw new PlatformNotSupportedException ("Process.Start is not supported on the current platform.");
  1069. }
  1070. #endif // MONO_FEATURE_PROCESS_START
  1071. public override string ToString()
  1072. {
  1073. return(base.ToString() + " (" + this.ProcessName + ")");
  1074. }
  1075. /* Waits up to ms milliseconds for process 'handle' to
  1076. * exit. ms can be <0 to mean wait forever.
  1077. */
  1078. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1079. private extern bool WaitForExit_internal(IntPtr handle, int ms);
  1080. public void WaitForExit ()
  1081. {
  1082. WaitForExit (-1);
  1083. }
  1084. public bool WaitForExit(int milliseconds) {
  1085. int ms = milliseconds;
  1086. if (ms == int.MaxValue)
  1087. ms = -1;
  1088. if (process_handle == IntPtr.Zero)
  1089. throw new InvalidOperationException ("No process is associated with this object.");
  1090. if (!WaitForExit_internal (process_handle, ms))
  1091. return false;
  1092. #if MONO_FEATURE_PROCESS_START
  1093. if (async_output != null)
  1094. async_output.WaitUtilEOF ();
  1095. if (async_error != null)
  1096. async_error.WaitUtilEOF ();
  1097. #endif // MONO_FEATURE_PROCESS_START
  1098. if (EnableRaisingEvents)
  1099. OnExited ();
  1100. return true;
  1101. }
  1102. /* Waits up to ms milliseconds for process 'handle' to
  1103. * wait for input. ms can be <0 to mean wait forever.
  1104. */
  1105. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1106. private extern bool WaitForInputIdle_internal(IntPtr handle, int ms);
  1107. // The internal call is only implemented properly on Windows.
  1108. [MonoTODO]
  1109. public bool WaitForInputIdle() {
  1110. return WaitForInputIdle (-1);
  1111. }
  1112. // The internal call is only implemented properly on Windows.
  1113. [MonoTODO]
  1114. public bool WaitForInputIdle(int milliseconds) {
  1115. return WaitForInputIdle_internal (process_handle, milliseconds);
  1116. }
  1117. private static bool IsLocalMachine (string machineName)
  1118. {
  1119. if (machineName == "." || machineName.Length == 0)
  1120. return true;
  1121. return (string.Compare (machineName, Environment.MachineName, true) == 0);
  1122. }
  1123. [Browsable (true)]
  1124. [MonitoringDescription ("Raised when it receives output data")]
  1125. public event DataReceivedEventHandler OutputDataReceived;
  1126. [Browsable (true)]
  1127. [MonitoringDescription ("Raised when it receives error data")]
  1128. public event DataReceivedEventHandler ErrorDataReceived;
  1129. #if MONO_FEATURE_PROCESS_START
  1130. [Flags]
  1131. enum AsyncModes {
  1132. NoneYet = 0,
  1133. SyncOutput = 1,
  1134. SyncError = 1 << 1,
  1135. AsyncOutput = 1 << 2,
  1136. AsyncError = 1 << 3
  1137. }
  1138. AsyncModes async_mode;
  1139. AsyncStreamReader async_output;
  1140. AsyncStreamReader async_error;
  1141. [ComVisibleAttribute(false)]
  1142. public void BeginOutputReadLine ()
  1143. {
  1144. if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false)
  1145. throw new InvalidOperationException ("Standard output has not been redirected or process has not been started.");
  1146. if ((async_mode & AsyncModes.SyncOutput) != 0)
  1147. throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
  1148. async_mode |= AsyncModes.AsyncOutput;
  1149. if (async_output == null)
  1150. async_output = new AsyncStreamReader (this, output_stream.BaseStream, new UserCallBack(this.OutputReadNotifyUser), output_stream.CurrentEncoding);
  1151. async_output.BeginReadLine ();
  1152. }
  1153. void OutputReadNotifyUser (String data)
  1154. {
  1155. // To avoid ---- between remove handler and raising the event
  1156. DataReceivedEventHandler outputDataReceived = OutputDataReceived;
  1157. if (outputDataReceived != null) {
  1158. if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
  1159. SynchronizingObject.Invoke (outputDataReceived, new object[] { this, new DataReceivedEventArgs (data) });
  1160. else
  1161. outputDataReceived (this, new DataReceivedEventArgs (data)); // Call back to user informing data is available.
  1162. }
  1163. }
  1164. [ComVisibleAttribute(false)]
  1165. public void CancelOutputRead ()
  1166. {
  1167. if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false)
  1168. throw new InvalidOperationException ("Standard output has not been redirected or process has not been started.");
  1169. if ((async_mode & AsyncModes.SyncOutput) != 0)
  1170. throw new InvalidOperationException ("OutputStream is not enabled for asynchronous read operations.");
  1171. if (async_output == null)
  1172. throw new InvalidOperationException ("No async operation in progress.");
  1173. async_output.CancelOperation ();
  1174. async_mode &= ~AsyncModes.AsyncOutput;
  1175. }
  1176. [ComVisibleAttribute(false)]
  1177. public void BeginErrorReadLine ()
  1178. {
  1179. if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false)
  1180. throw new InvalidOperationException ("Standard error has not been redirected or process has not been started.");
  1181. if ((async_mode & AsyncModes.SyncError) != 0)
  1182. throw new InvalidOperationException ("Cannot mix asynchronous and synchonous reads.");
  1183. async_mode |= AsyncModes.AsyncError;
  1184. if (async_error == null)
  1185. async_error = new AsyncStreamReader (this, error_stream.BaseStream, new UserCallBack(this.ErrorReadNotifyUser), error_stream.CurrentEncoding);
  1186. async_error.BeginReadLine ();
  1187. }
  1188. void ErrorReadNotifyUser (String data)
  1189. {
  1190. // To avoid ---- between remove handler and raising the event
  1191. DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
  1192. if (errorDataReceived != null) {
  1193. if (SynchronizingObject != null && SynchronizingObject.InvokeRequired)
  1194. SynchronizingObject.Invoke (errorDataReceived, new object[] { this, new DataReceivedEventArgs (data) });
  1195. else
  1196. errorDataReceived (this, new DataReceivedEventArgs (data)); // Call back to user informing data is available.
  1197. }
  1198. }
  1199. [ComVisibleAttribute(false)]
  1200. public void CancelErrorRead ()
  1201. {
  1202. if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false)
  1203. throw new InvalidOperationException ("Standard error has not been redirected or process has not been started.");
  1204. if ((async_mode & AsyncModes.SyncOutput) != 0)
  1205. throw new InvalidOperationException ("OutputStream is not enabled for asynchronous read operations.");
  1206. if (async_error == null)
  1207. throw new InvalidOperationException ("No async operation in progress.");
  1208. async_error.CancelOperation ();
  1209. async_mode &= ~AsyncModes.AsyncError;
  1210. }
  1211. #else
  1212. [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
  1213. public void BeginOutputReadLine ()
  1214. {
  1215. throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
  1216. }
  1217. [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
  1218. public void CancelOutputRead ()
  1219. {
  1220. throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
  1221. }
  1222. [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
  1223. public void BeginErrorReadLine ()
  1224. {
  1225. throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
  1226. }
  1227. [Obsolete ("Process.BeginOutputReadLine is not supported on the current platform.", true)]
  1228. public void CancelErrorRead ()
  1229. {
  1230. throw new PlatformNotSupportedException ("Process.BeginOutputReadLine is not supported on the current platform.");
  1231. }
  1232. #endif // MONO_FEATURE_PROCESS_START
  1233. [Category ("Behavior")]
  1234. [MonitoringDescription ("Raised when this process exits.")]
  1235. public event EventHandler Exited {
  1236. add {
  1237. if (process_handle != IntPtr.Zero && HasExited) {
  1238. value.BeginInvoke (null, null, null, null);
  1239. } else {
  1240. exited_event += value;
  1241. if (exited_event != null)
  1242. StartBackgroundWaitForExit ();
  1243. }
  1244. }
  1245. remove {
  1246. exited_event -= value;
  1247. }
  1248. }
  1249. // Closes the system process handle
  1250. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1251. private extern void Process_free_internal(IntPtr handle);
  1252. int disposed;
  1253. protected override void Dispose(bool disposing) {
  1254. // Check to see if Dispose has already been called.
  1255. if (disposed != 0 || Interlocked.CompareExchange (ref disposed, 1, 0) != 0)
  1256. return;
  1257. // If this is a call to Dispose,
  1258. // dispose all managed resources.
  1259. if (disposing) {
  1260. #if MONO_FEATURE_PROCESS_START
  1261. /* These have open FileStreams on the pipes we are about to close */
  1262. if (async_output != null)
  1263. async_output.Close ();
  1264. if (async_error != null)
  1265. async_error.Close ();
  1266. if (input_stream != null) {
  1267. if (!input_stream_exposed)
  1268. input_stream.Close ();
  1269. input_stream = null;
  1270. }
  1271. if (output_stream != null) {
  1272. if (!output_stream_exposed)
  1273. output_stream.Close ();
  1274. output_stream = null;
  1275. }
  1276. if (error_stream != null) {
  1277. if (!error_stream_exposed)
  1278. error_stream.Close ();
  1279. error_stream = null;
  1280. }
  1281. #endif // MONO_FEATURE_PROCESS_START
  1282. }
  1283. // Release unmanaged resources
  1284. if (process_handle!=IntPtr.Zero) {
  1285. Process_free_internal (process_handle);
  1286. process_handle = IntPtr.Zero;
  1287. }
  1288. base.Dispose (disposing);
  1289. }
  1290. ~Process ()
  1291. {
  1292. Dispose (false);
  1293. }
  1294. int on_exited_called = 0;
  1295. protected void OnExited()
  1296. {
  1297. if (on_exited_called != 0 || Interlocked.CompareExchange (ref on_exited_called, 1, 0) != 0)
  1298. return;
  1299. var cb = exited_event;
  1300. if (cb == null)
  1301. return;
  1302. if (synchronizingObject != null) {
  1303. synchronizingObject.BeginInvoke (cb, new object [] { this, EventArgs.Empty });
  1304. } else {
  1305. foreach (EventHandler d in cb.GetInvocationList ()) {
  1306. try {
  1307. d (this, EventArgs.Empty);
  1308. } catch {
  1309. }
  1310. }
  1311. }
  1312. }
  1313. static bool IsWindows
  1314. {
  1315. get
  1316. {
  1317. PlatformID platform = Environment.OSVersion.Platform;
  1318. if (platform == PlatformID.Win32S ||
  1319. platform == PlatformID.Win32Windows ||
  1320. platform == PlatformID.Win32NT ||
  1321. platform == PlatformID.WinCE) {
  1322. return true;
  1323. }
  1324. return false;
  1325. }
  1326. }
  1327. void StartBackgroundWaitForExit ()
  1328. {
  1329. IntPtr handle = process_handle;
  1330. if (enable_raising_events == 0)
  1331. return;
  1332. if (exited_event == null)
  1333. return;
  1334. if (handle == IntPtr.Zero)
  1335. return;
  1336. if (background_wait_for_exit_thread != null)
  1337. return;
  1338. Thread t = new Thread (_ => {
  1339. if (!WaitForExit_internal (handle, -1))
  1340. return;
  1341. if (EnableRaisingEvents)
  1342. OnExited ();
  1343. });
  1344. t.IsBackground = true;
  1345. if (Interlocked.CompareExchange (ref background_wait_for_exit_thread, t, null) == null)
  1346. t.Start ();
  1347. }
  1348. class ProcessWaitHandle : WaitHandle
  1349. {
  1350. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  1351. private extern static IntPtr ProcessHandle_duplicate (IntPtr handle);
  1352. public ProcessWaitHandle (IntPtr handle)
  1353. {
  1354. // Need to keep a reference to this handle,
  1355. // in case the Process object is collected
  1356. Handle = ProcessHandle_duplicate (handle);
  1357. // When the wait handle is disposed, the duplicated handle will be
  1358. // closed, so no need to override dispose (bug #464628).
  1359. }
  1360. }
  1361. }
  1362. }