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