【问题标题】:passing code to a function as parameter within "using statement"在“使用语句”中将代码作为参数传递给函数
【发布时间】:2014-02-25 04:53:29
【问题描述】:

这段代码很适合我:

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

    [DllImport("kernel32.dll")]
    public static extern bool CloseHandle(IntPtr token);

enum LogonType
    {
        Interactive = 2,
        Network = 3,
        Batch = 4,
        Service = 5,
        Unlock = 7,
        NetworkClearText = 8,
        NewCredentials = 9
    }
    enum LogonProvider
    {
        Default = 0,
        WinNT35 = 1,
        WinNT40 = 2,
        WinNT50 = 3
    }

private void Button1_Click()
    { 
        IntPtr token = IntPtr.Zero;
        LogonUser("Administrator",
                  "192.168.1.244",
                  "PassWord",
                  (int)LogonType.NewCredentials,
                  (int)LogonProvider.WinNT50,
                  ref token);
        using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))
        {
    CloseHandle(token);
    /*
    Code_of_Do_Something
    */
    }
}

但是...这意味着每次我需要进行模拟(在远程机器上做某事=服务器)时,我都必须重复“Button1_Click()”中的最后一个代码。 所以我的问题是:有可能做这样的插图吗?:

【问题讨论】:

  • 您也可以返回上下文值(WindowsIdentity.Impersonate)并自行处理。
  • CloseHandle 不应该在 代码之后吗?事实上,它不应该在它自己的finally 块内,这样它就会一直被执行吗?
  • 同意。你有什么证据可以在那里打电话给CloseHandle?如果WindowsIdentity.Impersonate() 失败,那么你根本就不会调用它。

标签: c# impersonation using-statement


【解决方案1】:

您可以为此目的使用委托。最简单的方法是使用ActionFunc。如果您不需要返回值,请使用Action

private void RunImpersonated(Action act)
{
    IntPtr token = IntPtr.Zero;
    LogonUser("Administrator",
              "192.168.1.244",
              "PassWord",
              (int)LogonType.NewCredentials,
              (int)LogonProvider.WinNT50,
              ref token);
    try
    {
        using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))
        {
            // Call action
            act();
        }
    }
    finally
    {
        CloseHandle(token);
    }
}

请注意,泛型类型参数有很多变体,允许您以强类型方式向ActionFunc 委托提供参数。例如,如果您需要一个 into 参数,请使用 Action<int> 而不仅仅是 Action

另外请注意,我创建了一个 finally 块,无论是否发生异常都会关闭句柄。

为了调用函数,可以使用 lambda 表达式:

private void button1_Click(object sender, EventArgs e)
{
    RunImpersonated(() => {
        DirectoryInfo dir = new DirectoryInfo( @"\\192.168.1.244\repository");
        foreach (DirectoryInfo di in dir.GetDirectories()) 
        { 
            lable_folders_count.Text = Convert.ToString(dir.GetFileSystemInfos().Length); 
        }
    });
}

【讨论】:

  • 我可以知道将这段代码放在一个动作中吗? code DirectoryInfo dir = new DirectoryInfo(@"\\192.168.1.244\repository); foreach (DirectoryInfo di in dir.GetDirectories()) { lable_folders_count.Text = Convert.ToString(dir.GetFileSystemInfos().Length); } code
  • @CrownFord:我更新了帖子并包含了一个示例。希望对您有所帮助。
  • 我得到了这个错误:“方法必须有一个返回类型”关于:RunImpersonated(()
  • @CrownFord:错误显示在哪里?在公共 void RunImpersonated(Action act) 或您调用 RunImpersonated 的地方?
  • 请从这里查看屏幕截图:link
【解决方案2】:

是的,可以将代码作为参数传递。但是让我们在不使用 lambda 的情况下解决您的问题:

private void Button1_Click()
{
    using(GetImpersonationContext())
    {
        /* code here */
    } 
}
private WindowsImpersonationContext GetImpersonationContext()
{
    IntPtr token = IntPtr.Zero;
    LogonUser("Administrator",
              "192.168.1.244",
              "PassWord",
              (int)LogonType.NewCredentials,
              (int)LogonProvider.WinNT50,
              ref token);

    WindowsImpersonationContext context = WindowsIdentity.Impersonate(token);
    CloseHandle(token);
    return context;
}

【讨论】:

  • 它工作正常,thanx...只需要从)); 表单WindowsIdentity.Impersonate(token); 中删除最后一个双精度数之一
猜你喜欢
  • 1970-01-01
  • 2013-01-27
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 2020-11-24
  • 2021-04-13
相关资源
最近更新 更多