如何以编程方式导致创建新的Windows用户的个人资料?


20

我正在为Windows服务创建(本地)用户运行。我有充分的理由不想使用网络服务,本地服务或本地系统。

我通过创建用户net user foobar "Abcd123!" /add-效果很好。

此时,c:\users\foobar尚不存在。

如果创建了用户的主目录,则在用户登录(或更确切地说,是针对用户的服务)或启动用户要使用的服务之前,Windows会创建一个名为“邻家用户配置文件”的邻家服务器c:\users\foobar-{gibberish/SID/whatever}-这不是可预测的名称。

我需要用户的主目录包含诸如.ssh目录之类的东西,.gitconfig-这样的工具(不限于那些工具),这些工具假设它将是一个使用它们的人,因此用户配置应包含在内~/...。通常,工具来自Unix。

实际问题

那么-是否存在一种编程方式(最好是PowerShell或现成的命令行)来告诉Windows为本地用户创建用户配置文件?

或者,还有其他解决方法吗?

我尚未尝试的事情:

  • 一个NSSM启动/预挂钩,通过Windows启动该服务,创建用户配置文件,然后将控制权交给运行该挂钩的NSSM包装程序,从而在启动之前将文件从其他位置复制到当前希望存在的用户配置文件目录中。
  • 将服务的USERPROFILE环境变量设置为实际用户配置文件目录之外的其他位置。这使我觉得是危险的越野滑雪,但也可以正常工作。

其他背景:

  • Windows Server 2016,桌面体验。
    • 不能使用Core / Nano。
  • 没有正在使用的活动目录。不会的。
  • 这些是本地用户。
  • 我正在通过Ansible进行此操作,后者在Windows的后台使用PowerShell。特别是带有Ansible 2.7.5 的win_user模块。
  • 我不想创建一个C:\users\default(等效于/etc/skel),因为有几个不同的服务用户,并且一个大小无法容纳所有用户。这也不会影响用户配置文件的创建时间,只会影响创建时的内容。
  • 我正在使用NSSM来管理服务。

我尝试过的事情

  • 启动服务并允许Windows创建目录
    • 我不想这样做,因为该服务在启动之前需要秘密,因此,如果我在图像烘焙过程中执行此操作,则需要清理它们,并确保我的服务不起作用烘烤阶段的任何工作。我想避免这两个小问题。

1
您是否检查过选项net user(例如/HOMEDIR/PROFILEPATH)?。请参阅net user /help。根据我的(未经测试的)理解,您可以为用户创建一个目录,并使用/HOMEDIR开关将其设置为homedir 。
斯文

请问您有什么用例可以避免Active Directory?使用AD,事情会容易得多。只是好奇。
Ondrej Tucny

我避免使用AD,因为这些机器都是短暂的。寿命以小时为单位,而不是以天为单位。这些机器托管无尘室构建环境。随身携带一台AD进出AD的机器是不值得的(如果您有兴趣的话,也请参阅medium.com/palantir/active-directory-as-code-e9666a2e548d)。
Peter Mounce

@Sven是-遗憾的是,即使它们设置了路径,也不会导致配置文件本身的创建。
Peter Mounce

Answers:


23

Windows可以使用CreateProfile API 按需创建用户配置文件

但是,如果不想创建可执行文件来执行此操作,则可以在PowerShell中调用API。其他人已经做到了:github上的示例

代码的相关部分:

$methodName = 'UserEnvCP'
$script:nativeMethods = @();

Register-NativeMethod "userenv.dll" "int CreateProfile([MarshalAs(UnmanagedType.LPWStr)] string pszUserSid,`
  [MarshalAs(UnmanagedType.LPWStr)] string pszUserName,`
  [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath, uint cchProfilePath)";

Add-NativeMethods -typeName $MethodName;

$localUser = New-Object System.Security.Principal.NTAccount("$UserName");
$userSID = $localUser.Translate([System.Security.Principal.SecurityIdentifier]);
$sb = new-object System.Text.StringBuilder(260);
$pathLen = $sb.Capacity;

Write-Verbose "Creating user profile for $Username";
try
{
    [UserEnvCP]::CreateProfile($userSID.Value, $Username, $sb, $pathLen) | Out-Null;
}
catch
{
    Write-Error $_.Exception.Message;
    break;
}

非常感谢您,这对我有用。其他说明-Register-NativeMethod和Add-NativeMethods函数在链接的要点中。
Peter Mounce

17

您所需要做的就是以该用户身份运行命令,Windows将创建配置文件:

psexec.exe -u foobar -p Abcd123! cmd.exe /c exit

https://docs.microsoft.com/zh-cn/sysinternals/downloads/psexec


1
因此,这里发生的事情 psexec 应该以和指定的用户名和密码连接到localhost -u-p并启动cmd以立即退出。我想念什么吗?这听起来有点违反直觉-使用不存在的用户名和密码连接到系统应该是错误的。这是如何运作的 ?
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy:为什么您认为用户名和密码不存在?问题中使用的是同一个人,显然是一个例子……
Ben Voigt

1
@BenVoigt好吧,我错过了问题的顶部。我以为OP也想创建用户,所以这就是答案。因此,评论的最后一部分是一个误解。
Sergiy Kolodyazhnyy

@BenVoigt虽然我还有一个问题。OP提到“我不想创建C:\ users \ default”。那么,使用此方法时用户的配置文件将来自何处C:\users\defaults?如果不是Windows,Windows如何知道如何创建特定的预配置目录?
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy:可以肯定的是,OP表示他不想自定义C:\ Users \ Default ...并不是说它将完全丢失。Windows将通过从普通香草C:\ Users \ default中进行复制来创建主目录C:\ Users \ foobar,然后一旦存在,OP即可将其特殊的调料应用于C:\ Users \ foobar,而不会影响其他任何目录用户。
Ben Voigt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.