How can I programmatically cause a new Windows user's profile to be created?












8














I'm creating a (local) user for a Windows service to run as. I've got good reasons for not wanting to use NETWORK SERVICE, LOCAL SERVICE, or LOCAL SYSTEM.



I create the user via net user foobar "Abcd123!" /add - this works fine.



At this point, c:usersfoobar does not exist.



If I create the user's home directory, before the user either logs on (or, more pertinently) or the service that the user is for starts up, Windows creates a user-profile next-door called c:usersfoobar-{gibberish/SID/whatever} - this is not a predictable name.



I need the user's home directory to contain things like a .ssh directory, a .gitconfig - tools like that (not limited to those tools) that make assumptions that it'll be a person using them, and so user-configuration goes inside ~/.... Usually, tools from a Unix heritage.



Actual question



So - is there a programmatic (preferably, PowerShell, or out-of-the-box command-line) way to tell Windows to create the user-profile for a local user?



Or, any other workarounds?



Things I've yet to try:




  • An NSSM start/pre hook that copies files from elsewhere into the user-profile directory that hopefully exists at this point by virtue of Windows starting the service, creating the user-profile then handing control to the NSSM wrapper running the hook before startup.

  • Setting the USERPROFILE environment variable for the service to be somewhere other than the actual user-profile directory. This strikes me as dangerously off-piste but also might work fine.


Other context:




  • Windows Server 2016, desktop experience.


    • Can't use Core/Nano.



  • There is no active directory in play. There won't be.

  • These are local users.

  • I'm doing this via Ansible, which is using PowerShell under the hood for Windows things. Specifically the win_user module, with Ansible 2.7.5.

  • I don't want to create a C:usersdefault (the equivalent of /etc/skel), because there are a few different service-users and one size won't fit all. This also doesn't affect when the user-profile is created, just what will be in it when it is.

  • I'm using NSSM to manage the services.


Things I've tried




  • starting the service and allowing Windows to create the directory


    • I don't want to do this, because the service requires secrets before starting up, and so if I do this inside my image-baking process I'll then need to clean them up, and also make sure my service doesn't do any work during the baking phase. I want to avoid both of those fiddly bits.












share|improve this question
























  • Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
    – Sven
    8 hours ago










  • May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
    – Ondrej Tucny
    6 hours ago


















8














I'm creating a (local) user for a Windows service to run as. I've got good reasons for not wanting to use NETWORK SERVICE, LOCAL SERVICE, or LOCAL SYSTEM.



I create the user via net user foobar "Abcd123!" /add - this works fine.



At this point, c:usersfoobar does not exist.



If I create the user's home directory, before the user either logs on (or, more pertinently) or the service that the user is for starts up, Windows creates a user-profile next-door called c:usersfoobar-{gibberish/SID/whatever} - this is not a predictable name.



I need the user's home directory to contain things like a .ssh directory, a .gitconfig - tools like that (not limited to those tools) that make assumptions that it'll be a person using them, and so user-configuration goes inside ~/.... Usually, tools from a Unix heritage.



Actual question



So - is there a programmatic (preferably, PowerShell, or out-of-the-box command-line) way to tell Windows to create the user-profile for a local user?



Or, any other workarounds?



Things I've yet to try:




  • An NSSM start/pre hook that copies files from elsewhere into the user-profile directory that hopefully exists at this point by virtue of Windows starting the service, creating the user-profile then handing control to the NSSM wrapper running the hook before startup.

  • Setting the USERPROFILE environment variable for the service to be somewhere other than the actual user-profile directory. This strikes me as dangerously off-piste but also might work fine.


Other context:




  • Windows Server 2016, desktop experience.


    • Can't use Core/Nano.



  • There is no active directory in play. There won't be.

  • These are local users.

  • I'm doing this via Ansible, which is using PowerShell under the hood for Windows things. Specifically the win_user module, with Ansible 2.7.5.

  • I don't want to create a C:usersdefault (the equivalent of /etc/skel), because there are a few different service-users and one size won't fit all. This also doesn't affect when the user-profile is created, just what will be in it when it is.

  • I'm using NSSM to manage the services.


Things I've tried




  • starting the service and allowing Windows to create the directory


    • I don't want to do this, because the service requires secrets before starting up, and so if I do this inside my image-baking process I'll then need to clean them up, and also make sure my service doesn't do any work during the baking phase. I want to avoid both of those fiddly bits.












share|improve this question
























  • Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
    – Sven
    8 hours ago










  • May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
    – Ondrej Tucny
    6 hours ago
















8












8








8


1





I'm creating a (local) user for a Windows service to run as. I've got good reasons for not wanting to use NETWORK SERVICE, LOCAL SERVICE, or LOCAL SYSTEM.



I create the user via net user foobar "Abcd123!" /add - this works fine.



At this point, c:usersfoobar does not exist.



If I create the user's home directory, before the user either logs on (or, more pertinently) or the service that the user is for starts up, Windows creates a user-profile next-door called c:usersfoobar-{gibberish/SID/whatever} - this is not a predictable name.



I need the user's home directory to contain things like a .ssh directory, a .gitconfig - tools like that (not limited to those tools) that make assumptions that it'll be a person using them, and so user-configuration goes inside ~/.... Usually, tools from a Unix heritage.



Actual question



So - is there a programmatic (preferably, PowerShell, or out-of-the-box command-line) way to tell Windows to create the user-profile for a local user?



Or, any other workarounds?



Things I've yet to try:




  • An NSSM start/pre hook that copies files from elsewhere into the user-profile directory that hopefully exists at this point by virtue of Windows starting the service, creating the user-profile then handing control to the NSSM wrapper running the hook before startup.

  • Setting the USERPROFILE environment variable for the service to be somewhere other than the actual user-profile directory. This strikes me as dangerously off-piste but also might work fine.


Other context:




  • Windows Server 2016, desktop experience.


    • Can't use Core/Nano.



  • There is no active directory in play. There won't be.

  • These are local users.

  • I'm doing this via Ansible, which is using PowerShell under the hood for Windows things. Specifically the win_user module, with Ansible 2.7.5.

  • I don't want to create a C:usersdefault (the equivalent of /etc/skel), because there are a few different service-users and one size won't fit all. This also doesn't affect when the user-profile is created, just what will be in it when it is.

  • I'm using NSSM to manage the services.


Things I've tried




  • starting the service and allowing Windows to create the directory


    • I don't want to do this, because the service requires secrets before starting up, and so if I do this inside my image-baking process I'll then need to clean them up, and also make sure my service doesn't do any work during the baking phase. I want to avoid both of those fiddly bits.












share|improve this question















I'm creating a (local) user for a Windows service to run as. I've got good reasons for not wanting to use NETWORK SERVICE, LOCAL SERVICE, or LOCAL SYSTEM.



I create the user via net user foobar "Abcd123!" /add - this works fine.



At this point, c:usersfoobar does not exist.



If I create the user's home directory, before the user either logs on (or, more pertinently) or the service that the user is for starts up, Windows creates a user-profile next-door called c:usersfoobar-{gibberish/SID/whatever} - this is not a predictable name.



I need the user's home directory to contain things like a .ssh directory, a .gitconfig - tools like that (not limited to those tools) that make assumptions that it'll be a person using them, and so user-configuration goes inside ~/.... Usually, tools from a Unix heritage.



Actual question



So - is there a programmatic (preferably, PowerShell, or out-of-the-box command-line) way to tell Windows to create the user-profile for a local user?



Or, any other workarounds?



Things I've yet to try:




  • An NSSM start/pre hook that copies files from elsewhere into the user-profile directory that hopefully exists at this point by virtue of Windows starting the service, creating the user-profile then handing control to the NSSM wrapper running the hook before startup.

  • Setting the USERPROFILE environment variable for the service to be somewhere other than the actual user-profile directory. This strikes me as dangerously off-piste but also might work fine.


Other context:




  • Windows Server 2016, desktop experience.


    • Can't use Core/Nano.



  • There is no active directory in play. There won't be.

  • These are local users.

  • I'm doing this via Ansible, which is using PowerShell under the hood for Windows things. Specifically the win_user module, with Ansible 2.7.5.

  • I don't want to create a C:usersdefault (the equivalent of /etc/skel), because there are a few different service-users and one size won't fit all. This also doesn't affect when the user-profile is created, just what will be in it when it is.

  • I'm using NSSM to manage the services.


Things I've tried




  • starting the service and allowing Windows to create the directory


    • I don't want to do this, because the service requires secrets before starting up, and so if I do this inside my image-baking process I'll then need to clean them up, and also make sure my service doesn't do any work during the baking phase. I want to avoid both of those fiddly bits.









windows powershell windows-service






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 45 mins ago









Peter Mortensen

2,09742124




2,09742124










asked 9 hours ago









Peter Mounce

67641124




67641124












  • Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
    – Sven
    8 hours ago










  • May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
    – Ondrej Tucny
    6 hours ago




















  • Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
    – Sven
    8 hours ago










  • May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
    – Ondrej Tucny
    6 hours ago


















Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
– Sven
8 hours ago




Have you checked the options net user has (e.g. /HOMEDIR or /PROFILEPATH)? . See net user /help. From my (untested) understanding, you can create a directory for the user, and set this as homedir with the /HOMEDIR switch.
– Sven
8 hours ago












May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
– Ondrej Tucny
6 hours ago






May I ask what use case do you have that avoids Active Directory? Things would be much easier with AD. Just curious.
– Ondrej Tucny
6 hours ago












2 Answers
2






active

oldest

votes


















10














All you need to do is run a command as that user, Windows will create the profile:



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



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






share|improve this answer





























    8














    Windows can create a user-profile on-demand, using the CreateProfile API



    However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.



    Relevant part of the code:



    $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;
    }





    share|improve this answer





















      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "2"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f946882%2fhow-can-i-programmatically-cause-a-new-windows-users-profile-to-be-created%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10














      All you need to do is run a command as that user, Windows will create the profile:



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



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






      share|improve this answer


























        10














        All you need to do is run a command as that user, Windows will create the profile:



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



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






        share|improve this answer
























          10












          10








          10






          All you need to do is run a command as that user, Windows will create the profile:



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



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






          share|improve this answer












          All you need to do is run a command as that user, Windows will create the profile:



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



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







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 8 hours ago









          Greg Askew

          28.2k33667




          28.2k33667

























              8














              Windows can create a user-profile on-demand, using the CreateProfile API



              However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.



              Relevant part of the code:



              $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;
              }





              share|improve this answer


























                8














                Windows can create a user-profile on-demand, using the CreateProfile API



                However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.



                Relevant part of the code:



                $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;
                }





                share|improve this answer
























                  8












                  8








                  8






                  Windows can create a user-profile on-demand, using the CreateProfile API



                  However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.



                  Relevant part of the code:



                  $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;
                  }





                  share|improve this answer












                  Windows can create a user-profile on-demand, using the CreateProfile API



                  However, if don't want to create an executable to perform this operation, you can call the API in PowerShell. Others have already done it: example on github.



                  Relevant part of the code:



                  $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;
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 8 hours ago









                  Swisstone

                  1,5941816




                  1,5941816






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Server Fault!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f946882%2fhow-can-i-programmatically-cause-a-new-windows-users-profile-to-be-created%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Quarter-circle Tiles

                      build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                      Mont Emei