在另一个用户上下文中执行代码

时间:2010-06-04 13:10:39

标签: c# .net winapi pinvoke uac

我的应用程序带有需要以管理员身份运行的清单,但应用程序的一部分是使用WNetAddConnection2映射驱动器,我相信由于凭据等原因需要在正常的用户环境中运行。有没有办法在普通用户上下文中执行这段代码而不创建单独的进程。

修改

从评论中我得到了这么多,但它不起作用。我预计它不会因为我真的不明白我应该如何使用它。也许最好是我打开一个新问题?

class Program
{
    [DllImport("advapi32.DLL")]
    public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
    [DllImport("advapi32.DLL")]
    public static extern bool RevertToSelf();

    static void Main(string[] args)
    {
        IntPtr phToken = IntPtr.Zero;
        ImpersonateLoggedOnUser(phToken);
        MapDrives();
        RevertToSelf();
    }
}

修改

如果当前用户具有管理员权限,那么主进程将使用清单提升,在提升的代码中我想在用户非提升空间中运行命令,因为它似乎具有不同的环境变量等。相信一旦线程启动它就无法改变自己,它需要运行一个新线程。

3 个答案:

答案 0 :(得分:4)

查看A small C# Class for impersonating a User代码项目文章。它实现了一个IDisposable类(在使用后释放身份验证令牌)。我已经看到.NET代码泄漏是因为没有发布模拟令牌。

您只能为一个代码块模拟用户,该代码块将访问您需要以其他用户身份访问的网络资源。您的代码看起来像

using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
{
   /* code that executes under the new context */
   ...
}

我希望它有所帮助。

答案 1 :(得分:1)

首先,您需要获取要启动应用的用户令牌,您可以使用WTSQueryUserToken执行此操作。如果用户尚未登录,您可以使用LogonUser Win32 API在新会话中获取新的。要获取计算机上的所有会话,您可以使用WTSEnumerateSessions

然后,一旦获得令牌,您就可以使用CreateProcessAsUser或其他ImpersonateLoggedOnUser Win32 API。

请确保在您获得的手柄上调用CloseHandle,这类工作特别容易泄漏。

答案 2 :(得分:0)

我不确定这是一种在不创建新进程的情况下执行此操作的方法,ImpersonateLoggedOnUser只能在服务中运行,而且我不想提供凭据。

如果我错了,请纠正我