2012-05-11 7 views
2

새 프로세스를 만들어야하지만 현재 프로세스가 아닌 다른 프로세스의 "자식"이되어야합니다. 예를 들어 새 프로세스를 다시 부모로 만듭니다. C#에서 STARTUPINFOEX를 사용하여 CreateProcess()를 호출하고 자식을 다시 부모로 만드는 방법

다음

거의 다 .NET : How to call CreateProcessAsUser() with STARTUPINFOEX from C#.NET : How to PInvoke UpdateProcThreadAttributehttp://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의 사용자 마샬링 오류가 포함됩니다.

모든 포인터가 많이 감사하겠습니다.

+0

Mabye http://stackoverflow.com/questions/1427196/net-how-to-pinvoke-updateprocthreadattribute I 시스템이 프로세스의 재 양육을 할 수 있도록 기대하지 않을 것이다, 몇 가지 유용한 정보 –

+1

을 가지고 있지만 ; 거대한 * 보안 문제처럼 보입니다. –

+0

피터 감사합니다. 나는 당신이 도움이되는 질문을 발견했지만, 나는 현재 그 순간에 대해서만 이야기합니다. 이 기사 http://winprogger.com/launching-a-non-child-process/는 내가 성취하고자하는 것이 가능해야 함을 나타냅니다. 나는 아마도 그 기사에서 C#으로 잘못 번역했을 것입니다. 나는 무엇을 알아낼 수없는 것 같습니다. –

답변

4

코드에 두 가지 문제가 있습니다. 먼저 InitializeProcThreadAttributeListUpdateProcThreadAttribute 함수의 lpAttributeList 매개 변수는 수정자를 사용하지 않고 IntPtr으로 입력해야합니다. 둘째, UpdateProcThreadAttribute 함수의 lpValue 매개 변수는 포인터의 값 (사용자의 경우 parentHandle)이 아니고 값 자체가되어야합니다. 아래는 고정 코드입니다.

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(
     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(
     IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool CloseHandle(IntPtr hObject); 

    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.cb = Marshal.SizeOf(sInfoEx); 
     IntPtr lpValue = IntPtr.Zero; 

     try 
     { 
      if (parentProcessId > 0) 
      { 
       var lpSize = IntPtr.Zero; 
       var success = InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); 
       if (success || lpSize == IntPtr.Zero) 
       { 
        return false; 
       } 

       sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize); 
       success = InitializeProcThreadAttributeList(sInfoEx.lpAttributeList, 1, 0, ref lpSize); 
       if (!success) 
       { 
        return false; 
       } 

       var parentHandle = Process.GetProcessById(parentProcessId).Handle; 
       // This value should persist until the attribute list is destroyed using the DeleteProcThreadAttributeList function 
       lpValue = Marshal.AllocHGlobal(IntPtr.Size); 
       Marshal.WriteIntPtr(lpValue, parentHandle); 

       success = UpdateProcThreadAttribute(
        sInfoEx.lpAttributeList, 
        0, 
        (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, 
        lpValue, 
        (IntPtr)IntPtr.Size, 
        IntPtr.Zero, 
        IntPtr.Zero); 
       if (!success) 
       { 
        return false; 
       } 
      } 

      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); 
     } 
     finally 
     { 
      // Free the attribute list 
      if (sInfoEx.lpAttributeList != IntPtr.Zero) 
      { 
       DeleteProcThreadAttributeList(sInfoEx.lpAttributeList); 
       Marshal.FreeHGlobal(sInfoEx.lpAttributeList); 
      } 
      Marshal.FreeHGlobal(lpValue); 

      // Close process and thread handles 
      if (pInfo.hProcess != IntPtr.Zero) 
      { 
       CloseHandle(pInfo.hProcess); 
      } 
      if (pInfo.hThread != IntPtr.Zero) 
      { 
       CloseHandle(pInfo.hThread); 
      } 
     } 
    } 

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