zoukankan      html  css  js  c++  java
  • 一次moveuser的使用经历[转]

    有一段时间没再ITECN上更新了,主要因为工作上要完成OCS的SOP文档,所以把主要精力都投入在上面了。

    前昨两天接到一个任务,需要帮助一些没有加域的计算机加域,并迁移用户的相关设置。经过接近一天时间的努力,用脚本配合moveuser,顺利完成了工作组下的用户平滑迁移到域用户,收获颇多,在此和诸位分享。也许在编写脚本的过程中,某些地方还有欠缺,还请各位多多包含。

    先来描述下问题情境:
    1. 用户使用本地计算机Users组成员帐号(假定用户名为user)登录计算机,并且使用了一段时间,用户配置文件偏大。且本地管理员密码不统一,可选的密码有三个。已分配IP地址。
    2. 现在计划将这些用户批量加域,计算机需要重命名,并迁移用户的相关设置。
    3. 整个过程对用户产生的影响越小越好,Helpdesk要进行的操作越少越好。
    4. 所有脚本最好整合成WinRAR自解压包。

    在描述具体实现过程前,诸位可以下载以下视频,查看最终效果。
    从 SkyDrive 下载

    下面来说说具体解决步骤。

    首先第一个问题是,用户是以本地计算机Users组成员身份登录计算机的,在这种情况下,我们是没有办法使用他的用户来加域的,需要使用本地管理员组里的成员,如Administrator才行。但是这又引出另一个问题,管理员帐号密码不统一,我们需要使用一种方法使得脚本能遍历这三种可能性,最终用正确的密码以管理员身份运行重命名计算机的脚本。如果三个密码都无法使用,那只能给个提示劳驾Helpdesk的兄弟破解密码了。

    那么如何实现以上需求呢?VBScript当然无法实现,他没有提供内置的方法来让我们以其它用户身份运行程序或脚本,而且遍历管理员密码也很难实现。那么我们就只能面对出师未捷身先死的窘境了么?当然不是,这个世界如此丰富多彩,早已有高人给我们提供了其它工具来实现这些需求,下面请出的是AutoIT,先来看看最终代码:

       1: dim $pwd[3]
       2: $pwd[0] = "pass@w0rd1"
       3: $pwd[1] = "pass@w0rd2"
       4: $pwd[2] = "pass@w0rd3"
       5:  
       6: For $i = 0 to 2
       7:         $retVal = RunAs("Administrator",@ComputerName,$pwd[$i],1,"wscript.exe " & Chr(34) & @ScriptDir & Chr(34) & "\renamecomputer.vbs")
       8:         If $retVal = 0 Then
       9:             if $i+1 = 3 Then
      10:                 MsgBox (0+16,"错误","管理员密码错误,请重设本地管理员密码。")
      11:                 ExitLoop
      12:             EndIf
      13:         Else
      14:             ExitLoop
      15:         EndIf
      16: Next

    有关AutoIT语法的相关内容,我在这里就不在阐释了,有兴趣的朋友可以去找找相关资料。在以上代码中,我们首先声明一个数组来存放可能的管理员密码。接着我们使用For循环来遍历可能的管理员密码,如果三个已知密码都是错误的,那么我们会给Helpdesk以下提示: 

    如果三个密码中有一个正确,就会启动重命名计算机脚本(与AutoIT生成的程序在同一路径下,所以使用@ScriptDir常量,并且为了避免路径中的空格引发错误,所以使用了Chr(34)。而路径中有空格是因为将涉及到的文件都解压到%temp%目录下)

    下面来说说重命名计算机的脚本。

       1: Set objShell = CreateObject("Wscript.shell")
       2: Set objFSO = CreateObject("Scripting.FileSystemObject")
       3:  
       4: strComputerName = InputBox("请输入新计算机名","输入")
       5: strLocalUserName = InputBox("请正确输入当前用户名" & vbcrlf & "否则将影响到用户配置文件迁移!","输入")
       6: strDomainUserName = InputBox("请正确输入域账号,姓名的拼音,比如lisi" & vbcrlf & "否则将影响到用户配置文件迁移!","输入")
       7: strScriptpath = Replace(WScript.ScriptFullName,WScript.ScriptName,"")
       8:  
       9: Set objTXT = objFSO.CreateTextFile(strScriptpath & "\moveuser.bat")
      10: objTXT.WriteLine("moveuser " & strLocalUserName & " contoso\" & strDomainUserName & " /k")
      11: objTXT.Close
      12:  
      13: objShell.Run("cmd /c net user administrator abcd@123")
      14:  
      15: WScript.Sleep 1500
      16:  
      17: strComputer = "."
      18: Set objWMIService = GetObject("winmgmts:" _
      19:     & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
      20:  
      21: Set colComputers = objWMIService.ExecQuery _
      22:     ("Select * from Win32_ComputerSystem")
      23:  
      24: For Each objComputer in colComputers
      25:     strErr = objComputer.Rename(strComputername)
      26: Next
      27:  
      28: If strErr = 0 Then
      29:         objFSO.CopyFile strScriptpath & "\joindomain.vbs","c:\windows\system32\"
      30:         objFSO.CopyFile strScriptpath & "\moveuser.bat","c:\windows\system32\"
      31:         objFSO.CopyFile strScriptpath & "\moveuser.exe","c:\windows\system32\"
      32:         objshell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\joindomain", "c:\windows\system32\joindomain.vbs","REG_SZ"
      33:         MsgBox "单击确定重新启动计算机",vbOKOnly+vbInformation,"信息"
      34:         objshell.Run("cmd /c shutdown.exe -r -t 0")
      35: End If

    首先我们需要Helpdesk输入新计算机名,当前用户的登录名,将要使用的域账号名,这也是整个迁移过程中唯一需要用户输入的地方。当然这里使用简单的输入框会存在一点问题,如果单击输入框中的取消按钮,可能会导致整个加域任务失败。不过这个任务是由Helpdesk完成而不是普通用户,所以我们暂时不处理这个问题。接下来,我们取得当前脚本的运行路径,并在该路径下根据Helpdesk的输入信息来生成moveuser.bat供后续使用。接着我们需要做的是重设本地管理员的密码,当下一次重启时,Helpdesk需要使用管理员帐号登录,加域脚本会自动执行加域脚本和 moveuser.bat。

    接下来我们利用脚本中心提供的示例代码重命名计算机,并将加域脚本,包含moveuser命令的批处理及moveuser命令本身复制到 system32目录下。同时我们向注册表里写入相关信息,使得下次登录时加域脚本能自动运行。最后脚本执行完成,然后单击确定后重新启动计算机。

    重启完成后,Helpdesk将使用管理员帐号登录计算机,计算机会自动执行加域脚本joindomain.vbs。

    加域脚本中的代码也不太复杂,下面先贴上代码:

       1: Const JOIN_DOMAIN = 1
       2: Const ACCT_CREATE = 2
       3:  
       4: strdnsOne = "192.168.100.1"'InputBox("Please type your first DNS address","Input")
       5: strdnsTwo = "192.168.100.2"'InputBox("Please type your second DNS address","Input")
       6: strDomain = "contoso.com"'InputBox("Please type your domain name","Input")
       7: strUser = "administrator"'InputBox("Please type your domain user name","Input")
       8: strPassword = "abcd@123"'InputBox("Please type you domain user's password","Input")
       9:  
      10: strComputer = "."
      11:  
      12: Set objShell = CreateObject("Wscript.shell")
      13: Set objFSO = CreateObject("Scripting.FileSystemObject")
      14:  
      15: Set objWMIService = GetObject("winmgmts:" _
      16:     & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
      17:  
      18: Set colNetCards = objWMIService.ExecQuery _
      19:     ("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")
      20:  
      21: For Each objNetCard in colNetCards
      22:     arrDNSServers = Array(strdnsone, strdnstwo)
      23:     objNetCard.SetDNSServerSearchOrder(arrDNSServers)
      24: Next
      25:  
      26: Set objNet = CreateObject("Wscript.network")
      27: strComputerName = objnet.ComputerName
      28:  
      29: Set objComputer = GetObject("winmgmts:{impersonationLevel=Impersonate}!\\" & _
      30: strComputer & "\root\cimv2:Win32_ComputerSystem.Name='" & _
      31:         strComputername & "'")
      32:  
      33: ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain, _
      34:     strPassword, strDomain & "\" & strUser, NULL, _
      35:         JOIN_DOMAIN + ACCT_CREATE)
      36:  
      37: If ReturnValue = 0 Then
      38:     Set objCMD = objshell.Exec("c:\windows\system32\moveuser.bat")
      39:     Do While objCMD.Status = 0
      40:         WScript.Sleep 500
      41:     Loop
      42:     MsgBox "单击确定重新启动计算机",vbOKOnly+vbInformation,"信息"
      43:     objshell.Run("cmd /c shutdown.exe -r -t 0")
      44: End If

    首先声明加域脚本要用到的常量,接着我们将加域所用到的dns服务器地址,域名,加域用的帐号名和密码(实验环境中直接用的域管理员帐号,实际环境中我们当然不能用,可以使用一个专门的帐号来代替)存放在变量中。下面使用的代码来自脚本中心,我们只需根据具体环境相应修改即可。当加域成功后,脚本会运行之前创建的moveuser批处理来迁移用户配置文件,当迁移完成后,需要再次重启计算机。至此整个任务已经完成,接下来需要做的就是等待计算机重启完成后,使用域账号登录,验证是否达到了我们预想的效果。 

    总结几点:

    1. 一开始的输入是关键,在使用这整套脚本之前,我们需要和Helpdesk强调这一点
    2. 我们需要保证软硬件环境能使得加域成功,现有脚本中没有做任何处理
    3. 用WinRAR生成自解压包时要注意解压路径的选择(start.exe即是用AutoIT写得脚本) 

    4. 关于虚拟机环境。诸位注意,我用的是Windows Server 2003做的实验,但是如果你在Windows Server 2003中创建普通帐号,这个账号是没有办法是没有重新启动计算机的,所以记得在本地安全策略里修改关闭系统的权限。
    最后还是强调一句:

    文中所有代码仅供参考,如需测试请在虚拟机中执行。本文的目的旨在提供思路而非最终解决方案。

    已发表 2008年11月8日 14:59 作者 ghjconan

    归档在:工作点滴

    评论
    # re: 一次moveuser的使用经历

    啊,没看出门道啊。

    我加域的时候用moveuser老失败。

    我有俩问题:

    1、加域和重命名计算机名是不能同时进行的,要重新启动。

    2、moveuser需要指定old用户和new用户。哪么你的这个过程中是不是还有很多输入啊?

    2008年11月8日 16:11 by smileruner

    # re: 一次moveuser的使用经历

    1. 所以我测试是重启了两次,第一次因为重命名计算机,第二次则是加域

    2. 新老用户名在一开始就完成输入,并将命令保存在moveuser.bat中

    2008年11月8日 16:22 by ghjconan

    # re: 一次moveuser的使用经历

    加域和重命名可以同步进行。

    Moveuser可以通过变量读取现有用户名,要求输入新用户名,并通过规范的用户名来规范计算机名称,同时使用这个用户账号将计算机加入域。

    2008年11月8日 16:34 by Lee

    # re: 一次moveuser的使用经历

    之所以要输入当前登录用户名是因为脚本是以管理员身份启动的,如果我试图想要通过环境变量获取当前登录用户名,得到的结果将会是是管理员的用户名……

    至于计算机命名规则,真实环境中是根据资产编号定的……所以需要Helpdesk手动输入……

    2008年11月8日 17:00 by ghjconan

    # re: 一次moveuser的使用经历

    re Lee

    据我所知,如果先该计算机名,将无法加域。如果先加域,再改计算机名,将再次要求输入加域用户名和密码。

    2008年11月9日 19:06 by smileruner

    # re: 一次moveuser的使用经历

    据我所知,我们项目组的同事写的脚本是可以这样做的。不过~~怎么做的我不知道。

    2008年11月10日 15:42 by Lee

    # re: 一次moveuser的使用经历

    这篇文章写的不错,赞一个!

    2008年11月10日 16:37 by ahpeng

    # re: 一次moveuser的使用经历

    先改机器名再加域是可以的,我已经测试过很多次了。

    ghjconan的加域思路和我很相似,我已经把加域过程VB化了,呵呵。

    2008年11月13日 15:08 by lzlutao

    # re: 一次moveuser的使用经历

    额,Lzlutao,先改计算机名再加域是不可取的。这样会导致你的计算机名更改失败。

    2008年11月14日 15:24 by smileruner

    # 从Ghjconan的《一次moveuser的使用经历》谈开。。。

    Ghjconan在他的博客发表了文章《一次moveuser的使用经历》,原帖地址: http://blogs.itecn.net/blogs/ghjconan/archive/2008/11/08/moveuser.aspx

  • 相关阅读:
    深入理解Kafka-学习笔记04-部分生产者客户端参数
    深入理解Kafka-学习笔记03-消息有序性
    IDEA包不存在找不到包解决方案
    深入理解Kafka-学习笔记02-生产者整体架构
    深入理解Kafka-学习笔记01-初识Kafka
    ClickHouse与MySQL数据类型对应
    MySQL查看版本
    从apache phoenix表提取数据为CSV
    Kafka查看版本
    HBASE查看版本
  • 原文地址:https://www.cnblogs.com/ddlzq/p/2133464.html
Copyright © 2011-2022 走看看