Powershell 修改用户配置文件

简介:

最近公司打算统一修改AD用户的一些属性,包括SamAccountName,UPN,Office365的UPN,这样保证这些属性和邮件地址是一致的。这些修改本身不难,都可以通过PowerShell批量实现,问题在于修改之后有很多额外的问题,例如Outlook的ost文件啦,通过AD进行LDAP登录的工具了,一些软件的保存路径等需要处理。


修改了AD登录名之后的首要问题就是计算机上的用户配置文件需要进行同步修改。公司没用SCCM,因此只有自己想办法了。豆子做了些测试,基本上需要做以下操作:

  1. 以其他管理员身份登录计算机;

  2. 确认该用户abc已经退出登录状态,可以通过任务管理器或者quser来操作

  3. 修改C:\users\abc 的文件名为新的用户名C:\users\abc1

  4. 修改注册表,这个里面有一堆根据SID命名的key,需要找到对应的,然后修改对应的profileImagePath

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

    wKioL1kuDQOhCuiZAACjCSYm6_s522.jpg

  5. 创建新的symboLink连接从 c:\users\abc  <==> c:\users\abc1。windows下面有自带的mklink命令可以使用,比如 mklink /D c:\users \abc c:\users\abc1。PS5以后可以用New-item创建,但是早期的版本没有原生的PS命令,只能间接调用cmd,或者自己写一个方法



上面的操作都可以通过PS脚本来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#创建SymLink的方法,这个网上发现有现成的,我就直接下载了
function  New-Symlink  {
     <#
     .SYNOPSIS
         Creates a symbolic link.
     #>
     param  (
         [ Parameter ( Position =0,  Mandatory = $true )]
         [string]  $Link ,
         [ Parameter ( Position =1,  Mandatory = $true )]
         [string]  $Target
     )
     Invoke-MKLINK  -Link  $Link  -Target  $Target  -Symlink
}
function  New-Hardlink  {
     <#
     .SYNOPSIS
         Creates a hard link.
     #>
     param  (
         [ Parameter ( Position =0,  Mandatory = $true )]
         [string]  $Link ,
         [ Parameter ( Position =1,  Mandatory = $true )]
         [string]  $Target
     )
     Invoke-MKLINK  -Link  $Link  -Target  $Target  -HardLink
}
function  New-Junction  {
     <#
     .SYNOPSIS
         Creates a directory junction.
     #>
     param  (
         [ Parameter ( Position =0,  Mandatory = $true )]
         [string]  $Link ,
         [ Parameter ( Position =1,  Mandatory = $true )]
         [string]  $Target
     )
     Invoke-MKLINK  -Link  $Link  -Target  $Target  -Junction
}
function  Invoke-MKLINK  {
     <#
     .SYNOPSIS
         Creates a symbolic link, hard link, or directory junction.
     #>
     [ CmdletBinding (DefaultParameterSetName =  "Symlink" )]
     param  (
         [ Parameter ( Position =0,  Mandatory = $true )]
         [string]  $Link ,
         [ Parameter ( Position =1,  Mandatory = $true )]
         [string]  $Target ,
         [ Parameter ( ParameterSetName  "Symlink" )]
         [switch]  $Symlink  $true ,
         [ Parameter ( ParameterSetName  "HardLink" )]
         [switch]  $HardLink ,
         [ Parameter ( ParameterSetName  "Junction" )]
         [switch]  $Junction
     )
     # Ensure target exists.
     if  ( -not ( Test-Path  $Target )) {
         throw  "Target does not exist.`nTarget: $Target"
     }
     # Ensure link does not exist.
     if  ( Test-Path  $Link ) {
         throw  "A file or directory already exists at the link path.`nLink: $Link"
     }
     $isDirectory  = ( Get-Item  $Target ).PSIsContainer
     $mklinkArg  = " "
     if ($Symlink -and $isDirectory) {
         $mkLinkArg = " /D "
     }
     if ($Junction) {
         # Ensure we are linking a directory. (Junctions don't work for files.)
         if (-not($isDirectory)) {
             throw " The target is a file. Junctions cannot be created  for  files.`nTarget:  $Target "
         }
         $mklinkArg = " /J "
     }
     if ($HardLink) {
         # Ensure we are linking a file. (Hard links don't work for directories.)
         if ($isDirectory) {
             throw " The target is a directory. Hard links cannot be created  for  directories.`nTarget:  $Target "
         }
         $mkLinkArg = " /H "
     }
     # Capture the MKLINK output so we can return it properly.
     # Includes a redirect of STDERR to STDOUT so we can capture it as well.
     $output = cmd /c mklink $mkLinkArg `"$Link`" `"$Target`" 2>&1
     if ($lastExitCode -ne 0) {
         throw " MKLINK failed. Exit code:  $lastExitCode `n $output "
     }
     else {
         Write-Output $output
     }
}
  
  
  
#定义一个Flag跳出循环
$flag=$true
while($flag){
     $oldName=read-host " Please input the old user name "
     write-host 'Searching user profile..' -ForegroundColor Cyan
      
     #测试该用户是否已经登录,这里有个小技巧把quser的字符串结果转换为对象,具体解释参考博客
     http://beanxyz.blog.51cto.com/5570417/1906162
     if (Test-Path " c:\users\ $oldName "){
         write-host " User Profile c:\users\ $oldName  found. " -ForegroundColor Cyan
         #Check if the user is currently logged In
         $quser = (quser) -replace '\s{2,17}', ',' | ConvertFrom-Csv
         $sessionId = $quser | Where-Object { $_.Username -eq $newName } | select -ExpandProperty id
          
         #如果已经登录,那么强行退出这个用户
         foreach($id in $sessionId){
             if($id -ne $null){
                 write-host " Detected User  $newName  still login " -ForegroundColor red
                 Write-Host " Force logoff the user " -ForegroundColor red
                 logoff $id
             }
          
         }
         
         $newName=read-host " Please input the new name "
         $oldpath=" c:\users\ $oldName "
         $newpath=" c:\users\ $newName "
          
         #重命名文件夹
         rename-item $oldpath $newpath -Confirm -ErrorAction Stop
         write-host " Searching Registry Information  " -ForegroundColor Cyan
          
         #查询对应的注册表Key
         Get-ChildItem " hklm:\software\microsoft\windows nt\currentversion\profilelist " | foreach{
             #Get the username from SID
             $sid=$_.Name.Split('\')[-1];
              
             #根据SID来匹配用户,如果用户匹配成功,那么修改对应的ProfileList
             try{
             $objSID = New-Object System.Security.Principal.SecurityIdentifier ($sid)
             $objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) 
             $username=$objUser.Value
             }
             catch{}
             #change registry keys
             if(($username -eq " omnicom\ $oldName ") -or ($username -eq " omnicom\ $newName ")){
                 write-host " Found Registry Information of user profile  $newName " -ForegroundColor Cyan
                 $keys=Get-ItemProperty " hklm:\software\microsoft\windows nt\currentversion\profilelist\ $sid
                 $keys.ProfileImagePath=$newpath
                 write-host " Registry key profile list is changed to  $newpath " -ForegroundColor Cyan
                  
                  
                 #调用上面的方法,创建Symbolink
                 #Create new symbolink
                 #New-Item -Path $oldpath -ItemType Junction -Value $newpath
                 New-Symlink -Link $oldpath -Target $newpath
                  
                 break;
             }
             else{
                 write-host " $username  Name not match...skip " -ForegroundColor Yellow
              
             }
          
         }
         $flag=$false
          
     }
     else {
         write-host " Profile is not found. Please try again" -ForegroundColor red
     }
}


执行效果,我直接把这个文件扔到一个远程电脑的C盘下测试,然后以本地管理员身份登录,执行这个脚本,成功!



wKioL1kuDE6DqAVTAAB2pbTll9c610.jpg

wKiom1kuDE2D7Jq7AAGCqe23nj4312.jpg






本文转自 beanxyz 51CTO博客,原文链接:http://blog.51cto.com/beanxyz/1930788,如需转载请自行联系原作者

目录
相关文章
|
2月前
|
Windows
修改Windows服务的配置
修改Windows服务的配置
|
3月前
|
C++ 开发者
如何使生成的exe程序默认以管理员权限启动
如何使生成的exe程序默认以管理员权限启动
37 0
快速打开host文件脚本(以管理员身份执行)
快速打开host文件脚本(以管理员身份执行)
252 0
|
Windows
PowerShell添加或修改注册表开机启动项脚本
代码如下: $name = Read-Host "请输入开机启动项的名字(随便起)" $value = Read-Host "请输入开机启动项的值" try{ New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name $name -PropertyType String -Value $value -ErrorAction Stop $tip = "成功添加开机启动项"+$name+"。
2177 0