새 프로세스를 만들어야하지만 현재 프로세스가 아닌 다른 프로세스의 "자식"이되어야합니다. 예를 들어 새 프로세스를 다시 부모로 만듭니다. C#에서 STARTUPINFOEX를 사용하여 CreateProcess()를 호출하고 자식을 다시 부모로 만드는 방법
다음
거의 다 .NET : How to call CreateProcessAsUser() with STARTUPINFOEX from C# 및 .NET : How to PInvoke UpdateProcThreadAttribute 및 http://winprogger.com/launching-a-non-child-process/using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
public class ProcessCreator
{
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CreateProcess(
string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UpdateProcThreadAttribute(
out IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue,
IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool InitializeProcThreadAttributeList(
out IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);
public static bool CreateProcess(int parentProcessId)
{
const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;
var pInfo = new PROCESS_INFORMATION();
var sInfoEx = new STARTUPINFOEX();
sInfoEx.StartupInfo = new STARTUPINFO();
if (parentProcessId > 0)
{
var lpSize = IntPtr.Zero;
IntPtr dummyPtr;
var success = InitializeProcThreadAttributeList(out dummyPtr, 1, 0, ref lpSize);
if (success || lpSize == IntPtr.Zero)
{
return false;
}
sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
if (sInfoEx.lpAttributeList == IntPtr.Zero)
{
return false;
}
success = InitializeProcThreadAttributeList(out sInfoEx.lpAttributeList, 1, 0, ref lpSize);
if (!success)
{
return false;
}
var parentHandle = Process.GetProcessById(parentProcessId).Handle;
success = UpdateProcThreadAttribute(
out sInfoEx.lpAttributeList,
0,
(IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
parentHandle,
(IntPtr)IntPtr.Size,
IntPtr.Zero,
IntPtr.Zero);
if (!success)
{
return false;
}
sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
}
var pSec = new SECURITY_ATTRIBUTES();
var tSec = new SECURITY_ATTRIBUTES();
pSec.nLength = Marshal.SizeOf(pSec);
tSec.nLength = Marshal.SizeOf(tSec);
var lpApplicationName = Path.Combine(Environment.SystemDirectory, "notepad.exe");
return CreateProcess(lpApplicationName, null, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFOEX
{
public STARTUPINFO StartupInfo;
public IntPtr lpAttributeList;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
}
ProcessCreator.CreateProcess (0) 기본 동작입니다 현재 프로세스의 자식으로 메모장을 시작하는 나에게 가지고있다. 여태까지는 그런대로 잘됐다.
전달 된 값이 0이 아닌 경우 코드는 프로세스 ID가 입력 값과 일치하는 프로세스의 자식으로 메모장을 시작하려고 시도합니다 (현재 프로세스가 있다고 가정합니다).
은 불행하게도 그 부분이 작동 다음과 같은 예외가 발생하지 않습니다FatalExecutionEngineError가 감지 메시지 : 런타임 치명적인 오류가 발생했습니다. 오류의 주소는 0x69a2c7ad, 스레드 0x1de0에있었습니다. 오류 코드는 0xc0000005입니다. 이 오류는 CLR 또는 안전하지 않거나 확인할 수없는 사용자 코드 부분의 버그 일 수 있습니다. 이 버그의 일반적인 출처에는 스택을 손상시킬 수있는 COM-interop 또는 PInvoke의 사용자 마샬링 오류가 포함됩니다.
모든 포인터가 많이 감사하겠습니다.
Mabye http://stackoverflow.com/questions/1427196/net-how-to-pinvoke-updateprocthreadattribute I 시스템이 프로세스의 재 양육을 할 수 있도록 기대하지 않을 것이다, 몇 가지 유용한 정보 –
을 가지고 있지만 ; 거대한 * 보안 문제처럼 보입니다. –
피터 감사합니다. 나는 당신이 도움이되는 질문을 발견했지만, 나는 현재 그 순간에 대해서만 이야기합니다. 이 기사 http://winprogger.com/launching-a-non-child-process/는 내가 성취하고자하는 것이 가능해야 함을 나타냅니다. 나는 아마도 그 기사에서 C#으로 잘못 번역했을 것입니다. 나는 무엇을 알아낼 수없는 것 같습니다. –