CreateProcessAsUser 用户上下文

问题描述 投票:0回答:2

我已经搜索了很长时间但还没有找到有效的解决方案:-(

我创建了一个窗口服务,它在使用 CreateProcessAsUser (http://www.pinvoke.net/default.aspx/advapi32/createprocessasuser.html)、WTSEnumerateSessions 等登录到计算机的每个用户上启动客户端。 ..

这已经很好用了。客户端在用户会话中启动,显示其任务栏图标,并且与服务的通信工作正常。

我遇到的问题是我需要让该客户端在用户的配置文件中存储临时文件。我尝试从一个小日志文件开始,以便我可以跟踪用户最终可能遇到的任何错误。不幸的是,我无法保存到用户的临时文件夹,因为客户端似乎在 LocalSystem 的上下文中运行,尽管 WindowsIdentity 显示了正确的用户:System.IO.Path.GetTempPath() 始终返回“C:\Windows\Temp”,但我的用户没有管理权限,因此他们无法在那里写入...此外,我计划将设置存储在当前用户的注册表中,但这也不起作用。我认为这在某种程度上与错误的临时路径有关。

我也尝试过 CreateEnvironmentBlock (http://www.pinvoke.net/default.aspx/userenv/CreateEnvironmentBlock.html),但我无法让它工作,我在某处发现一篇文章说这不再适用Vista 或更高版本,所以我停止研究那个。

为了测试,我通过这样做创建了一个小测试表单:

MessageBox.Show("Temp: " + System.IO.Path.GetTempPath() + Environment.NewLine + "User: " + WindowsIdentity.GetCurrent().Name, "Before impersonation");

WindowsIdentity currentUserId = WindowsIdentity.GetCurrent();
WindowsImpersonationContext impersonatedUser = currentUserId.Impersonate();

MessageBox.Show("Temp: " + System.IO.Path.GetTempPath() + Environment.NewLine + "User: " + WindowsIdentity.GetCurrent().Name, "After impersonation");

这个在模拟之前和之后总是显示相同的结果:

Temp: C:\Windows\Temp   User:testdomain\testuser
:-(

如果有帮助的话,这是我启动进程的函数(用户令牌由 WTSEnumerateSessions 传递) - 当然,这只适用于 LocalSystem 的上下文:

public static Process StartProcessAsUser(IntPtr UserToken, string App, string AppPath, string AppParameters)
{
    Process ResultProcess = null;

    IntPtr hDupedToken = IntPtr.Zero;
    NativeProcessAPI.PROCESS_INFORMATION oProcessInformation = new NativeProcessAPI.PROCESS_INFORMATION();

    try
    {
        NativeProcessAPI.SECURITY_ATTRIBUTES oSecurityAttributes = new NativeProcessAPI.SECURITY_ATTRIBUTES();
        oSecurityAttributes.Length = Marshal.SizeOf(oSecurityAttributes);

        bool result = NativeProcessAPI.DuplicateTokenEx(
              UserToken,
              NativeProcessAPI.GENERIC_ALL_ACCESS,
              ref oSecurityAttributes,
              (int)NativeProcessAPI.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
              (int)NativeProcessAPI.TOKEN_TYPE.TokenPrimary,
              ref hDupedToken
           );

        if (!result)
        {
            return null;
        }

        NativeProcessAPI.STARTUPINFO oStartupInfo = new NativeProcessAPI.STARTUPINFO();
        oStartupInfo.cb = Marshal.SizeOf(oStartupInfo);
        oStartupInfo.lpDesktop = String.Empty;

        result = NativeProcessAPI.CreateProcessAsUser(
                             hDupedToken,
                             null,
                             App + " " + AppParameters,
                             ref oSecurityAttributes, ref oSecurityAttributes,
                             false, 0, IntPtr.Zero,
                             AppPath, ref oStartupInfo, ref oProcessInformation
                       );

        if (result)
        {
            try
            {
                int ProcessID = oProcessInformation.dwProcessID;

                try
                {
                    ResultProcess = System.Diagnostics.Process.GetProcessById(ProcessID);
                }
                catch
                {
                    ResultProcess = null;
                }
            }
            catch (Exception ex)
            {
                ResultProcess = null;
            }
        }
    }
    catch
    {
        ResultProcess = null;
    }
    finally
    {
        if (oProcessInformation.hProcess != IntPtr.Zero)
            NativeProcessAPI.CloseHandle(oProcessInformation.hProcess);
        if (oProcessInformation.hThread != IntPtr.Zero)
            NativeProcessAPI.CloseHandle(oProcessInformation.hThread);
        if (hDupedToken != IntPtr.Zero)
            NativeProcessAPI.CloseHandle(hDupedToken);
    }

    return ResultProcess;
}

关于如何在用户上下文中而不是在本地系统上下文中启动进程有什么想法吗?

非常感谢!

c# windows windows-services createprocessasuser
2个回答
1
投票

将其留给其他想知道如何执行此操作的人:CreateEnvironmentBlock 是您需要使用的。

DuplicateTokenEx(userToken, MAXIMUM_ALLOWED | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, IntPtr.Zero, SecurityIdentification, TokenPrimary, out dupUserToken);
CreateEnvironmentBlock(out envBlock, dupUserToken, false);
CreateProcessAsUserW(dupUserToken, null, cmdLine, IntPtr.Zero, IntPtr.Zero, false,
            (uint)(CreateProcessFlags.CREATE_NEW_CONSOLE | CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT),
            envBlock, processDir, ref startupInfo, out procInfo);

0
投票

好的,我找到了解决方法:我通过使用 WindowsIdentity 提供的 SID 转而使用 USERS 配置单元,而不是 CURRENT_USER 配置单元:

Microsoft.Win32.Registry.Users.OpenSubKey(System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString() + ..., true)

虽然从用户的“环境”和“易失性环境”注册表路径获取环境变量而不是仅仅使用.Net的内置函数感觉有点不舒服,但它工作得很好......

但是非常感谢您的帮助;-)

编辑: 我不会将此标记为答案,因为它是 a) 我自己的解决方案和 b) 只是一种解决方法

© www.soinside.com 2019 - 2024. All rights reserved.