Process.cs 45 KB

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