Skip to content

Instantly share code, notes, and snippets.

@crshnbrn66
Forked from MSAdministrator/Create-NewProfile.ps1
Last active December 19, 2023 17:53
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save crshnbrn66/7e81bf20408c05ddb2b4fdf4498477d8 to your computer and use it in GitHub Desktop.
Save crshnbrn66/7e81bf20408c05ddb2b4fdf4498477d8 to your computer and use it in GitHub Desktop.
PowerShell functions to create a new user profile
<#
.Synopsis
Rough PS functions to create new user profiles
.DESCRIPTION
Call the Create-NewProfile function directly to create a new profile
.EXAMPLE
Create-NewProfile -Username 'testUser1' -Password 'testUser1'
.NOTES
Created by: Josh Rickard (@MS_dministrator) and Thom Schumacher (@driberif)
Date: 24MAR2017
Location: https://gist.github.com/crshnbrn66/7e81bf20408c05ddb2b4fdf4498477d8
Contact: https://github.com/MSAdministrator
MSAdministrator.com
https://github.com/crshnbrn66
powershellposse.com
#>
#Function to create the new local user first
function New-LocalUser
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$userName,
# Param2 help description
[string]
$password
)
$system = [ADSI]"WinNT://$env:COMPUTERNAME";
$user = $system.Create("user",$userName);
$user.SetPassword($password);
$user.SetInfo();
$flag=$user.UserFlags.value -bor 0x10000;
$user.put("userflags",$flag);
$user.SetInfo();
$group = [ADSI]("WinNT://$env:COMPUTERNAME/Users");
$group.PSBase.Invoke("Add", $user.PSBase.Path);
}
#function to register a native method
function Register-NativeMethod
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]$dll,
# Param2 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[string]
$methodSignature
)
$script:nativeMethods += [PSCustomObject]@{ Dll = $dll; Signature = $methodSignature; }
}
function Get-Win32LastError
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param($typeName = 'LastError')
if (-not ([System.Management.Automation.PSTypeName]$typeName).Type)
{
$lasterrorCode = $script:lasterror | ForEach-Object{
'[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetLastError();'
}
Add-Type @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class $typeName {
$lasterrorCode
}
"@
}
}
#function to add native method
function Add-NativeMethods
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param($typeName = 'NativeMethods')
$nativeMethodsCode = $script:nativeMethods | ForEach-Object { "
[DllImport(`"$($_.Dll)`")]
public static extern $($_.Signature);
" }
Add-Type @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class $typeName {
$nativeMethodsCode
}
"@
}
#Main function to create the new user profile
function Create-NewProfile {
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]$UserName,
# Param2 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[string]
$Password
)
Write-Verbose "Creating local user $Username";
try
{
New-LocalUser -username $UserName -password $Password;
}
catch
{
Write-Error $_.Exception.Message;
break;
}
$methodName = 'UserEnvCP'
$script:nativeMethods = @();
if (-not ([System.Management.Automation.PSTypeName]$MethodName).Type)
{
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;
}
}
function New-ProfileFromSID {
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]$UserName,
[string]$domain = 'PHCORP'
)
$methodname = 'UserEnvCP2'
$script:nativeMethods = @();
if (-not ([System.Management.Automation.PSTypeName]$methodname).Type)
{
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;
}
$sb = new-object System.Text.StringBuilder(260);
$pathLen = $sb.Capacity;
Write-Verbose "Creating user profile for $Username";
#$SID= ((get-aduser -id $UserName -ErrorAction Stop).sid.value)
if($domain)
{
$objUser = New-Object System.Security.Principal.NTAccount($domain, $UserName)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$SID = $strSID.Value
}
else
{
$objUser = New-Object System.Security.Principal.NTAccount($UserName)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$SID = $strSID.Value
}
Write-Verbose "$UserName SID: $SID"
try
{
$result = [UserEnvCP2]::CreateProfile($SID, $Username, $sb, $pathLen)
if($result -eq '-2147024713')
{
$status = "$userName already exists"
write-verbose "$username Creation Result: $result"
}
elseif($result -eq '-2147024809')
{
$staus = "$username Not Found"
write-verbose "$username creation result: $result"
}
elseif($result -eq 0)
{
$status = "$username Profile has been created"
write-verbose "$username Creation Result: $result"
}
else
{
$status = "$UserName unknown return result: $result"
}
}
catch
{
Write-Error $_.Exception.Message;
break;
}
$status
}
Function Remove-Profile {
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]$UserName,
[string]$ProfilePath,
[string]$domain = 'PHCORP'
)
$methodname = 'userenvDP'
$script:nativeMethods = @();
if (-not ([System.Management.Automation.PSTypeName]"$methodname.profile").Type)
{
add-type @"
using System.Runtime.InteropServices;
namespace $typename
{
public static class UserEnv
{
[DllImport("userenv.dll", CharSet = CharSet.Unicode, ExactSpelling = false, SetLastError = true)]
public static extern bool DeleteProfile(string sidString, string profilePath, string computerName);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
}
public static class Profile
{
public static uint Delete(string sidString)
{ //Profile path and computer name are optional
if (!UserEnv.DeleteProfile(sidString, null, null))
{
return UserEnv.GetLastError();
}
return 0;
}
}
}
"@
}
#$SID= ((get-aduser -id $UserName -ErrorAction Stop).sid.value)
if($domain)
{
$objUser = New-Object System.Security.Principal.NTAccount($domain, $UserName)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$SID = $strSID.Value
}
else
{
$objUser = New-Object System.Security.Principal.NTAccount($UserName)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$SID = $strSID.Value
}
Write-Verbose "$UserName SID: $SID"
try
{
#http://stackoverflow.com/questions/31949002/c-sharp-delete-user-profile
$result = [userenvDP.Profile]::Delete($SID)
}
catch
{
Write-Error $_.Exception.Message;
break;
}
$LastError
}
@tdalia
Copy link

tdalia commented Mar 14, 2019

CreateProfile is working great. Remove-Profile is not working. I get the following error.

add-type : c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : Identifier expected
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(2) :
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : >>> namespace
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : {
At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
      ion
    • FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

add-type : c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : Identifier expected
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : namespace
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : >>> {
c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(5) : public static class UserEnv
At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
      ion
    • FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

add-type : Cannot add type. Compilation errors occurred.
At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (:) [Add-Type], InvalidOperationException
    • FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

Remove-Profile : Unable to find type [userenvDP.Profile].
At C:\PS\newUser.ps1:2 char:1

  • Remove-Profile -UserName 'vcsois3' -ProfilePath 'C:\Users\vcsois3' -d ...
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-Profile
    

@slide
Copy link

slide commented Aug 6, 2019

What license would you attribute to this code? Is it enough to maintain the header to include it in open source SW?

@crshnbrn66
Copy link
Author

what is your concern?

@slide
Copy link

slide commented Aug 8, 2019

Just don't want to pull it into a project if the license (or lack there of) would be incompatible.

@crshnbrn66
Copy link
Author

I"m not aware of a license issue... I'd suggest you look on http://pinvoke.net/ to see what their rules / licensing is there..

@soulhakr
Copy link

Would this work to create a profile for a AD domain user?

@aefruswg
Copy link

aefruswg commented Jun 2, 2022

CreateProfile is working great. Remove-Profile is not working. I get the following error.

add-type : c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : Identifier expected c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(2) : c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : >>> namespace c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : { At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
      ion
    • FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

add-type : c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : Identifier expected c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(3) : namespace c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(4) : >>> { c:\Users\pharding\AppData\Local\Temp\tj4e34oe\tj4e34oe.0.cs(5) : public static class UserEnv At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
      ion
    • FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

add-type : Cannot add type. Compilation errors occurred. At C:\PS\user-profile.psm1:281 char:7

  •   add-type @"
    
  •   ~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (:) [Add-Type], InvalidOperationException
    • FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

Remove-Profile : Unable to find type [userenvDP.Profile]. At C:\PS\newUser.ps1:2 char:1

  • Remove-Profile -UserName 'vcsois3' -ProfilePath 'C:\Users\vcsois3' -d ...
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-Profile
    

I'm getting the same error. This function would be really useful if it could be sorted out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment