programing

산란 과정의 자식이 되지 않고 새로운 과정을 시작합니다.

newstyles 2023. 5. 24. 21:45

산란 과정의 자식이 되지 않고 새로운 과정을 시작합니다.

호출 프로세스의 자식이 되지 않고 새로운 프로세스를 시작하려면 어떻게 해야 합니까?

예:

기본 프로그램(Caller.exe)

process.start("file.exe")

이미지:

여기에 이미지 설명 입력

산란 프로세스(부모)가 생성된 프로세스(자녀)보다 먼저 종료되면 부모-자녀 체인이 끊어집니다.이를 활용하려면 다음과 같은 중간 스텁 프로세스를 사용해야 합니다.

Caller.exe → Stub.exe → File.exe입니다.

여기서 Stub.exe는 File.exe를 시작한 후 바로 종료되는 간단한 실행 프로그램입니다.

프로세스를 시작하면 프로세스의 상위 항목이 됩니다.

대신 cmd.exe에서 프로세스를 시작할 수 있습니다. 그러니 cmd.exe가 부모가 됩니다.

Process proc = Process.Start(new ProcessStartInfo { Arguments = "/C explorer", FileName = "cmd", WindowStyle = ProcessWindowStyle.Hidden });

호출 프로세스의 파일을 삭제하고 새 파일로 바꾸는 업데이터 프로세스를 시작하려고 했습니다.설정별UseShellExecute = true호출 프로세스가 종료될 때 생성된 프로세스가 종료되는 것을 피할 수 있었습니다.

안에 있습니다.WPF를 사용하는 NetCore 3.0 애플리케이션.

var startInfo = new ProcessStartInfo("Updater.exe");
startInfo.UseShellExecute = true;
Process.Start(startInfo);
Environment.Exit(0);

부모 없이 새 프로세스를 실행합니다.

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);

의 문서는 다음과 같습니다.

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

그리고 그것은 말합니다.

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

독립적인 과정과 일치하는 것으로 보입니다.

그래서 문서에 따르면,Process.Start당신이 원하는 것을 해야 합니다.

저는 이 코드를 사용하고 있습니다.장점은 핀보케를 사용할 필요가 없다는 것입니다.나는 그것을 발견했습니다.CreateProcess와 함께 api.DETACHED_PROCESS플래그는 100% 신뢰할 수 없으며 부모가 사망할 때 자식 프로세스가 여전히 중단되는 경우가 있습니다.

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

System.Diagnostics.Process.Start()메서드 호출kernel32!CreateProcess()후드 밑에프로세스를 생성할 때kernel32!CreateProcess()공정 속성을 사용하여 다른 상위 항목을 지정할 수 있습니다.여기 C++로 작성된 함수가 있습니다. 어떻게 하는지는 잘 모르겠지만요.Net은 이러한 기능을 지원합니다.

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;
}

https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/ 에서 가져온 소스 코드

여기 제가 지금 사용하고 있는 코드가 있습니다.저는 그것이 누군가에게 유용할 수도 있다고 생각했습니다.하나의 인수를 허용합니다.인수는 실행할 파일의 경로로 디코딩되는 base64 인코딩 문자열입니다.

 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

언급URL : https://stackoverflow.com/questions/8434379/start-new-process-without-being-a-child-of-the-spawning-process