Need some quick help with my vbs active directory login script

Soldato
Joined
1 Dec 2004
Posts
23,083
Location
S.Wales
Hi Dudes and dudesses,

Please see my newly created VBS login script which I am planning on using in a Windows 2003 AD environment, Its about 75% Complete, so far the home user directory and mapped shared drives are mapping fine when user logs in, I can get the printer map working IF the printer is hosted on a dedicated server, the only problem is our domain controller is hosted in a DC up north therefore if we wanted to print, the data would have to be sent up to the DC to be processed by the print server, then back down to our network in South Wales.

As we have 2 printers in the office which both have the ability to hardcode IP addresses in them, we dont therefore need to use a print server on a dedicated server.

Please see my code below.

Code:
' VBScipt for Windows AD-Domain user login script with mapped network drive & mapped printer support----------'
' v1.1--------------------------------------------------------------------------------------------------------'
'copyright 2009-------------------------------------------------------------------------------'
' ------------------------------------------------------------------------------------------------------------'

'On Error Resume Next


' Initialise Groups with Const statement
Const SUPPORT_GROUP = "cn=support"
Const FINANCE_GROUP = "cn=finance"
Const PROVISIONING_GROUP = "cn=provisioning"
Const SALES_GROUP = "cn=sales"

'Map Users home directory to h:\
Set wshNetwork = CreateObject("WScript.Network")
wshNetwork.MapNetworkDrive "h:", "\\***\***$\" & wshNetwork.UserName


' Create objects and extract strGroup values
Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))



If InStr(strGroups, SUPPORT_GROUP) Then

    wshNetwork.MapNetworkDrive "s:", "\\***\***\"
    wshNetwork.AddWindowsPrinterConnection "\\Servername\Printername\"
    'wshNetWork.SetDefaultPrinter
   

ElseIf InStr(strGroups, FINANCE_GROUP) Then

    wshNetwork.MapNetworkDrive "f:", "\\***\***\"
    wshNetwork.AddWindowsPrinterConnection "\\Servername\Printername\"
    'wshNetWork.SetDefaultPrinter
    '"\\PrintServer\FinLaser"
   
ElseIf InStr(strGroups, PROVISIONING_GROUP) Then

    wshNetwork.MapNetworkDrive "s:", "\\***\***\"
    wshNetwork.AddWindowsPrinterConnection "\\Servername\Printername\"
    'wshNetWork.SetDefaultPrinter
    '"\\PrintServer\HrLaser"
   
ElseIf InStr(strGroups, SALES_GROUP) Then

    wshNetwork.MapNetworkDrive "s:", "\\***\***\"
    wshNetwork.AddWindowsPrinterConnection "\\Servername\Printername\"
    'wshNetWork.SetDefaultPrinter
    '"\\PrintServer\HrLaser"

End If

As you can see, the line

Code:
wshNetwork.AddWindowsPrinterConnection "\\Servername\Printername\"

is in the format "\\servername\Printer Name" and this is causing a problem for us as technically the printer will not be hosted on a server.

I have also tried

Code:
"\\Printer IP\Printer name" and also "\\Printer IP"

but neither work, is there anyway around this? we want the deminish the server name and just connect via IP address of the printer.

Any help greatly appriciated.
 
Last edited:
AFAIK AddWindowsPrinter requires a UNC name in order to work.

The only thing I can suggest is setting up a local printer that connects to the printers IP and port.

EDIT: You should be able create a reg file to add the settings automatically.
 
Last edited:
AFAIK AddWindowsPrinter requires a UNC name in order to work.

The only thing I can suggest is setting up a local printer that connects to the printers IP and port.

EDIT: You should be able create a reg file to add the settings automatically.

interesting, ok, ill read up on UNC. As i mentioned the printer mapping works fine without UNC if the printer is hosted on the print server, we dont want this though, we dont even want it to be hosted on a local machine, the whole point of a printer with configurable IP is so that you can directly connect to them without using a print server or a local machine to host them.

Do you have more info on this reg file? what will it enable me to do?

This login script will be added to each users "login script" through active directory, then when they login it will run.

Thanks for your info so far :)
 
might be of some use:

Add IP port:

strComputer = "\\computer"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objNewPort = objWMIService.Get _
("Win32_TCPIPPrinterPort").SpawnInstance_

objNewPort.Name = "IP_169.254.110.14"
objNewPort.Protocol = 1
objNewPort.HostAddress = "169.254.110.14"
objNewPort.PortNumber = "9999"
objNewPort.SNMPEnabled = False
objNewPort.Put_


ADD Driver .....

strComputer = "\\computer"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
objWMIService.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True

Set objDriver = objWMIService.Get("Win32_PrinterDriver")

objDriver.Name = "NewPrinter Model 2900"
objDriver.SupportedPlatform = "Windows NT x86"
objDriver.Version = "3"
objDriver.DriverPath = "C:\Scripts\NewPrinter.dll"
objDriver.Infname = "C:\Scripts\NewPrinter.inf"
intResult = objDriver.AddPrinterDriver(objDriver)

Install printer:

strComputer = "\\computer"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_

objPrinter.DriverName = "HP LaserJet 4000 Series PS"
objPrinter.PortName = "IP_169.254.110.160"
objPrinter.DeviceID = "ScriptedPrinter"
objPrinter.Location = "USA/Redmond/Building 37/Room 114"
objPrinter.Network = True
objPrinter.Put_
 
Hi, just managed to have a look of the above code posted by Rolfcakes, although this looks interesting looking at the code it still looks asthough it relys on the printer being hosted by a local machine?

For all intents and purposes Windows treats it as a printer connected locally to your PC. You'll add the printer as a local one, the port it connects to is the important part. Instead of data being sent down LPT or a USB port it is sent via TCP/IP.

All the code does is automate the process that you go through when you click

Start > Settings > Printers and Faxes > Add New Printer > Local Printer

You'll want to put the driver files in a shared location.
 
So to clarify, when the script is loaded when the user logs in, it automates the procedure of going through start>programmes>add printers, it adds a printer using TCP/IP ports and uses the driver located in a shared location.

OK, i think iv got it, thanks very much for your help :)

Im going to work on this when I get a chance (probably tomorrow in work and ill post the code I have up here to see what everyone thinks).

Thanks

DJMK4
 
You've got it :). Once you get it working for new users you'll probably want to put some checks in place
e.g.
If the drivers exist - don't copy them
Does the printer already exist? If so, skip that part and continue with login
 
Hi, just managed to have a look of the above code posted by Rolfcakes, although this looks interesting looking at the code it still looks asthough it relys on the printer being hosted by a local machine?

Not really, i assume you're referring to the " \\computer " bit ... well thats because them scripts are for running remotely of you're own machine ... to make it local:

Simply change strComputer = "\\computer" to strComputer = "." and it would turn that to the local machine
 
OK, here is abit of an update on this project, its going good but im still trying to sort out a few bugs.

1) I want to implement the login script so that when it logs in, it will disconnect the network drives before reconnecting them, I thought I had sussed it by using the following code before mapping them:

wshNetwork.RemoveNetworkDrive "f:"

However this is not the case and I get the following error

Line 20 this network connection does not exist?? however if i remove it maps fine.

2) With regards to the print mapping, I have got this working! It creates a TCP/IP port, adds the driver, then adds the printer, when i log off and log back in, it stays put, is this the best way of doing this or is it best to disconnect the printer on log off? also, everytime I log back in it will look for and install the printer driver, I want it to check to see if the driver is already installed, if it is, skip that section.

Any tips on how to achieve this?

Kind Regards

DJMK4


Here is the code

Code:
' VBScipt for Windows AD-Domain user login script with mapped network drive & mapped printer support----------'
' v1.1--------------------------------------------------------------------------------------------------------'
' copyright 2009-------------------------------------------------------------------------------'
' ------------------------------------------------------------------------------------------------------------'


'MAP NETWORK DRIVES
'--------------------------------------------------------------------------------

'On Error Resume Next

' Initialise Groups with Const statement
Const SUPPORT_GROUP = "cn=support"
Const FINANCE_GROUP = "cn=finance"
Const PROVISIONING_GROUP = "cn=provisioning"
Const SALES_GROUP = "cn=sales"

'Map Users home directory to h:\
Set wshNetwork = CreateObject("WScript.Network")
wshNetwork.RemoveNetworkDrive "h:"
wshNetwork.MapNetworkDrive "h:", "\\****\Users$\" & wshNetwork.UserName


'Create objects and extract strGroup values
Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))


If InStr(strGroups, SUPPORT_GROUP) Then
    wshNetwork.RemoveNetworkDrive "s:"
    wshNetwork.MapNetworkDrive "s:", "\\****\DATA"
   

ElseIf InStr(strGroups, FINANCE_GROUP) Then
    wshNetwork.RemoveNetworkDrive "f:"
    wshNetwork.RemoveNetworkDrive "s:"
    wshNetwork.MapNetworkDrive "f:", "\\****\finance"
    wshNetwork.MapNetworkDrive "s:", "\\****\DATA"

       
       
ElseIf InStr(strGroups, PROVISIONING_GROUP) Then
    wshNetwork.RemoveNetworkDrive "s:"
    wshNetwork.MapNetworkDrive "s:", "\\****\DATA"

   
   
ElseIf InStr(strGroups, SALES_GROUP) Then
    WshNetwork.RemoveNetworkDrive "s:"
    wshNetwork.MapNetworkDrive "s:", "\\****\DATA"
End If



'MAP NETWORK PRINTER VIA IP PORT
'--------------------------------------------------------------------------------
'Create TCP/IP Port

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objNewPort = objWMIService.Get _
("Win32_TCPIPPrinterPort").SpawnInstance_

objNewPort.Name = "IP_****"
objNewPort.Protocol = 1
objNewPort.HostAddress = "****"
objNewPort.PortNumber = "9100"
objNewPort.SNMPEnabled = False
objNewPort.Put_


'ADD Driver

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
objWMIService.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True

Set objDriver = objWMIService.Get("Win32_PrinterDriver")

objDriver.Name = "HP Color LaserJet 2600n"
objDriver.SupportedPlatform = "Windows NT x86"
objDriver.Version = "3"
'objDriver.DriverPath = "\\****\netlogon\clj2600n\NewPrinter.dll"
objDriver.Infname = "\\****\netlogon\clj2600n\CLJ2600.INF"
intResult = objDriver.AddPrinterDriver(objDriver)


'Install printer

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_

objPrinter.DriverName = "HP Color LaserJet 2600n"
objPrinter.PortName   = "IP_****"
objPrinter.DeviceID   = "HP Color LaserJet 2600n"
objPrinter.Location = "****"
objPrinter.Network = True
objPrinter.Shared = False
objPrinter.Put_
 
Last edited:
OK, here is abit of an update on this project, its going good but im still trying to sort out a few bugs.

1) I want to implement the login script so that when it logs in, it will disconnect the network drives before reconnecting them, I thought I had sussed it by using the following code before mapping them:

wshNetwork.RemoveNetworkDrive "f:"

However this is not the case and I get the following error

Line 20 this network connection does not exist?? however if i remove it maps fine.

Did you map the drive using your script or was it created manually beforehand? When you can create it manually using Windows Explorer (Well a reg file at least... I'm unable to test Map Network Drive through explorer here at the moment) it adds the information to the registry under Network. You won't be able to remove this using WSHNetwork, you'll need to remove the keys first.

You can remove drives created with WSHNetwork but not ones that weren't. As a test enumerate the network drives on your PC to a text file or similar and see if the drive you're unable to remove with your script is listed - I've got a feeling it won't be.


2) With regards to the print mapping, I have got this working! It creates a TCP/IP port, adds the driver, then adds the printer, when i log off and log back in, it stays put, is this the best way of doing this or is it best to disconnect the printer on log off? also, everytime I log back in it will look for and install the printer driver, I want it to check to see if the driver is already installed, if it is, skip that section.

Any tips on how to achieve this?

Kind Regards

DJMK4


---SNIP---

From what I remember printers are stored in the Control Set, you shouldn't need to add them for specific users just PC's, once they're added - everyone here in work has a default "HP LaserJet" that doesn't actually exist - you can read the registry for the printer and check it has keys listed for drivers. In theory, that should work.
 
Last edited:
Did you map the drive using your script or was it created manually beforehand? When you can create it manually using Windows Explorer (Well a reg file at least... I'm unable to test Map Network Drive through explorer here at the moment) it adds the information to the registry under Network. You won't be able to remove this using WSHNetwork, you'll need to remove the keys first.

You can remove drives created with WSHNetwork but not ones that weren't. As a test enumerate the network drives on your PC to a text file or similar and see if the drive you're unable to remove with your script is listed - I've got a feeling it won't be.

The mapped drives was created using wshNetwork, the mapping works fine, but apon login before they map the drives I want them to removemapped drives before mapping them. Saves any errors coming up because "This drive is already mapped"



From what I remember printers are stored in the Control Set, you shouldn't need to add them for specific users just PC's, once they're added - everyone here in work has a default "HP LaserJet" that doesn't actually exist - you can read the registry for the printer and check it has keys listed for drivers. In theory, that should work.

Thanks, will look in to this.
 
The mapped drives was created using wshNetwork, the mapping works fine, but apon login before they map the drives I want them to removemapped drives before mapping them. Saves any errors coming up because "This drive is already mapped"

How odd. Can you check to see if the is anything stored under HKEY_CURRENT_USERS\Network

I can replicate the error if I have drives listed there but cannot just using WSHNetwork. Did you enumerate the drives? If so, was the troublesome drive listed? If WSHNetwork doesn't see it you want be able to remove it.

You could even use the enumeration as part of your code. e.g. F:\, \\myShare\Drive$ is listed so remove it then remap if not simply map it. :)
 
How odd. Can you check to see if the is anything stored under HKEY_CURRENT_USERS\Network

I can replicate the error if I have drives listed there but cannot just using WSHNetwork. Did you enumerate the drives? If so, was the troublesome drive listed? If WSHNetwork doesn't see it you want be able to remove it.

You could even use the enumeration as part of your code. e.g. F:\, \\myShare\Drive$ is listed so remove it then remap if not simply map it. :)


Thanks for the info on this :) Will be having another look at this project tomorrow as Iv been lumbered with some more work, d'oh!

Will post updates :)

Just a question though, when you say "enumeration", what is this? I will have to look this up on google i think,lol!
 
Thanks for the info on this :) Will be having another look at this project tomorrow as Iv been lumbered with some more work, d'oh!

Will post updates :)

Just a question though, when you say "enumeration", what is this? I will have to look this up on google i think,lol!

In this case I am referring to the EnumNetworkDrives method. It returns a collection of network drives and their UNC path.

Code:
 Set myNetworkDrives = wsNetwork.EnumNetworkDrives ; This will give you your array to iterate through.
 
 
myNetworkDrives(0) ; This would be "F:\" as an example
myNetworkDrives(1) ; Would be [URL="file://\\myServer\MyFolder$"]\\myServer\MyFolder$[/URL]"
myNetworkDrives(2) ; This would be "G:\" as an example
myNetworkDrives(3) ; Would be [COLOR=#0000ff][URL="file://\\myServer\BobsFolder$"]\\myServer\BobsFolder$[/URL]"[/COLOR]

If you match up each pair of elements you could list all the drives and their UNC paths.

In your case you'd only need to check the even elements which would be "F:", "G:" and so on. If you can't see "F:" in your output then you know it's not going to be accessible to WSHNetwork and you'll need to account for this in your code to avoid errors.

I'd put it in a sub a function that way you can simply call it when needed. Here's a rough idea

Code:
Private Sub AddNetworkDrive(sDrive, sUNC)
Dim objWSN, objDrives
 
Set objWSN = CreateObject("WScript.Network")
Set objDrives = objWSN.EnumNetworkDrives()
Do Until i >= objDrives.Count
 
    If objDrives(i) = sDrive Then
        objWSN.RemoveNetworkDrive (sDrive) ' The drive is already mapped, remove it before continuing
        i = objDrives.Count                ' No need to keep looping
    End If
    i = i + 2
Loop
objWSN.MapNetworkDrive sDrive, sUNC
 
End Sub

Then just call:

AddNetworkDrive "F:", "\\myServer\myShare$"

You could change it to a function and get it return success or failure.
 
Thanks for that info.

I am however getting issues with the drive mapping side now!

Seems that on mine it works, when i use it with someone elses AD account it has problems and returns a "Type Mismatch - "Join" error for the following line:

strGroups = LCase(Join(CurrentUser.MemberOf))

This is due to AD members being in less than or two or more groups which makes it return an error. I have dug and dug around on the web and have found various fix code snippets for this problem including the one below:

Code:
Dim strGroup
Dim colGroups

Set objUser = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & objUser.UserName)

colGroups = CurrentUser.memberOf
If IsEmpty(colGroups) Then
strGroup = ""
ElseIf TypeName(colGroups) = "String" Then
strGroup = LCase(colGroups)
Else
strGroup = LCase(Join(colGroups))
End If

which is supposed to replace that statement above, It doesnt return any errors but then the only drive it maps is the users home drive. See below for full code.

Code:
' VBScipt for Windows AD-Domain user login script with mapped network drive & mapped printer support----------'
' v1.1--------------------------------------------------------------------------------------------------------'
' dmoranda.co.uk copyright 2009-------------------------------------------------------------------------------'
' ------------------------------------------------------------------------------------------------------------'

'On Error Resume Next




Const SUPPORT_GROUP = "cn=support"
Const FINANCE_GROUP = "cn=finance"
Const PROVISIONING_GROUP = "cn=provisioning"
Const SALES_GROUP = "cn=sales"

'Map Users home directory to h:\
Set wshNetwork = CreateObject("WScript.Network")
wshNetwork.MapNetworkDrive "h:", "\\*****\Users$\" & wshNetwork.UserName


'Create objects and extract strGroup values
'Set ADSysInfo = CreateObject("ADSystemInfo")
'Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
'strGroups = LCase(Join(CurrentUser.MemberOf))


'Fix for AD users and number of groups they are a member 
Dim strGroup
Dim colGroups

Set objUser = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & objUser.UserName)

colGroups = CurrentUser.memberOf
If IsEmpty(colGroups) Then
strGroup = ""
ElseIf TypeName(colGroups) = "String" Then
strGroup = LCase(colGroups)
Else
strGroup = LCase(Join(colGroups))
End If


If InStr(strGroups, SUPPORT_GROUP) Then
    'wshNetwork.RemoveNetworkDrive "s:", "\\****\DATA"
	wshNetwork.MapNetworkDrive "s:", "\\***\DATA"

	

ElseIf InStr(strGroups, FINANCE_GROUP) Then
	'WshNet.RemoveNetworkDrive "f:", "\\****\finance"
	'WshNet.RemoveNetworkDrive "s:", "\\*****\DATA"
	wshNetwork.MapNetworkDrive "f:", "\\*****\finance"
    	wshNetwork.MapNetworkDrive "s:", "\\*****\DATA"

    	
		
ElseIf InStr(strGroups, PROVISIONING_GROUP) Then
	'WshNet.RemoveNetworkDrive "s:", "\\*****\DATA"
	wshNetwork.MapNetworkDrive "s:", "\\*****\DATA"

	
	
ElseIf InStr(strGroups, SALES_GROUP) Then
	'WshNet.RemoveNetworkDrive "s:", "\\*****\DATA"
	wshNetwork.MapNetworkDrive "s:", "\\*****\DATA"
End If

Would really appriciate some help on this :( I have spent hours trying to get this working "fully" but everytime i get i think I have it working I run into yet another problem.

Here is one of the links I have found regarding this issue.

http://www.petri.co.il/forums/archive/index.php/t-9290.html


Thanks in advance :)
 
Hmm think i may have just cracked it, still havnt tested this on a non-admins user account tho..

Code:
' VBScipt for Windows AD-Domain user login script with mapped network drive & mapped printer support----------'
' v1.1--------------------------------------------------------------------------------------------------------'
' copyright 2009-------------------------------------------------------------------------------'
' ------------------------------------------------------------------------------------------------------------'


Dim objNetwork, objUser, CurrentUser
Dim strGroup, arrGroups
'Defines a list for the variable values

Const SUPPORT_GROUP = "cn=support"
Const FINANCE_GROUP = "cn=finance"
Const PROVISIONING_GROUP = "cn=provisioning"
Const SALES_GROUP = "cn=sales"

Set objNetwork = CreateObject("WScript.Network")
Set objUser = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & objUser.UserName)

'On Error Resume Next
arrGroups = CurrentUser.memberOf
If (Err.Number <> 0) Then
On Error GoTo 0
strGroups = ""
Else
On Error GoTo 0
strGroup = LCase(Join(arrGroups))
End If

If InStr(strGroup, SUPPORT_GROUP) then
objNetwork.MapNetworkDrive "s:", "\\***\DATA"

Else If InStr(strGroups, FINANCE_GROUP) Then
objNetwork.MapNetworkDrive "s:", "\\***\DATA"
objNetwork.MapNetworkDrive "f:", "\\***\finance"

Else If InStr(strGroups, PROVISIONING_GROUP) Then
objNetwork.MapNetworkDrive "s:", "\\***\DATA"

Else If InStr(strGroups, SALES_GROUP) Then
objNetwork.MapNetworkDrive "s:", "\\***\DATA"
End If
end if
end if
end if
 
Last edited:
OK, the last attempt didnt work, still getting "Type mismatch - "Join" when a user tries to log in on line 34 which is

If InStr(strGroup, SUPPORT_GROUP) then

i belive. it maps the home directory fine.

Any ideas?
 
Back
Top Bottom