AD域登录脚本:按用户身份映射部门共享盘

还需要登录脚本吗?

虽然现在可以很方便地用组策略来实现网络共享映射,但有些时候VBS脚本仍然有它的用武之地,例如:

  • 映射用户主目录(可以通过用户属性设置用户主目录,但个人感觉通过脚本更加方便);
  • 个性化的映射如将扫描仪的目标目录映射为“我的扫描仪”以方便网络扫描仪的使用;
  • 记录用户登录及注销日志;
  • 收集客户端软、硬件信息;
  • 服务器或客户端异常导致组策略未能正确应用;
  • 客户端异常导致应用组策略后登录等待时间过长;
  • 没有原因,就是喜欢使用脚本

组策略与UAC

简单来说,如果用户属于客户端电脑的管理员组(一般手提电脑用户会加入本地管理员组以方便用户日常使用;台式电脑如果有程序需要在管理员模式下才能正常运行的也需加入本地管理员组,当然,此种情况亦可以通过AutoIT来解决),此时直接运行登录脚本将达不到预期效果,因为此种情况下脚本将会运行在elevated privilege user context下,而不是运行在当前登录的interactive user context下。
所以,一般情况(因为现在基本都是Windows 7 和Windows 10的客户端了吧),如使用登录脚本,最好不要直接引用登录脚本, 而是引用一个前导脚本,解决域用户是本地管理员时的运行问题。

注:此脚本为国外同行根据微软官方的launchapp.wsf所写,出处找到后再补上

'launchapp.vbs, modified from Microsoft's launchapp.wsf
'launches a process as interactive user, NOT as the elevated privilege user context
Option Explicit

Set objNetwork = CreateObject("Wscript.Network")

Const TriggerTypeRegistration = 7
Const ActionTypeExecutable = 0
Const FlagTaskCreate = 2
Const LogonTypeInteractive = 3

Dim strWorkingDirectory, strHostname, strOSVer, colProcessList, strUser, strDomain
Dim objNetwork, objComputer, objShell, objExec, objWMI, objItem, strScriptName, strStdOut
Dim strLogonScriptName, strUserProfile, strTargetScript

'定义登录脚本目录,通常和launchapp.vbs在同一目录
strWorkingDirectory = "\\mycorp.com\SYSVOL\mycorp.com\Policies\{9D8F5AF1-E6DF-491D-B980-DCF66DBDACE0}\User\Scripts\Logon"

'定义登录脚本名称logon.vbs
'launch this login script
strScriptName = "logon.vbs"
strLogonScriptName = strWorkingDirectory & "\" & strScriptName

Set objNetwork = CreateObject("WScript.Network")
Set objShell = CreateObject("WScript.Shell")
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
strHostname = objNetwork.ComputerName
Set objComputer = GetObject("WinNT://" & strHostname & ",computer")
strOSVer = objComputer.OperatingSystemVersion

strUserProfile=objShell.ExpandEnvironmentStrings("%USERPROFILE%")
strTargetScript = strUserProfile & "\logon.exe"

If strOSVer >= 6 Then
  If IsElevated() Then
    'Machine has UAC and user is elevated so use LAUNCHAPP.WSF Task Scheduler method based
    'on appendix from http://technet.microsoft.com/en-us/library/cc766208(WS.10).aspx
    'Are we launched in a RemoteApp session on a Terminal Server? If so, quit.
    Set colProcessList = objWMI.ExecQuery("Select * from Win32_Process Where Name = 'rdpshell.exe'")
    For Each objItem In colProcessList
      objItem.GetOwner strUser, strDomain
      'If we're an admin we can see all users' processes so we need to check only our own
      If strUser = objNetwork.UserName Then
        WScript.Quit
      End If
    Next
    LaunchApp
  Else
    'User is not elevated, so launch the script normally
    objShell.Run "cscript.exe //nologo " & Chr(34) & strWorkingDirectory & "\" & strScriptName & Chr(34), 0, True
    'objShell.Exec(strTargetScript)
  End If
Else
    'This is a Windows XP/2003 machine, so launch the script normally
    objShell.Run "cscript.exe //nologo " & Chr(34) & strWorkingDirectory & "\" & strScriptName & Chr(34), 0, True
    'objShell.Exec(strTargetScript)
End If

Set objNetwork = nothing
Set objComputer = nothing
Set objShell = nothing

Function IsElevated()
  IsElevated = False
  strStdOut = ""
  Set objExec = objShell.Exec ("whoami /groups")
  Do While (objExec.Status = 0)
    WScript.Sleep 100
    If Not objExec.StdOut.AtEndOfStream Then
      strStdOut = strStdOut & objExec.StdOut.ReadAll
    End If
  Loop
  If InStr(strStdOut,"S-1-16-12288") Then
    IsElevated = True
  End If
  Set objExec = nothing
End Function

Sub LaunchApp
  Dim objTaskService
  Dim strTaskName, rootFolder, taskDefinition, triggers, trigger, Action

  'Create the TaskService object
  Set objTaskService = CreateObject("Schedule.Service")
  Call objTaskService.Connect()
  strTaskName = "Launch App As Interactive User"

  'Get a folder to create a task definition in
  Set rootFolder = objTaskService.GetFolder("\")

  'Delete the task if already present
  On Error Resume Next
  Call rootFolder.DeleteTask(strTaskName, 0)
  Err.Clear

  'Create the new task
  Set taskDefinition = objTaskService.NewTask(0)

  'Create a registration trigger
  Set triggers = taskDefinition.Triggers
  Set trigger = triggers.Create(TriggerTypeRegistration)

  'Create the action for the task to execute
  Set Action = taskDefinition.Actions.Create(ActionTypeExecutable)
  'Action.Path = "cscript.exe"
  'Action.Path = strTargetScript
  'Action.Arguments = "//nologo " & strScriptName
  Action.WorkingDirectory = strWorkingDirectory
  Action.Path = strLogonScriptName

  'Register (create) the task
  call rootFolder.RegisterTaskDefinition(strTaskName, taskDefinition, FlagTaskCreate,,, LogonTypeInteractive)

  Set objTaskService = nothing
End Sub

可以根据用户身份自动映射的登录脚本

比较简单的脚本,请自行参照注释。

On Error Resume Next

'部门列表(对应安全组对象)
strGroupList = "售后部,生产部,技术部,行政部,财务部,海外部"
'部门共享名称列表
strShareList = "Svc$,Prd$,Eng$,Adm$,Fin$,Ovs$"
'部门共享盘符列表
StrDriveList = "J:,K:,L:,M:,N:,Q:"
'映射后的网盘名称
strDriveLableList = "售后部,生产部,技术部,行政部,财务部,海外部"

strArrGroup = split(strGroupList,",")
strArrDrive = split(strDriveList,",")
strArrShare = split(strShareList,",")
strDriveLable = split(strDriveLableList,",")

Set objNetwork = CreateObject("Wscript.Network")
Set objADSysInfo = CreateObject("ADSystemInfo")

'网盘名称字典,用于统一重命名映射后的网盘名称
set drives2Rename = CreateObject("Scripting.Dictionary")

'断开所以网盘(Y:和Z:除外)
Set colDrives = objNetwork.EnumNetworkDrives 
For i = 0 to colDrives.Count-1 Step 2 
    If colDrives.Item(i) = "Y:" or colDrives.Item(i) = "Z:" Then
	    'do nothing
    Else
        objNetwork.RemoveNetworkDrive colDrives.Item(i),true,true
    End if 
Next 

strUserDN = objADSysInfo.UserName
strUserName = objNetwork.UserName

Set objUser = GetObject("LDAP://" & strUserDN)
strUserDisplayName = objUser.Get("DisplayName")

'***************************************************************************************
'根据用户身份(所属安全组)自动映射所属部门共享,FileSrv-01为服务器名称
For int_i=0 to 7
    strGroup = strArrGroup(int_i)
    strGroupDN = "cn=" & strGroup & ",ou=Mycorp_Groups,ou=Mycorp,dc=mycorp,dc=com"
    Set objGroup = GetObject("LDAP://" & strGroupDN)
    If objGroup.IsMember("LDAP://" & strUserDN) Then
	  '如果用户属于某个部门则映射该部门共享
      objNetwork.MapNetworkDrive strArrDrive(int_i), "\\FileSrv-01\" & strArrShare(int_i)  
      '名称添加至字典
	  drives2Rename.Add strArrDrive(int_i) & "\", strDriveLable(int_i)	  
    End If
Next

'***************************************************************************************
'为所有用户映射通用共享
objNetwork.MapNetworkDrive "Q:", "\\FileSrv-01\Pub$"
'根据用户登录名映射用户个人私有主目录,例如如登录ID为ALi的用户的共享名为ALi$
objNetwork.MapNetworkDrive "S:", "\\FileSrv-01\" & strUserName & "$"

'名称添加至字典
drives2Rename.Add "Q:\", "公用"
drives2Rename.Add "S:\", "我的个人文件夹"

'***************************************************************************************
'映射公用打印机
strPrinterPath = "\\FileSrv-01\HP LaserJet 8000"
strPrinterMapPath = "\\FileSrv-01\HP LaserJet 8000"
strMapped = "False"

Set colPrinters = objNetwork.EnumPrinterConnections

For i = 0 to colPrinters.Count -1 Step 2
    If UCase(colPrinters.Item (i + 1)) = UCase(strPrinterPath) Then
       strMapped = "True"
    End If
Next

If strMapped = "False" Then
   objNetwork.AddWindowsPrinterConnection strPrinterMapPath
   objNetWork.SetDefaultPrinter strPrinterMapPath
Else
   objNetWork.SetDefaultPrinter strPrinterMapPath
End If

'***************************************************************************************
WScript.Sleep 5000
driveKeys = drives2Rename.Keys
'重命名所有映射的网络盘名称
for i = 0 to drives2Rename.Count -1 
    Set objShell = CreateObject("Shell.Application")
	objShell.NameSpace(driveKeys(i)).Self.Name = drives2Rename.Item(driveKeys(i))
next

'***************************************************************************************
'函数:返回一个介于E:-W:之间的可用盘符
Function getNextDriveLetter
   getNextDriveLetter = "-1"
   With CreateObject("Scripting.FileSystemObject")
      For i = Asc("E") To Asc("W") 
         If Not .DriveExists(Chr(i)) Then 
            getNextDriveLetter = Chr(i) & ":" 
            Exit For 
         End If 
      Next
   End With
End Function

'***************************************************************************************
Set objGroup = Nothing
Set colPrinters = Nothing
Set objShell = Nothing
Set objUser = Nothing
Set objNetwork = Nothing
Set objADSysInfo = Nothing

WScript.Quit 1

版权声明:本文为Sunny_Clickman原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。