Skip to main content
Account for changed AppData\Roaming folder
Source Link
VertigoRay
  • 423
  • 1
  • 5
  • 9

I would start by asking the registry where the profiles are because they, theoretically, can be customized. In that regard, so can the location of the AppData\Roaming folder in each profile, but that's beyond this script unless you askso we should account for itthat as well to be thorough.

# Get the list of profile paths from the registryregistry; since they theoretically can be customized.
$profileListReg = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' 

# This filters out short SIDs (such as the SYSTEMsystem account)
$profilesReg = (Get-ChildItem $profileListReg | Where-Object { $_.Name.Split('-').Count -gt 4 }).Name

[System.Collections.ArrayList] $userProfiles = @(){}

# Add Default Profile to array listhashtable
foreach ($profileReg in $profilesReg) {
    [void] $userProfiles.Add($profilesReg.PSChildName, (Get-ItemProperty ('Registry::{0}' -f $profileReg.Name)).ProfileImagePath)
} 

# Add Default Profile to array listhashtable
#   This will cover new users getting the file
[void] $userProfiles.Add('.DEFAULT', (Get-ItemProperty $profileListReg).Default)

$source = '\\FileShare\FancyConfigurationFiles\Config.xml'
$userShellFoldersReg = 'Registry::HKEY_USERS\{0}\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'

# Copy Config to each Profile ...
$sourceforeach =($userProfile '\\FileShare\FancyConfigurationFiles\Configin $userProfiles.xml'GetEnumerator()) {
$destination    Write-Verbose "$($userProfile.Name): $($userProfile.Value)"

    $userShellFolders = 'Get-Item ($userShellFoldersReg -f $userProfile.Name)
    $appData = $userShellFolders.GetValue('AppData','','DoNotExpandEnvironmentNames')
    Write-Verbose "AppData: ${0appData}\AppData\Roaming\'"
    
foreach    $destination = $appData.Replace('%USERPROFILE%', $userProfile.Value)
 in $userProfiles)  Write-Verbose "Destination: ${destination}"
    
    Copy-Item -Path $Source -Destination ($destination -f $userProfile) -Force
}

You should comment out the Copy-Item line at the bottom and turn on verbosity ($VerbosePreference = 'continue') to test and ensure those verbose messages look like what you expect them to.

Note: I do not like using HKLM: because interacting with the registry doesn't return full paths with HKLM:, it returns HKEY_LOCAL_MACHINE. So, you have to either string replace those or know that you can just tack Registry:: on the front of it and get to the path. This is more useful anyway since all hives are not available as PS Drives.

I would start by asking the registry where the profiles are because they, theoretically, can be customized. In that regard, so can the location of the AppData\Roaming folder in each profile, but that's beyond this script unless you ask for it.

# Get the list of profile paths from the registry
$profileListReg = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
# This filters out short SIDs (such as the SYSTEM account)
$profilesReg = (Get-ChildItem $profileListReg | Where-Object { $_.Name.Split('-').Count -gt 4 }).Name

[System.Collections.ArrayList] $userProfiles = @()
# Add Default Profile to array list
foreach ($profileReg in $profilesReg) {
    [void] $userProfiles.Add((Get-ItemProperty ('Registry::{0}' -f $profileReg)).ProfileImagePath)
}
# Add Default Profile to array list
#   This will cover new users getting the file
[void] $userProfiles.Add((Get-ItemProperty $profileListReg).Default)

# Copy Config ...
$source = '\\FileShare\FancyConfigurationFiles\Config.xml' 
$destination = '{0}\AppData\Roaming\' 
foreach ($userProfile in $userProfiles) {
    Copy-Item -Path $Source -Destination ($destination -f $userProfile) -Force
}

Note: I do not like using HKLM: because interacting with the registry doesn't return full paths with HKLM:, it returns HKEY_LOCAL_MACHINE. So, you have to either string replace those or know that you can just tack Registry:: on the front of it and get to the path. This is more useful anyway since all hives are not available as PS Drives.

I would start by asking the registry where the profiles are because they, theoretically, can be customized. In that regard, so can the location of the AppData\Roaming folder in each profile, so we should account for that as well to be thorough.

# Get the list of profile paths from the registry; since they theoretically can be customized.
$profileListReg = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' 

# This filters out short SIDs (such as the system account)
$profilesReg = Get-ChildItem $profileListReg | Where-Object { $_.Name.Split('-').Count -gt 4 }

$userProfiles = @{}

# Add Default Profile to hashtable
foreach ($profileReg in $profilesReg) {
    $userProfiles.Add($profilesReg.PSChildName, (Get-ItemProperty ('Registry::{0}' -f $profileReg.Name)).ProfileImagePath)
} 

# Add Default Profile to hashtable
#   This will cover new users getting the file
$userProfiles.Add('.DEFAULT', (Get-ItemProperty $profileListReg).Default)

$source = '\\FileShare\FancyConfigurationFiles\Config.xml'
$userShellFoldersReg = 'Registry::HKEY_USERS\{0}\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'

# Copy Config to each Profile ...
foreach ($userProfile in $userProfiles.GetEnumerator()) {
    Write-Verbose "$($userProfile.Name): $($userProfile.Value)"

    $userShellFolders = Get-Item ($userShellFoldersReg -f $userProfile.Name)
    $appData = $userShellFolders.GetValue('AppData','','DoNotExpandEnvironmentNames')
    Write-Verbose "AppData: ${appData}"
    
    $destination = $appData.Replace('%USERPROFILE%', $userProfile.Value)
    Write-Verbose "Destination: ${destination}"
    
    Copy-Item -Path $Source -Destination ($destination -f $userProfile) -Force
}

You should comment out the Copy-Item line at the bottom and turn on verbosity ($VerbosePreference = 'continue') to test and ensure those verbose messages look like what you expect them to.

Note: I do not like using HKLM: because interacting with the registry doesn't return full paths with HKLM:, it returns HKEY_LOCAL_MACHINE. So, you have to either string replace those or know that you can just tack Registry:: on the front of it and get to the path. This is more useful anyway since all hives are not available as PS Drives.

Source Link
VertigoRay
  • 423
  • 1
  • 5
  • 9

I would start by asking the registry where the profiles are because they, theoretically, can be customized. In that regard, so can the location of the AppData\Roaming folder in each profile, but that's beyond this script unless you ask for it.

# Get the list of profile paths from the registry
$profileListReg = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
# This filters out short SIDs (such as the SYSTEM account)
$profilesReg = (Get-ChildItem $profileListReg | Where-Object { $_.Name.Split('-').Count -gt 4 }).Name

[System.Collections.ArrayList] $userProfiles = @()
# Add Default Profile to array list
foreach ($profileReg in $profilesReg) {
    [void] $userProfiles.Add((Get-ItemProperty ('Registry::{0}' -f $profileReg)).ProfileImagePath)
}
# Add Default Profile to array list
#   This will cover new users getting the file
[void] $userProfiles.Add((Get-ItemProperty $profileListReg).Default)

# Copy Config ...
$source = '\\FileShare\FancyConfigurationFiles\Config.xml' 
$destination = '{0}\AppData\Roaming\' 
foreach ($userProfile in $userProfiles) {
    Copy-Item -Path $Source -Destination ($destination -f $userProfile) -Force
}

Note: I do not like using HKLM: because interacting with the registry doesn't return full paths with HKLM:, it returns HKEY_LOCAL_MACHINE. So, you have to either string replace those or know that you can just tack Registry:: on the front of it and get to the path. This is more useful anyway since all hives are not available as PS Drives.