我應該如何為 Windows 服務初始化新的本機帳戶?

我應該如何為 Windows 服務初始化新的本機帳戶?

我將 Terraform 與 Google Cloud 結合使用來建立 Windows Server Core 2019 主機以與 Jenkins 一起使用。我想使用 Git、OpenJDK 等來安裝一些軟體,然後啟動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,這會在首次登入時建立用戶設定檔。我認為這就是允許服務正確啟動的原因。

我試圖弄清楚如何建立用戶及其個人資料,而無需手動登入該用戶,以便服務可以正確啟動。安裝和啟動 PS 腳本以使用者身分執行,這可能是使用、或等標誌以使用者身分執行命令以建立其設定檔失敗的SYSTEM原因。Start-ProcessInvoke-CommandStart-Job-Credentialjenkins

我在嘗試運行命令或以exit用戶jenkins身份運行時遇到問題,如下所示:

[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工具。

相關內容