Как я могу программно вызвать создание нового профиля пользователя Windows?

20

Я создаю (локального) пользователя для службы Windows для запуска. У меня есть веские причины не использовать NETWORK SERVICE, LOCAL SERVICE или LOCAL SYSTEM.

Я создаю пользователя через 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, который использует PowerShell для Windows. В частности, модуль win_user с Ansible 2.7.5.
  • Я не хочу создавать C:\users\default(эквивалент /etc/skel), потому что есть несколько разных пользователей сервиса, и один размер не подойдет всем. Это также не влияет на то, когда создается профиль пользователя, а только на то, что будет в нем, когда оно будет создано.
  • Я использую NSSM для управления сервисами.

Вещи, которые я пробовал

  • запуск службы и разрешение Windows для создания каталога
    • Я не хочу этого делать, потому что сервис требует секретов перед запуском, и поэтому, если я сделаю это в процессе выпечки изображений, мне нужно будет их очистить, а также убедиться, что мой сервис не работает любая работа на этапе выпечки. Я хочу избежать обоих этих неприятных битов.
Питер Мунс
источник
1
Вы проверили варианты net user(например, /HOMEDIRили /PROFILEPATH)? , См net user /help. Из моего (непроверенного) понимания, вы можете создать каталог для пользователя и установить его как homedir с /HOMEDIRкоммутатором.
Свен
Могу ли я спросить, какой вариант использования у вас избегает Active Directory? Вещи были бы намного легче с AD. Просто любопытно.
Ондрей Туки
Я избегаю AD, потому что машины эфемерны; время жизни измеряется часами, а не днями. На машинах размещаются среды сборки чистых комнат. Жонглировать машинами в AD и из нее, когда они приходят и уходят, просто не стоит (см. Также medium.com/palantir/active-directory-as-code-e9666a2e548d, если вы заинтересованы в этом).
Питер Маунс
@ Свен да - к сожалению, ни один из них не приводит к созданию самого профиля, даже если он устанавливает путь.
Питер Маунс

Ответы:

23

Windows может создать профиль пользователя по требованию, используя API CreateProfile

Однако, если вы не хотите создавать исполняемый файл для выполнения этой операции, вы можете вызвать API в PowerShell. Другие уже сделали это: пример на 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;
}
Swisstone
источник
Большое спасибо, это работает для меня. Примечание для других - функции Register-NativeMethod и Add-NativeMethods находятся в связанном списке.
Питер Маунс
17

Все, что вам нужно сделать, это запустить команду от имени этого пользователя, Windows создаст профиль:

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

https://docs.microsoft.com/en-us/sysinternals/downloads/psexec

Грег Аскью
источник
1
Так что то, что здесь происходит, psexec должно подключаться к localhost под именем пользователя и паролем, указанным с помощью -uи, -pи запускаться cmdтолько для немедленного выхода. Я что-то пропустил? Это звучит несколько нелогично - подключение к системе с несуществующим именем пользователя и паролем должно быть ошибкой. Как это работает ?
Сергей Колодяжный
1
@SergiyKolodyazhnyy: Почему вы думаете, что это несуществующее имя пользователя и пароль? Это тот же вопрос, который использовался в вопросе, очевидно, в качестве примера ...
Бен Фойгт
1
@BenVoigt Ну, я пропустил верхнюю часть вопроса. Я думал, что OP тоже хочет создать пользователя, и именно это должен был сделать этот ответ. Так что последняя часть комментария является недоразумением.
Сергей Колодяжный
@BenVoigt Хотя у меня все еще есть вопрос. ОП упомянул "Я не хочу создавать C: \ users \ default". Итак, откуда взялся профиль пользователя, когда этот метод используется, и как Windows узнает о создании определенных предварительно настроенных каталогов, если не из C:\users\defaults?
Сергей Колодяжный,
1
@SergiyKolodyazhnyy: Довольно уверен, что OP означает, что он не хочет настраивать C: \ Users \ Default ... не то, чтобы он полностью отсутствовал. Windows создаст домашний каталог C: \ Users \ foobar, скопировав из простого ванили C: \ Users \ default, а затем, если он существует, OP может применить свой специальный соус к C: \ Users \ foobar, где он не повлияет на другие. пользователи.
Бен Фойгт