How do i detach an exe from Process.Start
Asked Answered
D

3

1

In a CodedUI Test, I am using System.Diagnostics.Process (Process.Start(exePath);) to execute a .exe file. Now my problem is, after Executing the test my application closes(WPF front-end). My question is, How will I get the process that I just started to independent from the thread where Process.Start() is executing so that once I the Test has ran the exe keeps running. I want it to keep running because there are other UI Tests that need the Front end Running. (Starting the exe at the beginning of each tests is too expensive and slow) I hope this is clear enough.

This is my code:

//[TestInitialize()] has already started the exe, so I have my front end open.



    [TestMethod]
        [TestCategory("Default Layout")]
        static void Move_StartTimer_Button_To_The_Top_Right_Corner_Keeps_Keeps_Button_Even_After_App_Restarts()
        {
            Process myExe = Process.GetProcesses().FirstOrDefault(process => process.ProcessName == "MyAppName");
            var fileName = myExe?.MainModule.FileName;
            UIMap.Click_Close_Application();
            Assert.IsTrue(Application_Closed_Sucessfully);
            Process.Start(fileName);
Assert.IsTrue(Application_Layout_Has_Button_On_The_Top_Right_Corner);
        }

When Move_StartTimer_Button_To_The_Top_Right_Corner_Keeps_Keeps_Button_Even_After_App_Restarts() has executed and completed, my app closes as well. How do I keep the front end running even after the execution? PLEASE NOTE: This is a CodedUI Test code, so by "after execution" I mean after the Test has ran (it may pass or fail it doesn't matter as long as it does not close the front end).

Dybbuk answered 19/1, 2017 at 9:9 Comment(8)
Process.Start() just starts a process - it doesn't ever stop a process.Hereditary
just start cmd with argument /C path/to/firefox.exeDownstroke
Your code -as is- won't compile. You're missing a ) after Contains("firefox"). Moreover, your question is still not clear. What do you mean by "Somewhere in between I close firefox before calling 'Process.Start()'"?Horsemint
why are you doing this? you can simply do Process.StartCorduroys
I'm sorry English is not my language so my grammar is very poor. Basically I'm testing "Default Layout" of my Application. This method is in a CodedUI test.. So I Start my application, do some changes, close the application, then start it again using Process.Start(). from there I want to see if the Layout remains as I have set it.. I just used firefox an example (my mistake)..Dybbuk
If it's a coded UI test, shouldn't you have a self-contained test? Why do you care if Firefox stays open? One could argue it should be terminated after your test.Karie
Hi all, I have edited my post 3 times now in attempt to make it clear as I'm desperate for this to work. Thanks in advanceDybbuk
See blogs.msdn.microsoft.com/visualstudioalm/2012/11/08/…Ceroplastics
K
3

Process.Start only starts a process of its own. It does not terminate the process at any time:

namespace ConsoleApplication5
{
  using System.Diagnostics;

  class Program
  {
    static void Main()
    {
      Process.Start("calc.exe");
    }
  }
}

This will start the calculator. The program itself will end but the calculator process is still running.

Karie answered 19/1, 2017 at 9:19 Comment(9)
This is correct, but now add [TestMethod] attribute at the top of Main. Once the test has ran, then the calculator closes.Dybbuk
@OlizWell Well, then don't do it? It's the point of a unit test to clean up after the fact.Karie
The point of the Test is the layout... If when the app was running I moved controls around, the tests confirms that when the app restarts controls are still where they were mode to.Dybbuk
Then surely it's ok for the browser to close after the test is done?Karie
Tests are in a playlist... if the app closes, then other tests will fail because the UI is not open. I get UIControl does not exist. My front end is not a browser, I was just making an example with firefox on how I get the .exe to start. Thanks for given feedback @KarieDybbuk
@OlizWell Your tests should be independent of one another. If a test needs something, it should create it. A test should never rely on the system being in a specified state at the start, it should create said state. With that in mind, it's perfectly fine and expected behavior for a test to clean up after it's done.Karie
absolutely correct. And I have all other tests setting them selves up properly, this was just 1 test working differently. I guess what I want could never be achieved.. Thanks for your help.Dybbuk
Well, if the other tests look like the one you posted, they do not set themselves up properly. They expect a certain state (app running). If you expect that as a prerequisite, each test has to make sure this is the case. Most likely by starting it themselves.Karie
I cant have each test starting the app.. that will just take forever. as things stand I have 345 CodedUI Tests and I cant get them to Run less than 90 minutes. So if each of these 345 started the front end as [TestInitialize] it could take hours to run my tests...Dybbuk
A
1

You are probably not looking in the right direction. Process.Start starts the process and the process has to manage its own termination unless you call the Kill method. See: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process

Did you try blocking your program (Console.ReadLine()) after you launched the process to check that the process actually survive?

Aligarh answered 19/1, 2017 at 9:18 Comment(1)
Hi Bruno, Please look at the question again... I have made a lot of changes to it because I messed up the question the first time no one could understand it. I have also give a snapshot of my actual code...Dybbuk
D
0

I am using this code. You can PInvoke the CreateProcess api with the DETACHED_PROCESS flag, but I have found it is not 100% reliable, the child process still sometimes dies when the parent dies.

https://github.com/dahall/taskscheduler

// you need two variables:
string fileName = ...
string arguments = ...

// Get the task service on the local machine
using TaskService ts = new();

// create task name
var taskName = "DetachedProcess_" + Convert.ToHexString(MD5.HashData(Encoding.UTF8.GetBytes(Path.GetFileName(fileName))));

// remove the task if it already exists
ts.RootFolder.DeleteTask(taskName, false);

// create a new task definition and assign properties
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "Detached process for " + fileName;

// create a trigger that will run the process in 5 seconds
td.Triggers.Add(new TimeTrigger(IPBanService.UtcNow.AddSeconds(5.0)));

// create the action to run the process
td.Actions.Add(new ExecAction(fileName, arguments, Path.GetDirectoryName(fileName)));

// delete task upon completion
td.Actions.Add(new ExecAction("schtasks.exe", "/Delete /TN \"" + taskName + "\" /F", null));

// register the task in the root folder
var task = ts.RootFolder.RegisterTaskDefinition(taskName, td);
task.Run(); // just run it now
Discommend answered 30/3, 2023 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.