2012-01-09 2 views
1

나는에 CreateProcessAsUser를 사용하여 Windows 서비스 (로컬 시스템)에서 구이 트레이 응용 프로그램을 시작하려고 - 그래서 같은 : 나는 그래서 기능을 사용하고에 CreateProcessAsUser - AccessViolationError

public static System.Diagnostics.Process StartProcessInSession(int sessionID, String commandLine) 
    { 
     IntPtr userToken; 
     if (WTSQueryUserToken(sessionID, out userToken)) 
     { 
      //note that WTSQueryUserToken only works when in context of local system account with SE_TCB_NAME 
      IntPtr lpEnvironment; 
      if (CreateEnvironmentBlock(out lpEnvironment, userToken, false)) 
      { 
       StartupInfo si = new StartupInfo(); 
       si.cb = Marshal.SizeOf(si); 
       si.lpDesktop = "winsta0\\default"; 
       si.dwFlags = STARTF.STARTF_USESHOWWINDOW; 
       si.wShowWindow = ShowWindow.SW_SHOW; 
       ProcessInformation pi; 
       if (CreateProcessAsUser(userToken, null, new StringBuilder(commandLine), IntPtr.Zero, IntPtr.Zero, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref si, out pi)) 
       { 
        CloseHandle(pi.hThread); 
        CloseHandle(pi.hProcess); 
        //context.Undo(); 
        try 
        { 
         return System.Diagnostics.Process.GetProcessById(pi.dwProcessId); 
        } 
        catch (ArgumentException e) 
        { 
         //The process ID couldn't be found - which is what always happens because it has closed 
         return null; 
        } 
       } 
       else 
       { 
        int err = Marshal.GetLastWin32Error(); 
        throw new System.ComponentModel.Win32Exception(err, "Could not create process.\nWin32 error: " + err.ToString()); 
       } 
      } 
      else 
      { 
       int err = Marshal.GetLastWin32Error(); 
       throw new System.ComponentModel.Win32Exception(err, "Could not create environment block.\nWin32 error: " + err.ToString()); 
      } 
     } 
     else 
     { 
      int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); 
      if (err == 1008) return null; //There is no token 
      throw new System.ComponentModel.Win32Exception(err, "Could not get the user token from session " + sessionID.ToString() + " - Error: " + err.ToString()); 
     } 
    } 

:

protected override void OnStart(string[] args) 
    { 
     _agentProcess = StartProcessInSession(WTSGetActiveConsoleSessionId(), "Some_correct_path"); 
    } 

이것은 실제로 잠시 동안 일했지만, 내 작업 중 하나에서 갑자기 작동이 멈췄습니다 ... CreateProccessAsUser 명령을 실행할 때 다음과 같은 오류가 나타납니다 (더 깊은 곳으로 이동하지 마십시오)

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."} 

왜 이런 일이 발생했는지, 또는 더 이상 디버깅하는 방법을 모릅니다. 어쨌든 어떤 생각이 있습니까? 이 doesnt는 나에게 어떤 의미라도 있기 때문에.

CreateProccessasuser 정의 :

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, [In] StringBuilder lpCommandLine, IntPtr /*to a SecurityAttributes struct or null*/ lpProcessAttributes, IntPtr /*to a SecurityAttributes struct or null*/ lpThreadAttributes, bool bInheritHandles, CreationFlags creationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation); 

감사

+0

'lpEnvironment'는 유효한 포인터로 설정되어 있습니까? 그리고'userToken'은 유효한'HANDLE'입니까? –

+0

어떻게'CreateProcessAsUser'를 정의 했습니까? –

+0

추가 정의. – Menyh

답변

1

당신의 ProcessInformation 유형이 값 형식 (구조체) 또는 참조 유형 (클래스)인가?

CreateProcessAsUser에 대한 정의 및 p/invoke 선언을 보여줍니다.

알아두기 올바른 속성을 사용하는 경우 모두 GetLastWin32Error p/invoke로 검사가 수행됩니다.

+0

[StructLayout (LayoutKind.Sequential)] 내부 구조체 ProcessInformation { \t \t # 지역 데이터 멤버 (4) 공개 INT dwProcessId; public int dwThreadId; 공개 IntPtr hProcess; 공개 IntPtr hThread; \t \t #endregion 데이터 멤버 } – Menyh