首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CreateProcessAsUser用户上下文

CreateProcessAsUser用户上下文
EN

Stack Overflow用户
提问于 2014-02-17 20:32:51
回答 2查看 2.3K关注 0票数 1

我已经寻找了很长时间,但还没有找到一个可行的解决方案:-(

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

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

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

我也尝试过CreateEnvironmentBlock (http://www.pinvoke.net/default.aspx/userenv/CreateEnvironmentBlock.html),但我不能让它工作,我发现有一篇文章说这在Vista或更高版本上不能再工作了,所以我停止了对它的研究。

为了进行测试,我创建了一个小的测试表单来执行以下操作:

代码语言:javascript
复制
        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提供)--当然,这只适用于本地系统的上下文:

代码语言:javascript
复制
    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;
    }

你知道如何在用户的上下文中而不是LocalSystem的上下文中启动我的进程吗?

非常感谢!

EN

回答 2

Stack Overflow用户

发布于 2017-03-02 22:33:29

把这个留给其他想知道怎么做的人吧: CreateEnvironmentBlock是你需要用到的。

代码语言:javascript
复制
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);
票数 1
EN

Stack Overflow用户

发布于 2014-02-18 16:32:26

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

代码语言:javascript
复制
Microsoft.Win32.Registry.Users.OpenSubKey(System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString() + ..., true)

虽然从用户的“环境”和“易失性环境”注册表路径中获取环境变量而不是只使用.Net的内置函数会让人感觉有点不舒服,但这种方法工作得很好……

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

编辑:我不会将此标记为答案,因为这是a)我自己的解决方案,b)只是变通方法

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21829228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档