【问题标题】:How to force Windows to create the running user's profile directory如何强制 Windows 创建运行用户的配置文件目录
【发布时间】:2017-02-24 07:43:33
【问题描述】:

我遇到了一个正在运行的进程的问题,该进程的用户的配置文件目录尚未创建。

为了解释,这里是发生这种情况的详细信息:

我们运行一个大型分布式服务器网格,并且正在使用(部分)DataSynapse 在该网格上执行进程。对于熟悉 DataSynapse 的人,引擎被配置为使用“RunAs”运行特定服务,其中我们使用某个 AD 域服务帐户进行服务进程。我认为问题在于 DataSynapse 在“runas”下运行进程时没有设置LoadUserProfile 标志(也不应该设置)。无论确切原因是什么,如果“runas”服务帐户(和 AD 域帐户)从未登录到某些网格机器,那么这些机器将没有该帐户的用户配置文件目录。

对于那些不熟悉 DataSynapse 的人,这里有一个更通用的解释。在网格上的每台机器上,都有一个进程在运行,我将其称为dsService,它在本地机器的系统帐户(或具有提升的凭据的一些类似帐户)的凭据下运行。进程dsService 将生成一个子进程,例如childProcess,但它在我们的AD 域帐户的凭据下运行childProcess,我将其称为serviceUser。网格上有数千台机器,通常它们从不手动登录。特别是,配置文件目录C:\users\serviceUser 最初可能不存在。一旦创建一次,就没有其他问题了。但是,如果将新节点添加到网格中,通常它们最初不会有 C:\users\serviceUser。问题是当dsService 产生childProcess 时,C:\users\serviceUser 没有被创建,我们需要它。

相信这是因为dsService 在生成childProcess 时没有将LoadUserProfile 标志设置为真,尽管我不确定。

无论如何,childProcess 是我们控制下的 (.net) 进程(以serviceUser 运行),我想知道是否有办法(在 C# 中)childProcess可以强制操作系统创建正在运行的用户的配置文件目录 C:\users\serviceUser 当它确定它还不存在时?

编辑: 实验已经证实,如果一个人在另一个用户 ID 下启动一个进程,并且用户的配置文件目录不存在(更具体地说,如果用户的 本地配置文件尚未创建 - 只是删除一个预先存在的profile 目录创建了一种不同的情况,无论如何我们都不感兴趣),然后(1)如果进程在LoadUserProfile 设置为true 的情况下启动,则会创建配置文件目录(并且假设是本地配置文件); (2) 如果进程在LoadUserProfile 设置为false 的情况下启动,则不会创建配置文件目录(假设是本地配置文件)。这是有道理的,正如人们所期望的那样。

相关帖子:stackoverflow.com/q/9008742/1082063

【问题讨论】:

  • 您必须使用“用户目录”吗?这似乎是应该将其数据保存在自己的程序目录中的应用程序类型,或者只是在它在硬盘驱动器其他位置创建的目录中......
  • 不,您不能从用户的上下文中执行此操作。如果 DataSynapse 不提供创建用户配置文件的选项,并且您无法绕过存在用户配置文件的要求,则需要安排一些代码作为本地系统或其他适当特权帐户运行。
  • 不过,首先,您应该测试简单地创建配置文件实际上是否足够。如果您的代码要求配置文件被初始化 而不仅仅是加载,那么您将遇到更难的问题。初始化配置文件的唯一方法是让用户以交互方式登录。
  • @Elemental-Pete:同一个应用程序在不同的用户 ID 下运行,每个用户 ID 的数据必须与其他 ID 保持分离和隐藏。这是一项机构审计要求。虽然这可以通过特殊的目录来完成,但运行进程的 ID 不能拥有在他们自己的配置文件之外创建(或锁定)目录的权限。虽然我们可以为每个这样的用户 ID 创建一个特殊的目录,但这并没有让我们更进一步:我们仍然需要在每个 Grid Engine 上进行初步设置,在这种情况下,最好确保配置文件已设置。
  • @Harry-Johnston:我们已经测试过只需创建配置文件就足够了。事实上,到目前为止,我们一直在运行时没有创建配置文件,只使用特殊目录,正如上面 Elemental Pete 的建议。我们要做的就是避免需要通过使用配置文件目录在每台网格机器上设置(特别许可的)目录,该目录在创建时具有我们需要的权限。

标签: c# windows profile impersonation user-profile


【解决方案1】:

如果运行账号有管理员权限,下面的代码会导致创建运行账号的配置文件,包括它的UserProfile目录。没有管理员,我不知道是否可以:

using System.Runtime.InteropServices;
...
[DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int CreateProfile(
    [In] string pszUserSid,
    [In] string pszUserName,
    System.Text.StringBuilder pszProfilePath,
    int cchProfilePath);

....
public static string getUserProfilePath()
{
    string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
    if(string.IsNullOrWhiteSpace(userProfilePath) || !Directory.Exists(userProfilePath))
    {   //This will only work if we have admin...
        var pathBuf = new System.Text.StringBuilder(240);
        var Up = System.DirectoryServices.AccountManagement.UserPrincipal.Current;
        if( 0 == CreateProfile(Up.Sid.ToString(), Up.SamAccountName, pathBuf, pathBuf.Capacity) }
        {
            userProfilePath = pathBuf.ToString();
        }
    }
    return userProfilePath;
}

如果有人可以告诉我在帐户不是管理员时如何执行此操作,他们的答案将被接受为正确答案。在那之前,这至少会给其他人一些想法。

【讨论】:

    猜你喜欢
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2016-05-16
    • 1970-01-01
    • 2013-09-25
    • 2015-06-24
    • 1970-01-01
    相关资源
    最近更新 更多