我应该如何为 Windows 服务初始化新的本地帐户?

我应该如何为 Windows 服务初始化新的本地帐户?

我正在使用 Terraform 和 Google Cloud 创建用于 Jenkins 的 Windows Server Core 2019 主机。我想使用,然后启动Jenkins 代理 JAR作为在本地用户下运行的系统服务jenkins

metadata我正在使用通过如下键提供的 PowerShell 脚本来设置它们sysprep-specialize-script-ps1windows-startup-script-ps1

https://cloud.google.com/compute/docs/startupscript#providing_a_startup_script_for_windows_instances

我的问题是我正在使用 Powershell 创建本地用户,如下所示:

New-LocalUser -Name $Username `
    -Description $Description `
    -Password $Password `
    -PasswordNeverExpires `
    -AccountNeverExpires

我使用 Windows Service Wrapper 创建了一个 Jenkins Agent 服务: https://github.com/winsw/winsw

但是当我尝试在不先登录 Jenkins 用户的情况下运行它时,我得到以下结果:

2020-08-26 14:49:57,760 INFO  - Starting the service with id 'JenkinsAgent'
2020-08-26 14:49:57,823 FATAL - WMI Operation failure: ServiceLogonFailure
WMI.WmiException: ServiceLogonFailure
   at WMI.WmiRoot.BaseHandler.CheckError(ManagementBaseObject result)
   at WMI.WmiRoot.InstanceHandler.Invoke(Object proxy, MethodInfo method, Object[] arguments)
   at WinSW.Program.<Run>g__Start|2_2(<>c__DisplayClass2_0& )
   at WinSW.Program.Run(String[] argsArray, IWinSWConfiguration descriptor)
   at WinSW.Program.Main(String[] args)

如果我首次使用 RDP 登录jenkins用户,则不会发生此问题,因为 RDP 会在首次登录时创建用户配置文件。我认为这就是服务能够正确启动的原因。

我正在尝试弄清楚如何创建用户及其个人资料,而无需手动登录该用户,以便服务可以正确启动。设置和启动 PS 脚本以用户身份运行,这可能是使用诸如、或带有标志的命令以用户身份运行命令以创建其个人资料失败的SYSTEM原因。Start-ProcessInvoke-CommandStart-Job-Credentialjenkins

我在尝试运行命令或exitjenkins用户身份运行时遇到了问题:

[localhost] The background process reported an error with the following message: .
    + CategoryInfo          : OpenError: (localhost:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : 2100,PSSessionStateBroken

我究竟做错了什么?

有没有更好的方法来实现我想要做的事情?

如何创建本地用户它的配置文件以便我创建的服务可以启动吗?

答案1

根据相关问题的回复有三种方法(看起来最有希望):

  1. 使用创建配置文件 API

  2. 使用 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;
    }
  1. 使用psexec实用工具 这看起来像是一种简单的方法,但我不确定它是否适用于 Ansible。 psexec.exe -u foobar -p Abcd123! cmd.exe /c exit 以下是更多信息psexec工具。

相关内容