2015-12-17 7 views
5

मैं प्रतिरूपण के तहत Process.Start() का उपयोग करने की कोशिश कर रहा हूं, मेरे पास कुछ दिनों के लिए Google है, अधिकांश उत्तर मैं एएसपीनेट के अधीन था, लेकिन मैं विकास कर रहा हूं विंडो अनुप्रयोग के लिए, इसलिए मुझे मूल कारण खोजने में कठिनाई हो रही है।प्रक्रिया का उपयोग करें। प्रतिरूपण करते समय प्रारंभ करें (विंडो अनुप्रयोग)

यह मेरा impersonate कोड

 private void impersonateValidUser(string userName, string domain, string password) 
     { 
      WindowsIdentity tempWindowsIdentity = null; 
      IntPtr token = IntPtr.Zero; 
      IntPtr tokenDuplicate = IntPtr.Zero;    
      if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) 
      { 
       if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
       { 
        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); 
        mImpersonationContext = tempWindowsIdentity.Impersonate(); 
       } 
      } 
     } 

है और मैं अपने कार्यक्रम के माध्यम से दस्तावेज़ खोलने के लिए कोशिश कर रहा हूँ (कोई नहीं .exe, इस तरह के .txt, .doc के रूप में)

using (new Impersonator(DomainUserID, Domain, Password)) 
     Process.Start(filePath); 

अब तक मैं मैं प्रतिरूपित उपयोगकर्ता के साथ निर्देशिका/फ़ाइल का पता लगाने में सक्षम हूं, जो मेरे वर्तमान लॉगिन उपयोगकर्ता के लिए अदृश्य होने का अनुमान है क्योंकि मैंने इसे एक्सेस नहीं दिया है। लेकिन जब भी मैं दस्तावेज़ को खोलने का प्रयास, मैं मिलता है त्रुटि

System.ComponentModel.Win32Exception (0x80004005): Access is denied 

कृपया मुझे सही कर अगर मैं गलत कर रहा हूँ तो इस परिदृश्य में, मैं उपयोगकर्ता नाम के साथ झूठे (और processStartInfo को UseShellExecute स्थापित करने के लिए लगता है कि नहीं कर रहा हूँ और पासवर्ड इनपुट भी?) क्योंकि यह निष्पादन योग्य फ़ाइल (?) के लिए है, और मैं CreateProcessAsUser फ़ंक्शन के साथ भी आ गया हूं, और यह फ़ंक्शन मेरे मामले पर भी लागू नहीं होता है, उदाहरण के लिए मैंने इसे .exe के लिए पढ़ा है फाइल भी

कोई भी मुझे ज्ञान दे सकता है अगर सराहना की जाएगी।

अद्यतन: का रूप धारण वर्ग

public class Impersonator : IDisposable 
{ 
    #region P/Invoke 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern int LogonUser(string lpszUserName, 
             string lpszDomain, 
             string lpszPassword, 
             int dwLogonType, 
             int dwLogonProvider, 
             ref IntPtr phToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern int DuplicateToken(IntPtr hToken, 
               int impersonationLevel, 
               ref IntPtr hNewToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool RevertToSelf(); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    private static extern bool CloseHandle(IntPtr handle); 
    #endregion 

    #region Constants 
    private const int LOGON32_LOGON_INTERACTIVE = 2; 
    private const int LOGON32_PROVIDER_DEFAULT = 0; 
    #endregion 

    #region Attributes 
    private WindowsImpersonationContext mImpersonationContext = null; 
    #endregion 

    #region Public methods. 

    public Impersonator(string userName, string domainName, string password) 
    { 
     impersonateValidUser(userName, domainName, password); 
    } 

    #endregion 

    #region IDisposable member. 
    public void Dispose() 
    { 
     undoImpersonation(); 
    } 
    #endregion 

    #region Private member. 

    private void impersonateValidUser(string userName, string domain, string password) 
    { 
     WindowsIdentity tempWindowsIdentity = null; 
     IntPtr token = IntPtr.Zero; 
     IntPtr tokenDuplicate = IntPtr.Zero; 

     try 
     { 
      if (RevertToSelf()) 
      { 
       if (LogonUser(userName, domain, password, 
        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) 
       { 
        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
        { 
         tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); 
         mImpersonationContext = tempWindowsIdentity.Impersonate(); 
        } 
        else 
        { 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
        } 
       } 
       else 
       { 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 
      } 
      else 
      { 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
     } 
     finally 
     { 
      if (token != IntPtr.Zero) 
      { 
       CloseHandle(token); 
      } 
      if (tokenDuplicate != IntPtr.Zero) 
      { 
       CloseHandle(tokenDuplicate); 
      } 
     } 
    } 

    /// <summary> 
    /// Reverts the impersonation. 
    /// </summary> 
    private void undoImpersonation() 
    { 
     if (mImpersonationContext != null) 
     { 
      mImpersonationContext.Undo(); 
     } 
    } 

    #endregion 
} 
+0

क्या आप अपने प्रतिरूपण वर्ग के सभी कोड को पोस्ट कर सकते हैं – Thomas

+0

हाय, उत्तर के लिए thx, मैंने –

+0

प्रश्न में अपनी कक्षा अपडेट की है क्षमा करें मैंने आपके अपडेट को नहीं देखा है, मैं इन दो कार्यान्वयन की तुलना करने की कोशिश करूंगा। – Thomas

उत्तर

0

यहाँ पूरा वर्ग मैं का रूप धारण करने के लिए उपयोग उपयोगकर्ता:

var secure = new SecureString(); 
foreach (char c in "myclearpassword") 
{ 
    secure.AppendChar(c); 
} 

:

/// <summary> 
/// Provide a context to impersonate operations. 
/// </summary> 
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
public class Impersonate : IDisposable 
{ 
    /// <summary> 
    /// Initialize a new instance of the ImpersonateValidUser class with the specified user name, password, and domain. 
    /// </summary> 
    /// <param name="userName">The user name associated with the impersonation.</param> 
    /// <param name="password">The password for the user name associated with the impersonation.</param> 
    /// <param name="domain">The domain associated with the impersonation.</param> 
    /// <exception cref="ArgumentException">If the logon operation failed.</exception> 
    public Impersonate(string userName, SecureString password, string domain) 
    { 
     ValidateParameters(userName, password, domain); 
     WindowsIdentity tempWindowsIdentity; 
     IntPtr userAccountToken = IntPtr.Zero; 
     IntPtr passwordPointer = IntPtr.Zero; 
     IntPtr tokenDuplicate = IntPtr.Zero; 

     try 
     { 
      if (Kernel32.RevertToSelf()) 
      { 
       // Marshal the SecureString to unmanaged memory. 
       passwordPointer = Marshal.SecureStringToGlobalAllocUnicode(password); 

       if (Advapi32.LogonUser(userName, domain, passwordPointer, LOGON32_LOGON_INTERACTIVE, 
        LOGON32_PROVIDER_DEFAULT, ref userAccountToken)) 
       { 
        if (Advapi32.DuplicateToken(userAccountToken, 2, ref tokenDuplicate) != 0) 
        { 
         tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); 
         impersonationContext = tempWindowsIdentity.Impersonate(); 
         if (impersonationContext != null) 
         { 
          return; 
         } 
        } 
       } 
      } 
     } 
     finally 
     { 
      // Zero-out and free the unmanaged string reference. 
      Marshal.ZeroFreeGlobalAllocUnicode(passwordPointer); 

      // Close the token handle. 
      if (userAccountToken != IntPtr.Zero) 
       Kernel32.CloseHandle(userAccountToken); 
      if (tokenDuplicate != IntPtr.Zero) 
       Kernel32.CloseHandle(tokenDuplicate); 
     } 

     throw new ArgumentException(string.Format("Logon operation failed for userName {0}.", userName)); 
    } 

    /// <summary> 
    /// Reverts the user context to the Windows user represented by the WindowsImpersonationContext. 
    /// </summary> 
    public void UndoImpersonation() 
    { 
     impersonationContext.Undo(); 
    } 

    /// <summary> 
    /// Releases all resources used by <see cref="Impersonate"/> : 
    /// - Reverts the user context to the Windows user represented by this object : <see cref="System.Security.Principal.WindowsImpersonationContext"/>.Undo(). 
    /// - Dispose the <see cref="System.Security.Principal.WindowsImpersonationContext"/>. 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (impersonationContext != null) 
      { 
       //UndoImpersonation(); 
       impersonationContext.Dispose(); 
       impersonationContext = null; 
      } 
     } 
    } 

    private void ValidateParameters(string userName, SecureString password, string domain) 
    { 
     if (string.IsNullOrWhiteSpace(userName)) 
     { 
      throw new ArgumentNullException("userName"); 
     } 
     if (password == null || password.Length == 0) 
     { 
      throw new ArgumentNullException("password"); 
     } 
     if (string.IsNullOrWhiteSpace(userName)) 
     { 
      throw new ArgumentNullException("domain"); 
     } 
    } 

    private WindowsImpersonationContext impersonationContext; 

    private const int LOGON32_LOGON_INTERACTIVE = 2; 
    public const int LOGON32_PROVIDER_DEFAULT = 0; 
} 

यहां पर सुरक्षित स्ट्रिंग के लिए एक स्ट्रिंग कन्वर्ट करने के लिए तो आप इसका उपयोग इस तरह कर सकते हैं:

using (var imp = new Impersonate(DomainUserID, SecurePassword, Domain)) 
{ 
    Process.Start(filePath); 
} 
+0

, मैं इसे व्यवस्थापक भूमिका के रूप में प्रदान करता हूं, और दस्तावेज़ पर पूर्ण नियंत्रण प्रदान करता हूं, और मुझे उपयोगकर्ता को प्रदान करने की आवश्यकता है? –

+0

क्या उपयोगकर्ता को फ़ोल्डर पर अनुमति है? – Thomas

+0

हां, मैं उपयोगकर्ता को पूर्ण नियंत्रण प्रदान करता हूं, मैं प्रतिरूपण के माध्यम से जोड़ और निकाल सकता हूं, लेकिन मुझे समस्या को खोलने में समस्या है: -/ –

2

प्रतिरूपण करते समय आप UseShellExecute = true का उपयोग नहीं कर सकते। विंडोज़ में शेल निष्पादन कैसे काम करता है इस तरह से संबंधित है। असल में सबकुछ खोल को पास किया जाता है जो क्रिया को संभालने के तरीके को देखता है (आपके मामले में "खुला") और उसके बाद एप्लिकेशन को खोलने वाले उपयोगकर्ता के तहत शुरू होता है, जो प्रतिरूपित उपयोगकर्ता नहीं है - प्रतिरूपित उपयोगकर्ता नहीं करता है यदि कोई सत्र नहीं है तो वास्तव में एक खोल है!

हालांकि आप एक उपयोगकर्ता UseShellExecute के लिए documentation अभी भी अपने मामले में लागू होता है धारण करने के कारण एक अलग तंत्र का उपयोग करें:

UseShellExecute झूठी होना चाहिए अगर UserName संपत्ति शून्य या एक InvalidOperationException होगा नहीं है एक खाली स्ट्रिंग, या Process.Start(ProcessStartInfo) विधि कहा जाता है जब फेंक दिया जाता है।

इस समस्या को हल करने के लिए इस उत्तर में वर्णित अनुसार पंजीकृत एप्लिकेशन को देखना सबसे आसान हो सकता है: Finding the default application for opening a particular file type on Windows। संबंधित एप्लिकेशन के पथ के साथ आप अन्य उपयोगकर्ता के रूप में निष्पादन योग्य प्रारंभ कर सकते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे