ProcessTest.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. //
  2. // ProcessTest.cs - NUnit Test Cases for System.Diagnostics.Process
  3. //
  4. // Authors:
  5. // Gert Driesen ([email protected])
  6. // Robert Jordan <[email protected]>
  7. //
  8. // (C) 2007 Gert Driesen
  9. //
  10. using System;
  11. using System.ComponentModel;
  12. using System.Diagnostics;
  13. using System.IO;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Runtime.InteropServices;
  17. using NUnit.Framework;
  18. namespace MonoTests.System.Diagnostics
  19. {
  20. [TestFixture]
  21. public class ProcessTest
  22. {
  23. static bool RunningOnUnix {
  24. get {
  25. int p = (int)Environment.OSVersion.Platform;
  26. return ((p == 128) || (p == 4) || (p == 6));
  27. }
  28. }
  29. [Test]
  30. public void GetProcessById_MachineName_Null ()
  31. {
  32. try {
  33. Process.GetProcessById (1, (string) null);
  34. Assert.Fail ("#1");
  35. } catch (ArgumentNullException ex) {
  36. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  37. Assert.IsNotNull (ex.Message, "#3");
  38. Assert.IsNotNull (ex.ParamName, "#4");
  39. Assert.AreEqual ("machineName", ex.ParamName, "#5");
  40. Assert.IsNull (ex.InnerException, "#6");
  41. }
  42. }
  43. [Test]
  44. public void GetProcesses_MachineName_Null ()
  45. {
  46. try {
  47. Process.GetProcesses ((string) null);
  48. Assert.Fail ("#1");
  49. } catch (ArgumentNullException ex) {
  50. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  51. Assert.IsNotNull (ex.Message, "#3");
  52. Assert.IsNotNull (ex.ParamName, "#4");
  53. Assert.AreEqual ("machineName", ex.ParamName, "#5");
  54. Assert.IsNull (ex.InnerException, "#6");
  55. }
  56. }
  57. [Test] // Covers #26363
  58. [NUnit.Framework.Category ("MobileNotWorking")]
  59. public void GetProcesses_StartTime ()
  60. {
  61. foreach (var p in Process.GetProcesses ()) {
  62. if (!p.HasExited && p.StartTime.Year < 1800)
  63. Assert.Fail ("Process should not be started since the 18th century.");
  64. }
  65. }
  66. [Test]
  67. public void PriorityClass_NotStarted ()
  68. {
  69. Process process = new Process ();
  70. try {
  71. process.PriorityClass = ProcessPriorityClass.Normal;
  72. Assert.Fail ("#A1");
  73. } catch (InvalidOperationException ex) {
  74. // No process is associated with this object
  75. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  76. Assert.IsNull (ex.InnerException, "#A3");
  77. Assert.IsNotNull (ex.Message, "#A4");
  78. }
  79. try {
  80. Assert.Fail ("#B1:" + process.PriorityClass);
  81. } catch (InvalidOperationException ex) {
  82. // No process is associated with this object
  83. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  84. Assert.IsNull (ex.InnerException, "#B3");
  85. Assert.IsNotNull (ex.Message, "#B4");
  86. }
  87. }
  88. [Test]
  89. public void PriorityClass_Invalid ()
  90. {
  91. Process process = new Process ();
  92. try {
  93. process.PriorityClass = (ProcessPriorityClass) 666;
  94. Assert.Fail ("#1");
  95. } catch (InvalidEnumArgumentException ex) {
  96. Assert.AreEqual (typeof (InvalidEnumArgumentException), ex.GetType (), "#2");
  97. Assert.IsNull (ex.InnerException, "#3");
  98. Assert.IsNotNull (ex.Message, "#4");
  99. Assert.IsTrue (ex.Message.IndexOf ("666") != -1, "#5");
  100. Assert.IsTrue (ex.Message.IndexOf (typeof (ProcessPriorityClass).Name) != -1, "#6");
  101. Assert.IsNotNull (ex.ParamName, "#7");
  102. Assert.AreEqual ("value", ex.ParamName, "#8");
  103. }
  104. }
  105. #if MONO_FEATURE_PROCESS_START
  106. [Test] // Start ()
  107. public void Start1_FileName_Empty ()
  108. {
  109. Process process = new Process ();
  110. process.StartInfo = new ProcessStartInfo (string.Empty);
  111. // no shell
  112. process.StartInfo.UseShellExecute = false;
  113. try {
  114. process.Start ();
  115. Assert.Fail ("#A1");
  116. } catch (InvalidOperationException ex) {
  117. // Cannot start process because a file name has
  118. // not been provided
  119. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  120. Assert.IsNull (ex.InnerException, "#A3");
  121. Assert.IsNotNull (ex.Message, "#A4");
  122. }
  123. // shell
  124. process.StartInfo.UseShellExecute = true;
  125. try {
  126. process.Start ();
  127. Assert.Fail ("#B1");
  128. } catch (InvalidOperationException ex) {
  129. // Cannot start process because a file name has
  130. // not been provided
  131. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  132. Assert.IsNull (ex.InnerException, "#B3");
  133. Assert.IsNotNull (ex.Message, "#B4");
  134. }
  135. }
  136. [Test] // Start ()
  137. public void Start1_FileName_InvalidPathCharacters ()
  138. {
  139. if (RunningOnUnix)
  140. // on unix, all characters are allowed
  141. Assert.Ignore ("Running on Unix.");
  142. string systemDir = Environment.GetFolderPath (Environment.SpecialFolder.System);
  143. string exe = "\"" + Path.Combine (systemDir, "calc.exe") + "\"";
  144. Process process = new Process ();
  145. process.StartInfo = new ProcessStartInfo (exe);
  146. // no shell
  147. process.StartInfo.UseShellExecute = false;
  148. Assert.IsTrue (process.Start ());
  149. process.Kill ();
  150. // shell
  151. process.StartInfo.UseShellExecute = true;
  152. Assert.IsTrue (process.Start ());
  153. process.Kill ();
  154. }
  155. [Test] // Start ()
  156. public void Start1_FileName_NotFound ()
  157. {
  158. Process process = new Process ();
  159. string exe = RunningOnUnix ? exe = "/usr/bin/shouldnoteverexist"
  160. : @"c:\shouldnoteverexist.exe";
  161. // absolute path, no shell
  162. process.StartInfo = new ProcessStartInfo (exe);
  163. process.StartInfo.UseShellExecute = false;
  164. try {
  165. process.Start ();
  166. Assert.Fail ("#A1");
  167. } catch (Win32Exception ex) {
  168. // The system cannot find the file specified
  169. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#A2");
  170. Assert.AreEqual (-2147467259, ex.ErrorCode, "#A3");
  171. Assert.IsNull (ex.InnerException, "#A4");
  172. Assert.IsNotNull (ex.Message, "#A5");
  173. Assert.AreEqual (2, ex.NativeErrorCode, "#A6");
  174. }
  175. // relative path, no shell
  176. process.StartInfo.FileName = "shouldnoteverexist.exe";
  177. process.StartInfo.UseShellExecute = false;
  178. try {
  179. process.Start ();
  180. Assert.Fail ("#B1");
  181. } catch (Win32Exception ex) {
  182. // The system cannot find the file specified
  183. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#B2");
  184. Assert.AreEqual (-2147467259, ex.ErrorCode, "#B3");
  185. Assert.IsNull (ex.InnerException, "#B4");
  186. Assert.IsNotNull (ex.Message, "#B5");
  187. Assert.AreEqual (2, ex.NativeErrorCode, "#B6");
  188. }
  189. if (RunningOnUnix)
  190. Assert.Ignore ("On Unix and Mac OS X, we try " +
  191. "to open any file (using xdg-open, ...)" +
  192. " and we do not report an exception " +
  193. "if this fails.");
  194. // absolute path, shell
  195. process.StartInfo.FileName = exe;
  196. process.StartInfo.UseShellExecute = true;
  197. try {
  198. process.Start ();
  199. Assert.Fail ("#C1");
  200. } catch (Win32Exception ex) {
  201. // The system cannot find the file specified
  202. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#C2");
  203. Assert.AreEqual (-2147467259, ex.ErrorCode, "#C3");
  204. Assert.IsNull (ex.InnerException, "#C4");
  205. Assert.IsNotNull (ex.Message, "#C5");
  206. Assert.AreEqual (2, ex.NativeErrorCode, "#C6");
  207. }
  208. // relative path, shell
  209. process.StartInfo.FileName = "shouldnoteverexist.exe";
  210. process.StartInfo.UseShellExecute = true;
  211. try {
  212. process.Start ();
  213. Assert.Fail ("#D1");
  214. } catch (Win32Exception ex) {
  215. // The system cannot find the file specified
  216. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#D2");
  217. Assert.AreEqual (-2147467259, ex.ErrorCode, "#D3");
  218. Assert.IsNull (ex.InnerException, "#D4");
  219. Assert.IsNotNull (ex.Message, "#D5");
  220. Assert.AreEqual (2, ex.NativeErrorCode, "#D6");
  221. }
  222. }
  223. [Test] // Start ()
  224. public void Start1_FileName_Null ()
  225. {
  226. Process process = new Process ();
  227. process.StartInfo = new ProcessStartInfo ((string) null);
  228. // no shell
  229. process.StartInfo.UseShellExecute = false;
  230. try {
  231. process.Start ();
  232. Assert.Fail ("#A1");
  233. } catch (InvalidOperationException ex) {
  234. // Cannot start process because a file name has
  235. // not been provided
  236. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  237. Assert.IsNull (ex.InnerException, "#A3");
  238. Assert.IsNotNull (ex.Message, "#A4");
  239. }
  240. // shell
  241. process.StartInfo.UseShellExecute = true;
  242. try {
  243. process.Start ();
  244. Assert.Fail ("#B1");
  245. } catch (InvalidOperationException ex) {
  246. // Cannot start process because a file name has
  247. // not been provided
  248. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  249. Assert.IsNull (ex.InnerException, "#B3");
  250. Assert.IsNotNull (ex.Message, "#B4");
  251. }
  252. }
  253. [Test] // Start ()
  254. public void Start1_FileName_Whitespace ()
  255. {
  256. Process process = new Process ();
  257. process.StartInfo = new ProcessStartInfo (" ");
  258. process.StartInfo.UseShellExecute = false;
  259. try {
  260. process.Start ();
  261. Assert.Fail ("#1");
  262. } catch (Win32Exception ex) {
  263. // The system cannot find the file specified
  264. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#2");
  265. Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
  266. Assert.IsNull (ex.InnerException, "#4");
  267. Assert.IsNotNull (ex.Message, "#5");
  268. // TODO: On windows we get ACCESS_DENIED (5) instead of FILE_NOT_FOUND (2) and .NET
  269. // gives ERROR_INVALID_PARAMETER (87). See https://bugzilla.xamarin.com/show_bug.cgi?id=44514
  270. Assert.IsTrue (ex.NativeErrorCode == 2 || ex.NativeErrorCode == 5 || ex.NativeErrorCode == 87, "#6");
  271. }
  272. }
  273. [Test] // Start (ProcessStartInfo)
  274. public void Start2_FileName_Empty ()
  275. {
  276. ProcessStartInfo startInfo = new ProcessStartInfo (string.Empty);
  277. // no shell
  278. startInfo.UseShellExecute = false;
  279. try {
  280. Process.Start (startInfo);
  281. Assert.Fail ("#A1");
  282. } catch (InvalidOperationException ex) {
  283. // Cannot start process because a file name has
  284. // not been provided
  285. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  286. Assert.IsNull (ex.InnerException, "#A3");
  287. Assert.IsNotNull (ex.Message, "#A4");
  288. }
  289. // shell
  290. startInfo.UseShellExecute = true;
  291. try {
  292. Process.Start (startInfo);
  293. Assert.Fail ("#B1");
  294. } catch (InvalidOperationException ex) {
  295. // Cannot start process because a file name has
  296. // not been provided
  297. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  298. Assert.IsNull (ex.InnerException, "#B3");
  299. Assert.IsNotNull (ex.Message, "#B4");
  300. }
  301. }
  302. [Test] // Start (ProcessStartInfo)
  303. public void Start2_FileName_NotFound ()
  304. {
  305. ProcessStartInfo startInfo = new ProcessStartInfo ();
  306. string exe = RunningOnUnix ? exe = "/usr/bin/shouldnoteverexist"
  307. : @"c:\shouldnoteverexist.exe";
  308. // absolute path, no shell
  309. startInfo.FileName = exe;
  310. startInfo.UseShellExecute = false;
  311. try {
  312. Process.Start (startInfo);
  313. Assert.Fail ("#A1");
  314. } catch (Win32Exception ex) {
  315. // The system cannot find the file specified
  316. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#A2");
  317. Assert.AreEqual (-2147467259, ex.ErrorCode, "#A3");
  318. Assert.IsNull (ex.InnerException, "#A4");
  319. Assert.IsNotNull (ex.Message, "#A5");
  320. Assert.AreEqual (2, ex.NativeErrorCode, "#A6");
  321. }
  322. // relative path, no shell
  323. startInfo.FileName = "shouldnoteverexist.exe";
  324. startInfo.UseShellExecute = false;
  325. try {
  326. Process.Start (startInfo);
  327. Assert.Fail ("#B1");
  328. } catch (Win32Exception ex) {
  329. // The system cannot find the file specified
  330. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#B2");
  331. Assert.AreEqual (-2147467259, ex.ErrorCode, "#B3");
  332. Assert.IsNull (ex.InnerException, "#B4");
  333. Assert.IsNotNull (ex.Message, "#B5");
  334. Assert.AreEqual (2, ex.NativeErrorCode, "#B6");
  335. }
  336. if (RunningOnUnix)
  337. Assert.Ignore ("On Unix and Mac OS X, we try " +
  338. "to open any file (using xdg-open, ...)" +
  339. " and we do not report an exception " +
  340. "if this fails.");
  341. // absolute path, shell
  342. startInfo.FileName = exe;
  343. startInfo.UseShellExecute = true;
  344. try {
  345. Process.Start (startInfo);
  346. Assert.Fail ("#C1");
  347. } catch (Win32Exception ex) {
  348. // The system cannot find the file specified
  349. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#C2");
  350. Assert.AreEqual (-2147467259, ex.ErrorCode, "#C3");
  351. Assert.IsNull (ex.InnerException, "#C4");
  352. Assert.IsNotNull (ex.Message, "#C5");
  353. Assert.AreEqual (2, ex.NativeErrorCode, "#C6");
  354. }
  355. // relative path, shell
  356. startInfo.FileName = "shouldnoteverexist.exe";
  357. startInfo.UseShellExecute = true;
  358. try {
  359. Process.Start (startInfo);
  360. Assert.Fail ("#D1");
  361. } catch (Win32Exception ex) {
  362. // The system cannot find the file specified
  363. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#D2");
  364. Assert.AreEqual (-2147467259, ex.ErrorCode, "#D3");
  365. Assert.IsNull (ex.InnerException, "#D4");
  366. Assert.IsNotNull (ex.Message, "#D5");
  367. Assert.AreEqual (2, ex.NativeErrorCode, "#D6");
  368. }
  369. }
  370. [Test] // Start (ProcessStartInfo)
  371. public void Start2_FileName_Null ()
  372. {
  373. ProcessStartInfo startInfo = new ProcessStartInfo ((string) null);
  374. // no shell
  375. startInfo.UseShellExecute = false;
  376. try {
  377. Process.Start (startInfo);
  378. Assert.Fail ("#A1");
  379. } catch (InvalidOperationException ex) {
  380. // Cannot start process because a file name has
  381. // not been provided
  382. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  383. Assert.IsNull (ex.InnerException, "#A3");
  384. Assert.IsNotNull (ex.Message, "#A4");
  385. }
  386. // shell
  387. startInfo.UseShellExecute = true;
  388. try {
  389. Process.Start (startInfo);
  390. Assert.Fail ("#B1");
  391. } catch (InvalidOperationException ex) {
  392. // Cannot start process because a file name has
  393. // not been provided
  394. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  395. Assert.IsNull (ex.InnerException, "#B3");
  396. Assert.IsNotNull (ex.Message, "#B4");
  397. }
  398. }
  399. [Test] // Start (ProcessStartInfo)
  400. public void Start2_FileName_Whitespace ()
  401. {
  402. ProcessStartInfo startInfo = new ProcessStartInfo (" ");
  403. startInfo.UseShellExecute = false;
  404. try {
  405. Process.Start (startInfo);
  406. Assert.Fail ("#1");
  407. } catch (Win32Exception ex) {
  408. // The system cannot find the file specified
  409. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#2");
  410. Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
  411. Assert.IsNull (ex.InnerException, "#4");
  412. Assert.IsNotNull (ex.Message, "#5");
  413. // TODO: On windows we get ACCESS_DENIED (5) instead of FILE_NOT_FOUND (2) and .NET
  414. // gives ERROR_INVALID_PARAMETER (87). See https://bugzilla.xamarin.com/show_bug.cgi?id=44514
  415. Assert.IsTrue (ex.NativeErrorCode == 2 || ex.NativeErrorCode == 5 || ex.NativeErrorCode == 87, "#6");
  416. }
  417. }
  418. [Test] // Start (ProcessStartInfo)
  419. public void Start2_StartInfo_Null ()
  420. {
  421. try {
  422. Process.Start ((ProcessStartInfo) null);
  423. Assert.Fail ("#1");
  424. } catch (ArgumentNullException ex) {
  425. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  426. Assert.IsNull (ex.InnerException, "#3");
  427. Assert.IsNotNull (ex.Message, "#4");
  428. Assert.IsNotNull (ex.ParamName, "#5");
  429. Assert.AreEqual ("startInfo", ex.ParamName, "#6");
  430. }
  431. }
  432. [Test] // Start (string)
  433. public void Start3_FileName_Empty ()
  434. {
  435. try {
  436. Process.Start (string.Empty);
  437. Assert.Fail ("#1");
  438. } catch (InvalidOperationException ex) {
  439. // Cannot start process because a file name has
  440. // not been provided
  441. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  442. Assert.IsNull (ex.InnerException, "#3");
  443. Assert.IsNotNull (ex.Message, "#4");
  444. }
  445. }
  446. [Test] // Start (string)
  447. public void Start3_FileName_NotFound ()
  448. {
  449. if (RunningOnUnix)
  450. Assert.Ignore ("On Unix and Mac OS X, we try " +
  451. "to open any file (using xdg-open, ...)" +
  452. " and we do not report an exception " +
  453. "if this fails.");
  454. string exe = @"c:\shouldnoteverexist.exe";
  455. // absolute path, no shell
  456. try {
  457. Process.Start (exe);
  458. Assert.Fail ("#A1");
  459. } catch (Win32Exception ex) {
  460. // The system cannot find the file specified
  461. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#A2");
  462. Assert.AreEqual (-2147467259, ex.ErrorCode, "#A3");
  463. Assert.IsNull (ex.InnerException, "#A4");
  464. Assert.IsNotNull (ex.Message, "#A5");
  465. Assert.AreEqual (2, ex.NativeErrorCode, "#A6");
  466. }
  467. // relative path, no shell
  468. try {
  469. Process.Start ("shouldnoteverexist.exe");
  470. Assert.Fail ("#B1");
  471. } catch (Win32Exception ex) {
  472. // The system cannot find the file specified
  473. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#B2");
  474. Assert.AreEqual (-2147467259, ex.ErrorCode, "#B3");
  475. Assert.IsNull (ex.InnerException, "#B4");
  476. Assert.IsNotNull (ex.Message, "#B5");
  477. Assert.AreEqual (2, ex.NativeErrorCode, "#B6");
  478. }
  479. }
  480. [Test] // Start (string)
  481. public void Start3_FileName_Null ()
  482. {
  483. try {
  484. Process.Start ((string) null);
  485. Assert.Fail ("#1");
  486. } catch (InvalidOperationException ex) {
  487. // Cannot start process because a file name has
  488. // not been provided
  489. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  490. Assert.IsNull (ex.InnerException, "#3");
  491. Assert.IsNotNull (ex.Message, "#4");
  492. }
  493. }
  494. [Test] // Start (string, string)
  495. public void Start4_Arguments_Null ()
  496. {
  497. if (RunningOnUnix)
  498. Assert.Ignore ("On Unix and Mac OS X, we try " +
  499. "to open any file (using xdg-open, ...)" +
  500. " and we do not report an exception " +
  501. "if this fails.");
  502. string exe = @"c:\shouldnoteverexist.exe";
  503. try {
  504. Process.Start ("whatever.exe", (string) null);
  505. Assert.Fail ("#1");
  506. } catch (Win32Exception ex) {
  507. // The system cannot find the file specified
  508. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#B2");
  509. Assert.AreEqual (-2147467259, ex.ErrorCode, "#B3");
  510. Assert.IsNull (ex.InnerException, "#B4");
  511. Assert.IsNotNull (ex.Message, "#B5");
  512. Assert.AreEqual (2, ex.NativeErrorCode, "#B6");
  513. }
  514. }
  515. [Test] // Start (string, string)
  516. public void Start4_FileName_Empty ()
  517. {
  518. try {
  519. Process.Start (string.Empty, string.Empty);
  520. Assert.Fail ("#1");
  521. } catch (InvalidOperationException ex) {
  522. // Cannot start process because a file name has
  523. // not been provided
  524. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  525. Assert.IsNull (ex.InnerException, "#3");
  526. Assert.IsNotNull (ex.Message, "#4");
  527. }
  528. }
  529. [Test] // Start (string, string)
  530. public void Start4_FileName_NotFound ()
  531. {
  532. if (RunningOnUnix)
  533. Assert.Ignore ("On Unix and Mac OS X, we try " +
  534. "to open any file (using xdg-open, ...)" +
  535. " and we do not report an exception " +
  536. "if this fails.");
  537. string exe = @"c:\shouldnoteverexist.exe";
  538. // absolute path, no shell
  539. try {
  540. Process.Start (exe, string.Empty);
  541. Assert.Fail ("#A1");
  542. } catch (Win32Exception ex) {
  543. // The system cannot find the file specified
  544. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#A2");
  545. Assert.AreEqual (-2147467259, ex.ErrorCode, "#A3");
  546. Assert.IsNull (ex.InnerException, "#A4");
  547. Assert.IsNotNull (ex.Message, "#A5");
  548. Assert.AreEqual (2, ex.NativeErrorCode, "#A6");
  549. }
  550. // relative path, no shell
  551. try {
  552. Process.Start ("shouldnoteverexist.exe", string.Empty);
  553. Assert.Fail ("#B1");
  554. } catch (Win32Exception ex) {
  555. // The system cannot find the file specified
  556. Assert.AreEqual (typeof (Win32Exception), ex.GetType (), "#B2");
  557. Assert.AreEqual (-2147467259, ex.ErrorCode, "#B3");
  558. Assert.IsNull (ex.InnerException, "#B4");
  559. Assert.IsNotNull (ex.Message, "#B5");
  560. Assert.AreEqual (2, ex.NativeErrorCode, "#B6");
  561. }
  562. }
  563. [Test]
  564. public void Start_UseShellExecuteWithEmptyUserName ()
  565. {
  566. if (RunningOnUnix)
  567. Assert.Ignore ("On Unix and Mac OS X, we try " +
  568. "to open any file (using xdg-open, ...)" +
  569. " and we do not report an exception " +
  570. "if this fails.");
  571. string exe = @"c:\shouldnoteverexist.exe";
  572. try {
  573. Process p = new Process ();
  574. p.StartInfo.FileName = exe;
  575. p.StartInfo.UseShellExecute = true;
  576. p.StartInfo.UserName = "";
  577. p.Start ();
  578. Assert.Fail ("#1");
  579. } catch (InvalidOperationException) {
  580. Assert.Fail ("#2");
  581. } catch (Win32Exception) {
  582. }
  583. try {
  584. Process p = new Process ();
  585. p.StartInfo.FileName = exe;
  586. p.StartInfo.UseShellExecute = true;
  587. p.StartInfo.UserName = null;
  588. p.Start ();
  589. Assert.Fail ("#3");
  590. } catch (InvalidOperationException) {
  591. Assert.Fail ("#4");
  592. } catch (Win32Exception) {
  593. }
  594. }
  595. [Test] // Start (string, string)
  596. public void Start4_FileName_Null ()
  597. {
  598. try {
  599. Process.Start ((string) null, string.Empty);
  600. Assert.Fail ("#1");
  601. } catch (InvalidOperationException ex) {
  602. // Cannot start process because a file name has
  603. // not been provided
  604. Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  605. Assert.IsNull (ex.InnerException, "#3");
  606. Assert.IsNotNull (ex.Message, "#4");
  607. }
  608. }
  609. [Test]
  610. public void StartInfo ()
  611. {
  612. ProcessStartInfo startInfo = new ProcessStartInfo ();
  613. Process p = new Process ();
  614. Assert.IsNotNull (p.StartInfo, "#A1");
  615. p.StartInfo = startInfo;
  616. Assert.AreSame (startInfo, p.StartInfo, "#A2");
  617. }
  618. [Test]
  619. public void StartInfo_Null ()
  620. {
  621. Process p = new Process ();
  622. try {
  623. p.StartInfo = null;
  624. Assert.Fail ("#1");
  625. } catch (ArgumentNullException ex) {
  626. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  627. Assert.IsNull (ex.InnerException, "#3");
  628. Assert.IsNotNull (ex.Message, "#4");
  629. Assert.IsNotNull (ex.ParamName, "#5");
  630. Assert.AreEqual ("value", ex.ParamName, "#6");
  631. }
  632. }
  633. [Test]
  634. [NUnit.Framework.Category ("NotDotNet")]
  635. [NUnit.Framework.Category ("MobileNotWorking")]
  636. public void TestRedirectedOutputIsAsync ()
  637. {
  638. // Test requires cygwin, so we just bail out for now.
  639. if (Path.DirectorySeparatorChar == '\\')
  640. Assert.Ignore ("Test requires cygwin.");
  641. Process p = new Process ();
  642. p.StartInfo = new ProcessStartInfo ("/bin/sh", "-c \"sleep 2; echo hello\"");
  643. p.StartInfo.RedirectStandardOutput = true;
  644. p.StartInfo.UseShellExecute = false;
  645. p.Start ();
  646. Stream stdout = p.StandardOutput.BaseStream;
  647. byte [] buffer = new byte [200];
  648. // start async Read operation
  649. DateTime start = DateTime.Now;
  650. IAsyncResult ar = stdout.BeginRead (buffer, 0, buffer.Length,
  651. new AsyncCallback (Read), stdout);
  652. Assert.IsTrue ((DateTime.Now - start).TotalMilliseconds < 1000, "#01 BeginRead was not async");
  653. p.WaitForExit ();
  654. Assert.AreEqual (0, p.ExitCode, "#02 script failure");
  655. /*
  656. ar.AsyncWaitHandle.WaitOne (2000, false);
  657. if (bytesRead < "hello".Length)
  658. Assert.Fail ("#03 got {0} bytes", bytesRead);
  659. Assert.AreEqual ("hello", Encoding.Default.GetString (buffer, 0, 5), "#04");
  660. */
  661. }
  662. void Read (IAsyncResult ar)
  663. {
  664. Stream stm = (Stream) ar.AsyncState;
  665. bytesRead = stm.EndRead (ar);
  666. }
  667. public int bytesRead = -1;
  668. [Test]
  669. [NUnit.Framework.Category ("MobileNotWorking")]
  670. // This was for bug #459450
  671. public void TestEventRaising ()
  672. {
  673. EventWaitHandle errorClosed = new ManualResetEvent(false);
  674. EventWaitHandle outClosed = new ManualResetEvent(false);
  675. EventWaitHandle exited = new ManualResetEvent(false);
  676. Process p = new Process();
  677. p.StartInfo = GetCrossPlatformStartInfo ();
  678. p.StartInfo.UseShellExecute = false;
  679. p.StartInfo.RedirectStandardOutput = true;
  680. p.StartInfo.RedirectStandardError = true;
  681. p.StartInfo.RedirectStandardInput = false;
  682. p.OutputDataReceived += (object sender, DataReceivedEventArgs e) => {
  683. if (e.Data == null) {
  684. outClosed.Set();
  685. }
  686. };
  687. p.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => {
  688. if (e.Data == null) {
  689. errorClosed.Set();
  690. }
  691. };
  692. p.Exited += (object sender, EventArgs e) => {
  693. exited.Set ();
  694. };
  695. p.EnableRaisingEvents = true;
  696. p.Start();
  697. p.BeginErrorReadLine();
  698. p.BeginOutputReadLine();
  699. Console.WriteLine("started, waiting for handles");
  700. bool r = WaitHandle.WaitAll(new WaitHandle[] { errorClosed, outClosed, exited }, 10000, false);
  701. Assert.AreEqual (true, r, "Null Argument Events Raised");
  702. }
  703. [Test]
  704. [NUnit.Framework.Category ("MobileNotWorking")]
  705. public void TestEnableEventsAfterExitedEvent ()
  706. {
  707. Process p = new Process ();
  708. p.StartInfo = GetCrossPlatformStartInfo ();
  709. p.StartInfo.UseShellExecute = false;
  710. p.StartInfo.RedirectStandardOutput = true;
  711. p.StartInfo.RedirectStandardError = true;
  712. var exitedCalledCounter = 0;
  713. var exited = new ManualResetEventSlim ();
  714. p.Exited += (object sender, EventArgs e) => {
  715. exitedCalledCounter++;
  716. Assert.IsTrue (p.HasExited);
  717. exited.Set ();
  718. };
  719. p.EnableRaisingEvents = true;
  720. p.Start ();
  721. p.BeginErrorReadLine ();
  722. p.BeginOutputReadLine ();
  723. p.WaitForExit ();
  724. exited.Wait (10000);
  725. Assert.AreEqual (1, exitedCalledCounter);
  726. Thread.Sleep (50);
  727. Assert.AreEqual (1, exitedCalledCounter);
  728. }
  729. [Test]
  730. [NUnit.Framework.Category ("MobileNotWorking")]
  731. public void TestEnableEventsBeforeExitedEvent ()
  732. {
  733. Process p = new Process ();
  734. p.StartInfo = GetCrossPlatformStartInfo ();
  735. p.StartInfo.UseShellExecute = false;
  736. p.StartInfo.RedirectStandardOutput = true;
  737. p.StartInfo.RedirectStandardError = true;
  738. p.EnableRaisingEvents = true;
  739. var exitedCalledCounter = 0;
  740. var exited = new ManualResetEventSlim ();
  741. p.Exited += (object sender, EventArgs e) => {
  742. exitedCalledCounter++;
  743. Assert.IsTrue (p.HasExited);
  744. exited.Set ();
  745. };
  746. p.Start ();
  747. p.BeginErrorReadLine ();
  748. p.BeginOutputReadLine ();
  749. p.WaitForExit ();
  750. Assert.IsTrue (exited.Wait (10000));
  751. Assert.AreEqual (1, exitedCalledCounter);
  752. Thread.Sleep (50);
  753. Assert.AreEqual (1, exitedCalledCounter);
  754. }
  755. [Test]
  756. [NUnit.Framework.Category ("MobileNotWorking")]
  757. public void TestDisableEventsBeforeExitedEvent ()
  758. {
  759. Process p = new Process ();
  760. p.StartInfo = GetCrossPlatformStartInfo ();
  761. p.StartInfo.UseShellExecute = false;
  762. p.StartInfo.RedirectStandardOutput = true;
  763. p.StartInfo.RedirectStandardError = true;
  764. p.EnableRaisingEvents = false;
  765. ManualResetEvent mre = new ManualResetEvent (false);
  766. p.Exited += (object sender, EventArgs e) => {
  767. mre.Set ();
  768. };
  769. p.Start ();
  770. p.BeginErrorReadLine ();
  771. p.BeginOutputReadLine ();
  772. p.WaitForExit ();
  773. Assert.IsFalse (mre.WaitOne (1000));
  774. }
  775. ProcessStartInfo GetCrossPlatformStartInfo ()
  776. {
  777. if (RunningOnUnix) {
  778. string path;
  779. #if MONODROID
  780. path = "/system/bin/ls";
  781. #else
  782. path = "/bin/ls";
  783. #endif
  784. return new ProcessStartInfo (path, "/");
  785. } else
  786. return new ProcessStartInfo ("help", "");
  787. }
  788. ProcessStartInfo GetEchoCrossPlatformStartInfo ()
  789. {
  790. if (RunningOnUnix) {
  791. string path;
  792. #if MONODROID
  793. path = "/system/bin/cat";
  794. #else
  795. path = "/bin/cat";
  796. #endif
  797. return new ProcessStartInfo (path);
  798. } else {
  799. var psi = new ProcessStartInfo ("findstr");
  800. psi.Arguments = "\"^\"";
  801. return psi;
  802. }
  803. }
  804. #endif // MONO_FEATURE_PROCESS_START
  805. [Test]
  806. public void ProcessName_NotStarted ()
  807. {
  808. Process p = new Process ();
  809. Exception e = null;
  810. try {
  811. String.IsNullOrEmpty (p.ProcessName);
  812. } catch (Exception ex) {
  813. e = ex;
  814. }
  815. Assert.IsNotNull (e, "ProcessName should raise if process was not started");
  816. //msg should be "No process is associated with this object"
  817. Assert.AreEqual (e.GetType (), typeof (InvalidOperationException),
  818. "exception should be IOE, I got: " + e.GetType ().Name);
  819. Assert.IsNull (e.InnerException, "IOE inner exception should be null");
  820. }
  821. #if MONO_FEATURE_PROCESS_START
  822. [Test]
  823. [NUnit.Framework.Category ("MobileNotWorking")]
  824. public void ProcessName_AfterExit ()
  825. {
  826. Process p = new Process ();
  827. p.StartInfo = GetCrossPlatformStartInfo ();
  828. p.StartInfo.UseShellExecute = false;
  829. p.StartInfo.RedirectStandardOutput = true;
  830. p.StartInfo.RedirectStandardError = true;
  831. p.Start ();
  832. p.BeginErrorReadLine();
  833. p.BeginOutputReadLine();
  834. p.WaitForExit ();
  835. String.IsNullOrEmpty (p.ExitCode + "");
  836. Exception e = null;
  837. try {
  838. String.IsNullOrEmpty (p.ProcessName);
  839. } catch (Exception ex) {
  840. e = ex;
  841. }
  842. Assert.IsNotNull (e, "ProcessName should raise if process was finished");
  843. //msg should be "Process has exited, so the requested information is not available"
  844. Assert.AreEqual (e.GetType (), typeof (InvalidOperationException),
  845. "exception should be IOE, I got: " + e.GetType ().Name);
  846. Assert.IsNull (e.InnerException, "IOE inner exception should be null");
  847. }
  848. #endif // MONO_FEATURE_PROCESS_START
  849. [Test]
  850. public void Handle_ThrowsOnNotStarted ()
  851. {
  852. Process p = new Process ();
  853. try {
  854. var x = p.Handle;
  855. Assert.Fail ("Handle should throw for unstated procs, but returned " + x);
  856. } catch (InvalidOperationException) {
  857. }
  858. }
  859. [Test]
  860. public void HasExitedCurrent () {
  861. Assert.IsFalse (Process.GetCurrentProcess ().HasExited);
  862. }
  863. #if MONO_FEATURE_PROCESS_START
  864. [Test]
  865. [NUnit.Framework.Category ("MobileNotWorking")]
  866. public void DisposeWithDisposedStreams ()
  867. {
  868. var psi = GetCrossPlatformStartInfo ();
  869. psi.RedirectStandardInput = true;
  870. psi.RedirectStandardOutput = true;
  871. psi.UseShellExecute = false;
  872. var p = Process.Start (psi);
  873. p.StandardInput.BaseStream.Dispose ();
  874. p.StandardOutput.BaseStream.Dispose ();
  875. p.Dispose ();
  876. }
  877. [Test]
  878. [NUnit.Framework.Category ("MobileNotWorking")]
  879. public void StandardInputWrite ()
  880. {
  881. var psi = GetEchoCrossPlatformStartInfo ();
  882. psi.RedirectStandardInput = true;
  883. psi.RedirectStandardOutput = true;
  884. psi.UseShellExecute = false;
  885. using (var p = Process.Start (psi)) {
  886. // drain stdout
  887. p.OutputDataReceived += (s, e) => {};
  888. p.BeginOutputReadLine ();
  889. for (int i = 0; i < 1024 * 9; ++i) {
  890. p.StandardInput.Write ('x');
  891. if (i > 0 && i % 128 == 0)
  892. p.StandardInput.WriteLine ();
  893. }
  894. p.StandardInput.Close ();
  895. p.WaitForExit ();
  896. }
  897. }
  898. #endif // MONO_FEATURE_PROCESS_START
  899. [Test]
  900. public void Modules () {
  901. var modules = Process.GetCurrentProcess ().Modules;
  902. foreach (var a in AppDomain.CurrentDomain.GetAssemblies ()) {
  903. var found = false;
  904. var name = a.GetName ();
  905. StringBuilder sb = new StringBuilder ();
  906. sb.AppendFormat ("Could not found: {0} {1}\n", name.Name, name.Version);
  907. sb.AppendLine ("Looked in modules:");
  908. foreach (var o in modules) {
  909. var m = (ProcessModule) o;
  910. sb.AppendFormat (" {0} {1}.{2}.{3}\n", m.FileName.ToString (),
  911. m.FileVersionInfo.FileMajorPart,
  912. m.FileVersionInfo.FileMinorPart,
  913. m.FileVersionInfo.FileBuildPart);
  914. if (!m.FileName.StartsWith ("[In Memory] " + name.Name))
  915. continue;
  916. var fv = m.FileVersionInfo;
  917. if (fv.FileBuildPart != name.Version.Build ||
  918. fv.FileMinorPart != name.Version.Minor ||
  919. fv.FileMajorPart != name.Version.Major)
  920. continue;
  921. found = true;
  922. }
  923. Assert.IsTrue (found, sb.ToString ());
  924. }
  925. }
  926. #if MONO_FEATURE_PROCESS_START
  927. [Test]
  928. [NUnit.Framework.Category ("MobileNotWorking")]
  929. [ExpectedException (typeof (InvalidOperationException))]
  930. public void TestDoubleBeginOutputReadLine ()
  931. {
  932. using (Process p = new Process ()) {
  933. p.StartInfo = GetCrossPlatformStartInfo ();
  934. p.StartInfo.UseShellExecute = false;
  935. p.StartInfo.RedirectStandardOutput = true;
  936. p.StartInfo.RedirectStandardError = true;
  937. p.Start ();
  938. p.BeginOutputReadLine ();
  939. p.BeginOutputReadLine ();
  940. Assert.Fail ();
  941. }
  942. }
  943. [Test]
  944. [NUnit.Framework.Category ("MobileNotWorking")]
  945. [ExpectedException (typeof (InvalidOperationException))]
  946. public void TestDoubleBeginErrorReadLine ()
  947. {
  948. using (Process p = new Process ()) {
  949. p.StartInfo = GetCrossPlatformStartInfo ();
  950. p.StartInfo.UseShellExecute = false;
  951. p.StartInfo.RedirectStandardOutput = true;
  952. p.StartInfo.RedirectStandardError = true;
  953. p.Start ();
  954. p.BeginErrorReadLine ();
  955. p.BeginErrorReadLine ();
  956. Assert.Fail ();
  957. }
  958. }
  959. [Test]
  960. [NUnit.Framework.Category ("MobileNotWorking")]
  961. public void TestExitedRaisedTooSoon ()
  962. {
  963. if (!RunningOnUnix)
  964. Assert.Ignore ("using sleep command, only available on unix");
  965. int sleeptime = 5;
  966. using (Process p = Process.Start("sleep", sleeptime.ToString ())) {
  967. ManualResetEvent mre = new ManualResetEvent (false);
  968. p.EnableRaisingEvents = true;
  969. p.Exited += (sender, e) => {
  970. mre.Set ();
  971. };
  972. Assert.IsFalse (mre.WaitOne ((sleeptime - 2) * 1000), "Exited triggered before the process returned");
  973. }
  974. }
  975. #endif // MONO_FEATURE_PROCESS_START
  976. [Test]
  977. public void GetProcessesByName()
  978. {
  979. // This should return Process[0] or a Process[] with all the "foo" programs running
  980. Process.GetProcessesByName ("foo");
  981. }
  982. [Test]
  983. [ExpectedException(typeof(InvalidOperationException))]
  984. [NUnit.Framework.Category ("AndroidNotWorking")] //Getting the name of init works fine on Android, go figure.
  985. public void HigherPrivilegeProcessName ()
  986. {
  987. if (!RunningOnUnix)
  988. Assert.Ignore ("accessing pid 1, only available on unix");
  989. string v = Process.GetProcessById (1).ProcessName;
  990. }
  991. [Test]
  992. [NUnit.Framework.Category ("AndroidNotWorking")] //SELinux makes probing the parent process impossible
  993. public void NonChildProcessWaitForExit ()
  994. {
  995. if (!RunningOnUnix)
  996. Assert.Ignore ("accessing parent pid, only available on unix");
  997. using (Process process = Process.GetProcessById (getppid ()))
  998. using (ManualResetEvent mre = new ManualResetEvent (false))
  999. {
  1000. Assert.IsFalse (process.WaitForExit (10), "#1");
  1001. Assert.IsFalse (process.HasExited, "#2");
  1002. Assert.Throws<InvalidOperationException>(delegate { int exitCode = process.ExitCode; }, "#3");
  1003. process.Exited += (s, e) => mre.Set ();
  1004. process.EnableRaisingEvents = true;
  1005. Assert.IsFalse (mre.WaitOne (100), "#4");
  1006. Assert.IsFalse (process.WaitForExit (10), "#5");
  1007. Assert.IsFalse (process.HasExited, "#6");
  1008. Assert.Throws<InvalidOperationException>(delegate { int exitCode = process.ExitCode; }, "#7");
  1009. }
  1010. }
  1011. [Test]
  1012. [NUnit.Framework.Category ("AndroidNotWorking")] //SELinux makes probing the parent process impossible
  1013. public void NonChildProcessName ()
  1014. {
  1015. if (!RunningOnUnix)
  1016. Assert.Ignore ("accessing parent pid, only available on unix");
  1017. using (Process process = Process.GetProcessById (getppid ()))
  1018. {
  1019. string pname = process.ProcessName;
  1020. Assert.IsNotNull (pname, "#1");
  1021. AssertHelper.IsNotEmpty (pname, "#2");
  1022. }
  1023. }
  1024. [Test]
  1025. [NUnit.Framework.Category ("AndroidNotWorking")] //SELinux makes probing the parent process impossible
  1026. public void NonChildProcessId ()
  1027. {
  1028. if (!RunningOnUnix)
  1029. Assert.Ignore ("accessing parent pid, only available on unix");
  1030. int ppid;
  1031. using (Process process = Process.GetProcessById (ppid = getppid ()))
  1032. {
  1033. int pid = process.Id;
  1034. Assert.AreEqual (ppid, pid, "#1");
  1035. AssertHelper.Greater (pid, 0, "#2");
  1036. }
  1037. }
  1038. [DllImport ("libc")]
  1039. static extern int getppid();
  1040. }
  1041. }