还需要登录脚本吗?
虽然现在可以很方便地用组策略来实现网络共享映射,但有些时候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版权协议,转载请附上原文出处链接和本声明。