如何强制Windows创建正在运行的用户的配置文件目录

时间:2016-10-14 19:18:15

标签: c# windows profile impersonation user-profile

我遇到了正在运行的流程的问题,其中流程的配置文件目录'用户尚未创建。

要解释,以下是有关如何发生这种情况的详细信息:

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

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

相信这是因为dsService在生成LoadUserProfile时未将childProcess标志设置为true,但我不确定。

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

编辑: 实验已确认,如果在另一个用户ID下启动进程,并且用户的配置文件目录不在那里(更具体地说,如果尚未创建用户的本地配置文件然而 - 只是删除一个预先存在的配置文件目录会创建一个不同的情况,我们对此无益感兴趣),然后(1)如果进程启动,则创建配置文件目录(以及一个假设,本地配置文件)将LoadUserProfile设置为true; (2)如果在dataService.getPermits设置为false的情况下启动进程,则不会创建概要文件目录(以及一个假设,本地概要文件)。这是有道理的,并且正如人们所期望的那样。

相关文章:stackoverflow.com/q/9008742/1082063

1 个答案:

答案 0 :(得分:0)

如果正在运行的帐户具有管理员权限,则以下代码将导致创建正在运行的帐户的配置文件,包括其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;
}

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