C# Winform 模拟无法正常工作

Posted

技术标签:

【中文标题】C# Winform 模拟无法正常工作【英文标题】:C# Winform Impersonation fail to work 【发布时间】:2010-09-23 16:08:17 【问题描述】:

我刚刚花了 2 天时间阅读了一堆关于 C# 模拟的资料(包括 *** 和 codeproject 文章),这是我的调查结果。

简而言之,我只想从在标准(非特权)用户帐户下运行的 winform 应用程序启动和停止服务。我想用管理员帐户模拟我的用户。两个帐户都是本地帐户。

在下面的代码中,我在令牌检索期间(通过互操作调用)没有收到任何错误,但对 servicecontroller.Start 和 servicecontroller.Stop 的调用总是失败。

网络上的所有文章都描述了模拟用户的相同过程,但直到现在,我都无法让它发挥作用,甚至无法弄清楚出了什么问题。

有没有人知道那里出了什么问题...

提前致谢

--布鲁诺

     public partial class Form1 : Form

    public Form1()
    
        InitializeComponent();
    
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

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

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
        int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
    private void button1_Click(object sender, EventArgs e)
    


        WindowsImpersonationContext wic = ImpersonateUser(
                 "Administrator",
                 "machinename",
                 "password");

        try
        
            ServiceController sc = new ServiceController("SERVICE_PERE");
            Process p = new Process();


            sc.Start();
        
        catch (Exception ex)
        

            Debugger.Break();
        
        finally
        
            wic.Undo();
        


    

    private void button2_Click(object sender, EventArgs e)
    
        WindowsImpersonationContext wic = ImpersonateUser(
                 "Administrator",
                 "machinename",
                 "password");


        try
        

            ServiceController sc = new ServiceController("SERVICE_PERE");

            sc.Stop();
        
        catch (Exception ex)
        
            Debugger.Break();

        
        finally
        
            wic.Undo();
            //CodeAccessPermission.RevertAssert();
        
    
    public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
    
        // initialize tokens

        IntPtr pExistingTokenHandle = new IntPtr(0);
        IntPtr pDuplicateTokenHandle = new IntPtr(0);
        pExistingTokenHandle = IntPtr.Zero;
        pDuplicateTokenHandle = IntPtr.Zero;

        // if domain name was blank, assume local machine

        if (sDomain == "")
            sDomain = System.Environment.MachineName;

        try
        
            string sResult = null;

            const int LOGON32_PROVIDER_DEFAULT = 0;

            // create token

            const int LOGON32_LOGON_INTERACTIVE = 2;
            //const int SecurityImpersonation = 2;


            // get handle to token

            bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    ref pExistingTokenHandle);

            // did impersonation fail?

            if (false == bImpersonated)
            
                int nErrorCode = Marshal.GetLastWin32Error();
                sResult = "LogonUser() failed with error code: " +
                    nErrorCode + "\r\n";

                // show the reason why LogonUser failed

                //MessageBox.Show(this, sResult, "Error",
                //    MessageBoxButtons.OK, MessageBoxIcon.Error);
            

            // Get identity before impersonation

            sResult += "Before impersonation: " +
                WindowsIdentity.GetCurrent().Name + "\r\n";

            bool bRetVal = DuplicateToken(pExistingTokenHandle,
                2, ref pDuplicateTokenHandle);

            // did DuplicateToken fail?

            if (false == bRetVal)
            
                int nErrorCode = Marshal.GetLastWin32Error();
                // close existing handle

                CloseHandle(pExistingTokenHandle);
                sResult += "DuplicateToken() failed with error code: "
                    + nErrorCode + "\r\n";

                // show the reason why DuplicateToken failed

                //MessageBox.Show(this, sResult, "Error",
                //    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            
            else
            
                // create new identity using new primary token

                WindowsIdentity newId = new WindowsIdentity
                                            (pDuplicateTokenHandle);

                WindowsImpersonationContext impersonatedUser =
                                            newId.Impersonate();

                // check the identity after impersonation

                sResult += "After impersonation: " +
                    WindowsIdentity.GetCurrent().Name + "\r\n";

                //MessageBox.Show(this, sResult, "Success",
                //    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return impersonatedUser;
            
        
        catch (Exception ex)
        
            throw ex;
        
        finally
        
            // close handle(s)

            if (pExistingTokenHandle != IntPtr.Zero)
                CloseHandle(pExistingTokenHandle);
            if (pDuplicateTokenHandle != IntPtr.Zero)
                CloseHandle(pDuplicateTokenHandle);
        
    


public enum LogonType

    LOGON32_LOGON_INTERACTIVE = 2,
    LOGON32_LOGON_NETWORK = 3,
    LOGON32_LOGON_BATCH = 4,
    LOGON32_LOGON_SERVICE = 5,
    LOGON32_LOGON_UNLOCK = 7,
    LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
    LOGON32_LOGON_NEW_CREDENTIALS = 9,

public enum LogonProvider

    LOGON32_PROVIDER_DEFAULT = 0,

【问题讨论】:

【参考方案1】:

启动和停止服务需要管理员权限。您无法通过模拟绕过 UAC,您必须显示提升提示。 This answer 告诉你怎么做。

【讨论】:

好的,我去看看。谢谢你。

以上是关于C# Winform 模拟无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

更新查询无法正常工作c#winform

C# winform 控件拖动问题

使用 Outlook 2010 和 2013 C# 从 winform 实现发送邮件

C#与IE交互

C# 中winform判断URL打开是不是正常

C# winform 模拟键盘输入自动接入访问网络