40

How would I go about starting a new process without it being the child of the calling process.

Example:

Main Program (Caller.exe)

process.start("file.exe")

Image:

enter image description here

Uwe Keim
  • 38,279
  • 56
  • 171
  • 280
Andrew Paglusch
  • 686
  • 1
  • 7
  • 16
  • 1
    Just of curiosity, what are the implications of it being a child process and not a parent? – MichaelS Dec 08 '11 at 17:11
  • If a user were to select "kill process tree" in the taskmanager, my entire application would not die. – Andrew Paglusch Dec 09 '11 at 12:26
  • 1
    Still smells like a [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem "What is the XY problem? - Meta Stack Exchange"). What is the real point of new process not being child of current, or circumvent "kill process tree"? – Stéphane Gourichon Mar 07 '18 at 09:36
  • You might want to create a "launcher" that starts a process and killing the "launcher" won't kill all of the processes that it launched. I think the solution was posted by Josh -- create stub launcher that (by-design) starts a process detached from the caller. – NeoH4x0r Feb 02 '22 at 21:24
  • Here is a "better" version of this question which describes things in more detail: https://stackoverflow.com/questions/12068647/creating-a-new-process-thats-not-a-child-of-the-creating-process/70967133 – Coconut Feb 03 '22 at 07:12

7 Answers7

24

If the spawning process (parent) ends before the spawned process (child) does, then the parent-child chain is broken. To make use of this, you'd have to use an intermediate stub-process like so:

Caller.exe → Stub.exe → File.exe.

Here Stub.exe is simple launcher program that ends just after starting File.exe.

Uwe Keim
  • 38,279
  • 56
  • 171
  • 280
Josh
  • 853
  • 7
  • 15
  • Thank you very much. I'm going to use this solution – Andrew Paglusch Dec 08 '11 at 21:12
  • Thank you for this. I ended up in a weird situation where I had a browser rendering a Java applet, which called an exe application, which in turn rendered an embedded IE component through `Webbrowser` control, and a target third party blackbox-type webpage running in this component was hanging until parent browser either gained back focus or was terminated. De-parenting .exe app from Java solved this completely. – Timekiller Jan 26 '17 at 13:42
  • The detached program can no longer be retrieved with `Process.GetProcesses()`? – Altiano Gerung Jul 31 '18 at 07:12
  • This does not answer the question. It is only teaching how to break the parent-child chain, not how to start a process without it being a child of the spawning process. – Coconut Jan 03 '22 at 08:00
  • @Coconut Process.start will create the process as a child of the caller -- therefore you must break the chain as Josh has described. Honestly, this should be the accepted answer/solution. – NeoH4x0r Feb 02 '22 at 21:28
  • @NeoH4x0r Yes, it's only a workaround, not the right answer to the question which reads "Start new process, without being a child of the spawning process". `System.Diagnostics.Process.Start()` method is really just `kernel32!CreateProcess()` under the hood. If you create a process with `kernel32!CreateProcess()` it allows you to specify a different parent by using a process attribute. I'm posting another answer with the source code describing that. – Coconut Feb 03 '22 at 07:15
14

If you start a process, then you'll be its parent.

Maybe you could try to start your process from cmd.exe instead, so cmd.exe will be the parent.

Process proc = Process.Start(new ProcessStartInfo { Arguments = "/C explorer", FileName = "cmd", WindowStyle = ProcessWindowStyle.Hidden });
ken2k
  • 46,953
  • 10
  • 113
  • 166
7

I have been trying to start a updater process which deletes the files of the calling process and replaces them with new ones. By setting UseShellExecute = true, I was able to circumvent the spawned process from exiting when the calling process exited.

This is inside a .Net Core 3.0 application using WPF.

var startInfo = new ProcessStartInfo("Updater.exe");
startInfo.UseShellExecute = true;
Process.Start(startInfo);
Environment.Exit(0);
Blightbuster
  • 351
  • 6
  • 15
  • This should be the accepted answer. It works in .net 5 as well. – D. Lockett Jul 04 '21 at 11:47
  • 1
    It should be noted that the default of UseShellExecute (is true on .Net framework apps and false on .Net core apps) -- so this probably wouldn't help the OP on VB.net -- since the default would be true, and child processes were still being killed when the parent died. – NeoH4x0r Feb 04 '22 at 18:27
  • 1
    Somehow this didn't work for me (.NET 6). The process is killed when my app closes, and it prints output into my Console App. – Luke Vo Feb 22 '22 at 16:06
6

This runs new process without parent:

System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
psi.FileName = @"cmd";
psi.Arguments = "/C start notepad.exe";
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
System.Diagnostics.Process.Start(psi);
Pawel P
  • 85
  • 1
  • 2
0

The documentation of Process.Start(string fileName) says

a new process that’s started alongside already running instances 
of the same process will be independent

and it says

Starting a process by specifying its file name is similar to 
typing the information in the Run dialog box of the Windows Start menu

which to me seems consistent with independent processes.

So according to the documentation, Process.Start should do what you desire.

JBSnorro
  • 5,182
  • 3
  • 34
  • 60
  • However, I ran into this problem because it want to spawn an independent child process, but it is spawned dependently through `Process.Start`. Then I tried isolating the behavior in a simple test project, where I concluded that `Process.Start` does indeed start the process independently. This makes me suspect there is something else which affects the behavior of `Process.Start` – JBSnorro Dec 20 '17 at 14:10
  • The MS docs says that is similar to typing into "run" only because the file doesn't have to be an exe and will automatically open in whater application has been configured for the file type. For example, Start("http://localhost") – NeoH4x0r Feb 04 '22 at 18:15
  • Running multiple instances of a process to make them independent ins't applicable when you only want to start a single instance. – NeoH4x0r Feb 04 '22 at 18:18
  • The OP mentions launching a [single instance] of a process -- not multiple instances of the same process.....hence the downvote. – NeoH4x0r Feb 05 '22 at 18:57
-1

Here is the code that I'm now using. I thought that it may be useful to someone. It accepts one argument. The argument is a base64 encoded string that decodes to the path of the file that you would like to run.

 Module Module1

    Sub Main()
        Dim CommandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = My.Application.CommandLineArgs
        If CommandLineArgs.Count = 1 Then
            Try
                Dim path As String = FromBase64(CommandLineArgs(0))
                Diagnostics.Process.Start(path)
            Catch
            End Try
            End
        End If
    End Sub

    Function FromBase64(ByVal base64 As String) As String
        Dim b As Byte() = Convert.FromBase64String(base64)
        Return System.Text.Encoding.UTF8.GetString(b)
    End Function

End Module
Andrew Paglusch
  • 686
  • 1
  • 7
  • 16
  • 3
    Your OP says nothing about base64 encoding, WTF? – FizxMike Jul 11 '17 at 20:02
  • 2
    This answer is 6 years old, so forgive me if I don't remember all of the details here. I believe the base64 decoding of the argument is an attempt to strip unwanted characters from the input file's path. The input path would obviously need to be base64 encoded prior to use with this code. Again, this is 6 years old, so I'm not sure if that's what I was after at the time. There's probably a better way of doing this, but I was still fairly new at the time of writing. – Andrew Paglusch Jul 11 '17 at 23:50
-2

System.Diagnostics.Process.Start() method calls kernel32!CreateProcess() under the hood. When creating a process with kernel32!CreateProcess() you can specify a different parent by using a process attribute. Here is a function written in C++ that does just that - although I'm not sure how .Net supports such features.

bool CreateProcessWithParent(DWORD parentId, PWSTR commandline) {
    auto hProcess = ::OpenProcess(PROCESS_CREATE_PROCESS, FALSE, parentId);
    if (!hProcess)
        return false;
 
    SIZE_T size;
    //
    // call InitializeProcThreadAttributeList twice
    // first, get required size
    //
    ::InitializeProcThreadAttributeList(nullptr, 1, 0, &size);
 
    //
    // now allocate a buffer with the required size and call again
    //
    auto buffer = std::make_unique<BYTE[]>(size);
    auto attributes = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(buffer.get());
    ::InitializeProcThreadAttributeList(attributes, 1, 0, &size);
 
    //
    // add the parent attribute
    //
    ::UpdateProcThreadAttribute(attributes, 0, 
        PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, 
        &hProcess, sizeof(hProcess), nullptr, nullptr);
 
    STARTUPINFOEX si = { sizeof(si) };
    //
    // set the attribute list
    //
    si.lpAttributeList = attributes;
    PROCESS_INFORMATION pi;
 
    //
    // create the process
    //
    BOOL created = ::CreateProcess(nullptr, commandline, nullptr, nullptr, 
        FALSE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, 
        (STARTUPINFO*)&si, &pi);
 
    //
    // cleanup
    //
    ::CloseHandle(hProcess);
    ::DeleteProcThreadAttributeList(attributes);
 
    return created;
}

Source code taken from https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/

Coconut
  • 1,394
  • 14
  • 21
  • This may work in the end -- but the OP didn't necessarily ask for a Windows-only solution. – NeoH4x0r Feb 04 '22 at 17:47
  • This answer has been downvoted not because it's invalid, but because it triggered other users who posted wrong answers. – Coconut Feb 08 '22 at 06:39
  • Come up with a "correct" platform-independent solution and I'll upvote it. – NeoH4x0r Feb 08 '22 at 23:56
  • The question never asked for a cross-platform solution. This is a valid answer therefore. – Coconut Feb 10 '22 at 00:41
  • The only problem is with someone who's so unintelligent that he cannot tell the sufficient condition from the necessary condition. – Coconut Feb 10 '22 at 00:43
  • OP asked for a c# / vb.net solution. Your suggesting making a new c++ solution and embed it in a project? This seems like a bloated solution at best. – Blightbuster May 10 '22 at 18:17