2017-11-17 1 views
0

제목이 약간 혼란 스럽습니다. 그래서 내 주요 문제는 이것이다 :process.start로 시작된 응용 프로그램에서 Outlook interlop 실행 중

내가 업데이트 기능 후 다른 app.And를 업데이트하는 응용 프로그램이 종료가 Process.Start를 방법과 다른 응용 프로그램을 시작했다

Process.Start(@"C:\Program Files (x86)\XMLMailService\XMLMailWF.exe"); 

이 두 번째 업데이트 프로그램 전송 간단한 전망 interlop를 가진 우편물

Microsoft.Office.Interop.Outlook.Application OutlookObject = new Microsoft.Office.Interop.Outlook.Application(); 
       Microsoft.Office.Interop.Outlook.MailItem MailObject = (Microsoft.Office.Interop.Outlook.MailItem)(OutlookObject.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem)); 
       MailObject.To = txtkime.Text; 
       MailObject.Subject = psubj; 
       MailObject.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceNormal; 
       MailObject.HTMLBody = pbody; 
       MailObject.Attachments.Add(pdfyolu); 
       MailObject.Send(); 

실제로 문제는 부호 관련이 아니다. 그러나 Outlook 코드는 두 번 클릭하여 앱을 시작할 때 매력처럼 작동합니다. 하지만 this 오류가 발생합니다.

그래서 앱이 process.start로 시작하면 Outlook interlop에서 오류가 발생하는 이유는 무엇입니까? 80080005 서버 실행이 HRESULT에서 (예외 실패 :

편집 : 다음 오류로 인해 CLSID {0006F03A-0000-0000-C000-000000000046}과 구성 요소의 COM 클래스 팩터 리를 검색 오류 번역 =>

실패 : 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

+1

오류 메시지를 영어로 번역하거나 번역 할 수 있도록 텍스트로 추가해야합니다. – Shah

+0

Process.Start를 사용하여 XMLMailWF.exe를 시작할 다른 응용 프로그램의 유형은 무엇입니까? 즉, 데스크톱 winforms/wpf, 콘솔, Windows 서비스? – Shah

답변

0

누구나 동일한 해결책을 찾은 상황입니다.

첫 번째 앱이 zip 파일을 다운로드하고 압축을 해제합니다. 압축을 풀고 조정을 한 후 다운로드 한 앱을 process.start ("...") 메소드로 시작합니다.

여기에서 문제가 발생했습니다. 1) 첫 번째 앱에는 관리자 권한이 필요합니다. Process.Start를 사용하면 관리자 권한으로 두 번째 앱을 시작합니다. 2) 두 번째 앱은 Outlook 클라이언트의 메일을 보조 기능으로 전송합니다. Outlook은 자동화 응용 프로그램을 좋아하지 않습니다. 당신이 관리자로 Outlook interlop를 사용하려고하면 COM 오류가 발생합니다. Outlook은 관리자 권한이없는 Outlook을 사용합니다. 관리자의 모드로 검색 기능이 작동하지 않기 때문에 (일반 사용자는 이유를 알고 있습니다)

두 가지 해결책이 있습니다.

1) 관리자 권한없이 첫 번째 앱을 시작할 수 있습니다. 관리자 권한으로 앱의 다른 인스턴스를 시작하여 일종의 데이터를 반환하여 첫 번째 인스턴스에 작업 완료를 알립니다. 그런 다음 첫 번째 인스턴스는 관리자 권한없이 process.start를 사용할 수 있습니다. 그러나 첫 번째 앱이 많은 컴퓨터에 설치되어 있고 게으른 사람이기 때문에 이것은 적합하지 않습니다. 그래서 ı 어려운 방법을 선택하십시오. 2) 관리자 권한없이 두 번째 앱을 다시 시작할 수 있습니다. here

public static class UserRights 
{ 


    public static void RunAsDesktopUser(string fileName) 
    { 
     if (string.IsNullOrWhiteSpace(fileName)) 
      throw new ArgumentException("Value cannot be null or whitespace.", nameof(fileName)); 

     // To start process as shell user you will need to carry out these steps: 
     // 1. Enable the SeIncreaseQuotaPrivilege in your current token 
     // 2. Get an HWND representing the desktop shell (GetShellWindow) 
     // 3. Get the Process ID(PID) of the process associated with that window(GetWindowThreadProcessId) 
     // 4. Open that process(OpenProcess) 
     // 5. Get the access token from that process (OpenProcessToken) 
     // 6. Make a primary token with that token(DuplicateTokenEx) 
     // 7. Start the new process with that primary token(CreateProcessWithTokenW) 

     var hProcessToken = IntPtr.Zero; 
     // Enable SeIncreaseQuotaPrivilege in this process. (This won't work if current process is not elevated.) 
     try 
     { 
      var process = GetCurrentProcess(); 
      if (!OpenProcessToken(process, 0x0020, ref hProcessToken)) 
       return; 

      var tkp = new TOKEN_PRIVILEGES 
      { 
       PrivilegeCount = 1, 
       Privileges = new LUID_AND_ATTRIBUTES[1] 
      }; 

      if (!LookupPrivilegeValue(null, "SeIncreaseQuotaPrivilege", ref tkp.Privileges[0].Luid)) 
       return; 

      tkp.Privileges[0].Attributes = 0x00000002; 

      if (!AdjustTokenPrivileges(hProcessToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero)) 
       return; 
     } 
     finally 
     { 
      CloseHandle(hProcessToken); 
     } 

     // Get an HWND representing the desktop shell. 
     // CAVEATS: This will fail if the shell is not running (crashed or terminated), or the default shell has been 
     // replaced with a custom shell. This also won't return what you probably want if Explorer has been terminated and 
     // restarted elevated. 
     var hwnd = GetShellWindow(); 
     if (hwnd == IntPtr.Zero) 
      return; 

     var hShellProcess = IntPtr.Zero; 
     var hShellProcessToken = IntPtr.Zero; 
     var hPrimaryToken = IntPtr.Zero; 
     try 
     { 
      // Get the PID of the desktop shell process. 
      uint dwPID; 
      if (GetWindowThreadProcessId(hwnd, out dwPID) == 0) 
       return; 

      // Open the desktop shell process in order to query it (get the token) 
      hShellProcess = OpenProcess(ProcessAccessFlags.QueryInformation, false, dwPID); 
      if (hShellProcess == IntPtr.Zero) 
       return; 

      // Get the process token of the desktop shell. 
      if (!OpenProcessToken(hShellProcess, 0x0002, ref hShellProcessToken)) 
       return; 

      var dwTokenRights = 395U; 

      // Duplicate the shell's process token to get a primary token. 
      // Based on experimentation, this is the minimal set of rights required for CreateProcessWithTokenW (contrary to current documentation). 
      if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out hPrimaryToken)) 
       return; 

      // Start the target process with the new token. 
      var si = new STARTUPINFO(); 
      var pi = new PROCESS_INFORMATION(); 
      if (!CreateProcessWithTokenW(hPrimaryToken, 0, fileName, "", 0, IntPtr.Zero, Path.GetDirectoryName(fileName), ref si, out pi)) 
       return; 
     } 
     finally 
     { 
      CloseHandle(hShellProcessToken); 
      CloseHandle(hPrimaryToken); 
      CloseHandle(hShellProcess); 
     } 

    } 

    #region Interop 

    private struct TOKEN_PRIVILEGES 
    { 
     public UInt32 PrivilegeCount; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] 
     public LUID_AND_ATTRIBUTES[] Privileges; 
    } 

    [StructLayout(LayoutKind.Sequential, Pack = 4)] 
    private struct LUID_AND_ATTRIBUTES 
    { 
     public LUID Luid; 
     public UInt32 Attributes; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct LUID 
    { 
     public uint LowPart; 
     public int HighPart; 
    } 

    [Flags] 
    private enum ProcessAccessFlags : uint 
    { 
     All = 0x001F0FFF, 
     Terminate = 0x00000001, 
     CreateThread = 0x00000002, 
     VirtualMemoryOperation = 0x00000008, 
     VirtualMemoryRead = 0x00000010, 
     VirtualMemoryWrite = 0x00000020, 
     DuplicateHandle = 0x00000040, 
     CreateProcess = 0x000000080, 
     SetQuota = 0x00000100, 
     SetInformation = 0x00000200, 
     QueryInformation = 0x00000400, 
     QueryLimitedInformation = 0x00001000, 
     Synchronize = 0x00100000 
    } 

    private enum SECURITY_IMPERSONATION_LEVEL 
    { 
     SecurityAnonymous, 
     SecurityIdentification, 
     SecurityImpersonation, 
     SecurityDelegation 
    } 

    private enum TOKEN_TYPE 
    { 
     TokenPrimary = 1, 
     TokenImpersonation 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_INFORMATION 
    { 
     public IntPtr hProcess; 
     public IntPtr hThread; 
     public int dwProcessId; 
     public int dwThreadId; 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    private 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; 
    } 

    [DllImport("kernel32.dll", ExactSpelling = true)] 
    private static extern IntPtr GetCurrentProcess(); 

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 
    private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool LookupPrivilegeValue(string host, string name, ref LUID pluid); 

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 
    private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TOKEN_PRIVILEGES newst, int len, IntPtr prev, IntPtr relen); 

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


    [DllImport("user32.dll")] 
    private static extern IntPtr GetShellWindow(); 

    [DllImport("user32.dll", SetLastError = true)] 
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, uint processId); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL impersonationLevel, TOKEN_TYPE tokenType, out IntPtr phNewToken); 

    [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] 
    private static extern bool CreateProcessWithTokenW(IntPtr hToken, int dwLogonFlags, string lpApplicationName, string lpCommandLine, int dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 

    #endregion 


} 
에 설명 된대로

그래서 나는 here에 설명 된 앱

static class Program 
{ 

    public static bool IsAdministrator() 
    { 
     var identity = WindowsIdentity.GetCurrent(); 
     var principal = new WindowsPrincipal(identity); 
     return principal.IsInRole(WindowsBuiltInRole.Administrator); 
    } 

    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     if (IsAdministrator()) 
     { 
      UserRights.RunAsDesktopUser(@"C:\Program Files (x86)\XMLMailService\XMLMailWF.exe"); 
      Form1.benciktim = true; 
      Application.Exit(); 
     } 
     else 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 

    } 
} 

를 다시 시작처럼 관리자 권한 확인이 코드를 사용하고 코드의 화려한 조각을 사용 (어느 까다 롭습니다)

1

이것은 관리자 권한 또는 Outlook과 아무 관련이 없습니다. COM은 다른 보안 컨텍스트에서 실행되는 프로세스간에 호출을 마샬링하는 것을 거부합니다. 이로 인해 권한 상승 공격이 발생할 수 있습니다. Outlook은 싱글 톤이기 때문에 새로운 COM 개체가 생성되지 않습니다. 호출은 단순히 다른 보안 컨텍스트에서 실행되는 이미 실행중인 인스턴스로 전달됩니다.

관련 문제