Showing posts with label VBScript. Show all posts
Showing posts with label VBScript. Show all posts

2008-10-23

Add an IE Favorite to a User Profile via VBScript

If your company has an IT support website or any other website people need to visit regularly, but never bookmark then this is a handy logon script.

This script creates a shortcut both on the desktop and in IE for the specified website. It is also possible to set a custom icon for the link (I used my company's logo), but that is 100% optional. The icon code is commented out below. Without it your link will have the default Internet Explorer icon.

All you need to do is change "http://example.com" to the website you want to link to.







'------------------------------
'Author: Christopher Maddalena
'Date: October 17, 2007
'Purpose: Create an IE shortcut for example.com on the user's desktop and favorites list.
'How: The script checks for the existence of the shortcut and, if it does not exists, creates it.
' The shortcut is created in two places under the name "IT SUPPORT.url":
' 1) In the current user's Favorites list in IE.
' 2) In the All Users desktop directory.
' The desktop shortcut is made slightly differently as an .LNK to allow for changing the icon.
'------------------------------

Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Dim objShell, objShortcut

'Create the desktop shortcut
Set objShell = CreateObject("WScript.Shell")
Set objShortcut = objShell.CreateShortcut("C:\Documents and Settings\All Users\Desktop\IT SUPPORT.url")
objShortcut.TargetPath = objShell.ExpandEnvironmentStrings("http://example.com")
'objShortcut.IconLocation = "\\FOLDER_PATH\ICON.ICO"
objShortcut.Save

'Create the IE favorite
Set objShell = CreateObject("WScript.Shell")
Set objShortcut = objShell.CreateShortcut("C:\Documents and Settings\All Users\Favorites\IT SUPPORT.url")
objShortcut.TargetPath = objShell.ExpandEnvironmentStrings("http://example.com")
'objShortcut.IconLocation = "\\FOLDER_PATH\ICON.ICO"
objShortcut.Save
End Sub

Set Windows Wallpaper, IE Homepage and Colors via VBScript

This script sets the user's IE homepage, background wallpaper and color scheme via the registry. I used it to control the wallpaper company wide. Each division has it's own logo, so I used the user's DN (Distinguished Name) in Active Directory to look for specified OUs that would be used to determine what wallpaper they should have.

The wallpaper image file would be copied to their local drive and the path is saved as a variable to be written to the registry. The background color is also modified (to my company's logo color) and the homepage is set.

I have left a single example in for reference. The example looks for the "Admin Staff" OU to be listed.

The LDAP query will obviously need to be modified to match your domain controller.







'------------------------------
'Author: Christopher Maddalena
'Date: November 14, 2007
'How: The user's distinguished name is pulled from AD and searched for specific
'OUs. Registry keys are altered using WScript.Shell
'to change the background colors and wallpaper image.
'------------------------------
Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Const HKCU = &H80000001
Const HKUSER = &H80000003

Dim objShell, objFileSystem, objFileCopy, objSrcFile, objADSystemInfo, objUser, objCommand, objConnection, objRootDSE, objRecordSet, objNetwork, objRegistry
Dim strRegLocate, strWallpaperPath, strCopyPath, strDNSDomain, strstrFilter, strAttributes, strQuery, strUserName, strDN, dwValue, strRegPath, strKey, strComputer

Set objShell = WScript.CreateObject("WScript.Shell")
Set objFileSystem = CreateObject("Scripting.FileSystemobject")
Set objNetwork = CreateObject("WScript.Network")

strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

objCommand.Properties("Page Size") = 1000

'Pull the username for the query
strUserName = objNetwork.UserName

'Query the user's distinguishedName from AD
objCommand.CommandText = "SELECT distinguishedName FROM 'LDAP://dc=AD,dc=AD,dc=AD' WHERE objectCategory='user' " & _
"AND sAMAccountName='" & strUserName & "'"

Set objRecordSet = objCommand.Execute

strCopyPath = objShell.ExpandEnvironmentStrings("%programfiles%") & "\FOLDER\"

strDN = objRecordSet.Fields("distinguishedName").Value

'Test function - Applies to the Admin Staff OU
'If InStr(strDN,"Admin Staff") Then
'Set objSrcFile = objFilesystem.GetFile("\\FILE_PATH\WALLPAPER.JPG")

'objFileSystem.CopyFile objSrcFile.Path, strCopyPath

'strWallpaperPath = strCopyPath & "WALLPAPER.JPG"
'End If

'Set the user's homepage
'strRegLocate = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\Start Page"
'objShell.RegWrite strRegLocate,"WEBSITE", "REG_SZ"

'Set the user's wallpaper
strRegLocate = "HKEY_CURRENT_USER\Control Panel\Desktop\Wallpaper"
objShell.RegWrite strRegLocate, strWallpaperPath

'Set the wallpaper style (centered)
strRegLocate = "HKEY_CURRENT_USER\Control Panel\Desktop\WallpaperStyle"
objShell.RegWrite strRegLocate, "0", "REG_SZ"

'Set the background color
strRegPath = "Control Panel\Colors\"
strKey = "Background"
objRegistry.GetStringValue HKCU,strRegPath,strKey,dwValue
strRegLocate = "HKEY_CURRENT_USER\Control Panel\Colors\Background"
MsgBox(dwValue)
'If not already the correct color, change it
If dwValue <> "0 34 79" Then
objShell.RegWrite strRegLocate,"0 34 79", "REG_SZ"
End If

'strRegLocate = "HKEY_USERS\.DEFAULT\Control Panel\Colors\Background"
'objShell.RegWrite strRegLocate,"0 34 79", "REG_SZ"

'Save the changes
objShell.Run "%windir%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters", 1, True
End Sub

Simple Script for Executing an .EXE

I figured I'd add some simple scripts to the collection. This one is almost too simple, but it might help a beginner out there somewhere.

If you just need a quick, no nonsense script to execute a target .exe file you can use the code below:






Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Dim objShell : Set objShell = CreateObject("Wscript.Shell")

objShell.Run "\\FILE_PATH\FILE.EXE", 0, True

Set objShell = Nothing
End Sub

2008-09-08

New & Improved Active Directory Clean-up Script

Introducing the new and improved AD clean-up script!

This new iteration is has a new function added to it called NSLookup(). This function does just what you'd imagine it does; runs nslookup against a computer name.

Before a machine account is added to the stale account text file the NSLookup() function performs the command with that machine's name. If a name is not returned in the results then the machine is added to the stale accounts.

Another new feature of the script creates a separate text file for machine names that do return a name in the results. The text file is called Problem Accounts.txt. The reason for this is any account that is not reporting login timestamps to the domain controller(s), but is recognized by nslookup could be experiencing problems and warrant further investigation.

The new script runs just as fast as the old version. By using nslookup instead of pinging the machine name the script does not have to wait for a response or timeout. I do recommend running this script with cscript now because of this. If you simply run it as a .vbs file you'll watch a ton of command windows open and close very rapidly. It's rather amusing, but it can be irritating.

Try opening it like that with Wireshark running and you're likely to cause someone to have a seizure.

I'm now going to begin working on version 3. Originally, I did not want to automate this process completely, but now that it is practically bulletproof I am going to automatically disable and move the stale accounts. So look forward to that.

As before, credit for the script that I built this script off of goes to Richard Mueller.

His original scripts and documentation can be found here (http://www.rlmueller.net/Last%20Logon.htm)

Download Link







'------------------------------
'Author: Christopher Maddalena w/ Richard Mueller
'Date: October 17, 2007; Revised: September 8, 2008
'Purpose: List stale user and computer account in AD in a text file.
'How: Dictionary objects are created to store the computer and user names for both disabled.
' and current accounts. These objects are segregated in this manner to allow for
' comparison. If a user/computer name exists on both lists then that account is active.
' This is done to remove the chance an active user or computer account are marked as stale
' because they have not been active on one particular domain controller.
' ADO and LDAP are used to query each domain controller sperately for the name and lastLogon
' attribute to ensure accuracy. The lastLogon attribute is compared to the current
' date and time set to the time zone bias pulled from he registry.
' Run this script using cscript: cscript ADCleanUpV2.vbs > output.txt
'------------------------------

Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Dim intHigh, intLow, intSeconds, str64Bit, strOutput, arrDC()
Dim strNumDays, strTodaysDate, strDeleteDate, strRealDeleteDate, strTimeZoneKey, strTimeZone, k, strConfig, strDNSDomain, strQuery, strDN
Dim strDTMDate, strDTMDateValue, strDTMAdjusted, strStaleDays, strUser, strBase, strFilter, strAttributes, strComputer

'Declare and set objects
Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Dim objShell : Set objShell = CreateObject("WScript.Shell")
Dim objLogFile : Set objLogFile = objFileSystem.CreateTextFile("C:\Stale Accounts.txt", True)
Dim objLogFile2 : Set objLogFile2 = objFileSystem.CreateTextFile("C:\Problem Accounts.txt", True)
Dim objRootDSE : Set objRootDSE = GetObject("LDAP://RootDSE")

'Declare and set dictionary objects
Dim objComputerList : Set objComputerList = CreateObject("Scripting.Dictionary")
objComputerList.CompareMode = vbTextCompare
Dim objUserLIst : Set objUserList = CreateObject("Scripting.Dictionary")
objUserList.CompareMode = vbTextCompare
Dim objCurrentUserList : Set objCurrentUserList = CreateObject("Scripting.Dictionary")
objCurrentUserList.CompareMode = vbTextCompare
Dim objCurrentComputerList : Set objCurrentComputerList = CreateObject("Scripting.Dictionary")
objCurrentComputerList.CompareMode = vbTextCompare

'Set values for current date time and
strNumDays = 30 'Number of days stale
strStaleDays = strNumDays
strStaleDays = 0 - strStaleDays
strTodaysDate = CDate(Now())
strDeleteDate = CDate(Now()) - strNumDays
strRealDeleteDate = "#" & strDeleteDate & "#"
strDTMDateValue = DateAdd("d", strStaleDays, strTodaysDate)
objLogFile.WriteLine(strDTMDateValue)

'Obtain local time zone bias
strTimeZoneKey = objShell.RegRead("HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(strTimeZoneKey)) = "LONG") Then
strTimeZone = strTimeZoneKey
ElseIf (UCase(TypeName(strTimeZoneKey)) + "VARIANT()") Then
strTimeZone = 0
For k = 0 To UBound(strTimeZoneKey)
strTimeZone = strTimeZone + (strTimeZoneKey(k) * 256^k)
Next
End If

'Convert datetime value to UTC for query
strDTMAdjusted = DateAdd("n", strTimeZone, strDTMDateValue)

'Find number of seconds since 1/1/1601
intSeconds = DateDiff("s", #1/1/1601#, strDTMAdjusted)

'Convert seconds to a string and convert to 100-nanosecond intervals
str64Bit = CStr(intSeconds) & "0000000"

'Determine configuration context and DNS domain from RootDSE
strConfig = objRootDSE.Get("configurationNamingContext")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

'Use ADO to search AD for nTDSDSA to identify domain controllers
Dim objCommand : Set objCommand = CreateObject("ADODB.Command")
Dim objConnection : Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection

strBase = ""
strFilter = "(objectClass=nTDSDSA)"
strAttributes = "AdsPath"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"

objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Asynchronous") = True
objCommand.Properties("Timeout") = 60
objCommand.Properties("Cache Results") = False

Dim objRecordSet : Set objRecordSet = objCommand.Execute

'Enumerate through nTDSDSA and set domain controller AdsPaths into arrays
k = 0
Do Until objRecordSet.EOF
Dim objDC : Set objDC = GetObject(GetObject(objRecordSet.Fields("AdsPath").Value).Parent)
ReDim Preserve arrDC(k)
arrDC(k) = objDC.DNSHostName
k = k + 1
objRecordSet.MoveNext
Loop
objRecordSet.Close

'Retrieve lastLogon attribute for each USER on each controller
For k = 0 To UBound(arrDC)
strBase = ""
strFilter = "(&(ObjectCategory=Person)(objectClass=User))"
strAttributes = "name,lastLogon"
strQuery = strBase & ";" & strFilter & ";" & strAttributes _
& ";subtree"
objCommand.CommandText = strQuery
On Error Resume Next
Set objRecordSet = objCommand.Execute
If (Err.number <> 0) Then
On Error GoTo 0
objLogFile.WriteLine("Domain Controller not available: " & arrDC(k))
Else
On Error GoTo 0
Do Until objRecordSet.EOF
strDN = objRecordSet.Fields("name").Value
On Error Resume Next
Dim objDate : Set objDate = objRecordSet.Fields("lastLogon").Value
If (Err.number <> 0) Then
On Error GoTo 0
strDTMDate = #1/1/1601#
Else
On Error GoTo 0
intHigh = objDate.HighPart
intLow = objDate.LowPart
If (intLow < inthigh =" intHigh" inthigh =" 0)" intlow =" 0)" strdtmdate =" #1/1/1601#" strdtmdate =" #1/1/1601#"> strDTMDate Then
If (objUserList.Exists(strDN) = True) Then
If (strDTMDate > objUserList(strDN)) Then
objUserList.Item(strDN) = strDTMDate
End If
Else
objUserList.Add strDN, strDTMDate
End If
Else
If (objCurrentUserList.Exists(strDN) = True) Then
If (strDTMDate > objCurrentUserList(strDN)) Then
objCurrentUserList.Item(strDN) = strDTMDate
End If
Else
objCurrentUserList.Add strDN, strDTMDate
End If
End If
If objUserList.Exists(strDN) AND objCurrentUserList.Exists(strDN) Then
objUserList.Remove(strDN)
End If
objRecordSet.MoveNext
Loop
objRecordSet.Close
End If
Next

'Output users to log file
objLogFile.WriteLine ""
objLogFile.WriteLine("USERS + LAST LOGIN DATE AND TIME: ")
objLogFile.WriteLine ""

For Each strUser In objUserList.Keys
objLogFile.WriteLine strUser & ";" & objUserList.Item(strUser)
Next

'Retrieve lastLogon attribute for each COMPUTER on each controller
For k = 0 To UBound(arrDC)
strBase = ""
strFilter = "(&(objectClass=Computer)(lastLogon<=" & str64Bit & "))" strAttributes = "name,lastLogon" strQuery = strBase & ";" & strFilter & ";" & strAttributes _ & ";subtree" objCommand.CommandText = strQuery On Error Resume Next Set objRecordSet = objCommand.Execute If (Err.number <> 0) Then
On Error GoTo 0
objLogFile.WriteLine("Domain Controller not available: " & arrDC(k))
Else
On Error GoTo 0
Do Until objRecordSet.EOF
strDN = objRecordSet.Fields("name").Value
On Error Resume Next
Set objDate = objRecordSet.Fields("lastLogon").Value
If (Err.number <> 0) Then
On Error GoTo 0
strDTMDate = #1/1/1601#
Else
On Error GoTo 0
intHigh = objDate.HighPart
intLow = objDate.LowPart
If (intLow < inthigh =" intHigh" inthigh =" 0)" intlow =" 0)" strdtmdate =" #1/1/1601#" strdtmdate =" #1/1/1601#"> strDTMDate Then
If (objComputerList.Exists(strDN) = True) Then
If (strDTMDate > objComputerList(strDN)) Then
objComputerList.Item(strDN) = strDTMDate
End If
Else
objComputerList.Add strDN, strDTMDate
End If
Else
If objComputerList.Exists(strDN) AND objCurrentComputerList.Exists(strDN) Then
objComputerList.Remove(strDN)
End If
End If
objRecordSet.MoveNext
Loop
objRecordSet.Close
End If
Next

objLogFile.WriteLine("")
objLogFile.WriteLine("COMPUTERS + DATE OF LAST USER LOG IN: ")
objLogFile.WriteLine ""

objLogFile2.WriteLine "Possible Problematic Machine Accounts:"
objLogFile2.WriteLine "These machines resolve to a name, but do not appear to be communicating with the domain."

'Close text file
objLogFile.Close
objLogFile2.Close

For Each strComputer In objComputerList.Keys
NSLookup(strComputer)
Next

'Clean up
objConnection.Close
Set objRootDSE = Nothing
Set objConnection = Nothing
Set objCommand = Nothing
Set objRecordset = Nothing
Set objDC = Nothing
Set objDate = Nothing
Set objUserList = Nothing
Set objComputerList = Nothing
Set objShell = Nothing

MsgBox("Query is complete.")
End Sub

Function NSLookup(strComputer)
Dim strLine, strBool

Dim objFileSystem : Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Dim objLogFile : Set objLogFile = objFileSystem.OpenTextFile("C:\Stale Accounts.txt", 8, True)
Dim objLogFile2 : Set objLogFile2 = objFileSystem.OpenTextFile("C:\Problem Accounts.txt", 8, True)
Dim objShell : Set objShell = CreateObject("WScript.Shell")

Dim objWshScriptExec : Set objWshScriptExec = objShell.Exec("nslookup " & strComputer)

Dim objStdOut : Set objStdOut = objWshScriptExec.StdOut

strBool = "0"

Do Until objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
If left(strLine,4) = "Name" Then
objLogFile2.WriteLine strComputer
objLogFile2.WriteLine ""
strBool = "1"
End If
Loop
If strBool = "0" Then
objLogFile.WriteLine strComputer
End if

objLogFile.Close
objLogFile2.Close
End Function


2008-09-04

New & Improved AD Clean-up Script: Coming Soon!

Recently we discovered that my Active Directory cleanup script is not 100% correct. This is not an error in the coding, but rather due to an error on the machine it's querying.

We noticed some machine names that we knew were not inactive account were showing up as stale. Upon further investigation in the computer's event logs we saw a lot of problems indicating it was not communicating with the domain controller correctly. This resulted in old lastLogon timestamps.

After removing the computer from the domain and reaadding it we had up-to-date timestamps and the logs were clear.

I am currently working on implementing a way for the script to ping the computer name before adding outputting it to the Stale Account text file. If it resolves into an IP address, we know it is active because it has a DNS entry. If it does not, it's pretty safe to say it's a stale account.

I will post the new and improved script once it's finished.

VBScript Powered HTML Application to Install Printers

This is a handy little application every IT help desk needs. The number one reason an employee will call our department is to request a printer be installed. Maybe they deleted it, maybe they got a new printer, or maybe they traveled to another branch. Whatever the reason, it's time consuming and painfully monotonous.

That's why I developed this great HTA (HTML Applicaton) powered by a VBScript that makes use of WMI to install a printer. Basically, an HTA is a container for website, but it's a website that is unaffected by browser security features (like script blocking). Unfortunately this doesnot work "out of the box". You don't need this exact setup, but this is what you won't seewhen you look at my script:

I have two databases this HTA connects to. We have a large number of remote branches and we support them all, so one database is all branch names and numbers. The other is a database of printer types and IP addresses all tied to a corresponding branch ID.

I have the printer drivers stored on a network share for easy manual access and updating as needed.

Various graphics are used to make things pretty.

I have had to strip out the HTML so you can actually see the script, but that's OK, the script is the meat of this post.

Each printer type will require some testing. If an .INF file is supplied as the driver, you have it easy. However, if you look at the second printer in this script, you will see some special code is required for others. In this example, HP only supplies .EXE files, but there are some special commands you can use to run it silently.

To transform this into a functioning HTA with a GUI you simply need to add HTML tags and an HTA tag block to it. Then save it as Whatever.HTA. Just be sure to alter the script as necessary if you name your listboxes and button differently or decide you don't need multiple printer types or a location listbox.

If you need any clarification, feel free to comment. I'm happy to help!





'------------------------------
'Author: Christopher Maddalena
'Date: December 20, 2007
'Purpose: Create a TCP/IP port for a printer and install it using a non-natice driver.
'How: The script creates a TCP/IP port, retrieves the .INF driver file and performs the
' Add Printer task by using a specified .INF, name and IP address with WMI.
'------------------------------

'Create the connection to the database
Set objConn = CreateObject("ADODB.Connection")
Set objConn2 = CreateObject("ADODB.Connection")

'Open the connection to the database
objConn.Open "ConnectionString"
objConn2.Open "COnnectionString 2"

On Error Resume Next
Err.Clear

'Commands executed on load
Sub window_onLoad()
'Resize the window to 525x550
window.resizeTo 525,600

'Populate listbox (lstBranch) with branch names from database
Set objRecordset = CreateObject("ADODB.Recordset")
'Open a dynamic recordset (allows for updating, movePrevious, and more)
objRecordset.Open "SQL statement", objConn, 2
'Create new listbox options until the end of the database rows
Do Until objRecordset.EOF = True
Set objOption = Document.createElement("OPTION")
objOption.Text = objRecordset("Branch # 'n Such") & " - " & objRecordset("Branch Location or City")
objOption.Value = objRecordset("Branch #")
lstBranch.Add(objOption)
objRecordset.MoveNext
Loop
objRecordset.Close

objRecordset.Open "SQL statement", objConn2, 2
'Create new listbox options until the end of the database rows
Do Until objRecordset.EOF = True
Set objOption = Document.createElement("OPTION")
objOption.Text = objRecordset("The printer type or name")
objOption.Value = objRecordset("A unique ID")
lstPrinter.Add(objOption)
objRecordset.MoveNext
Loop
objRecordset.Close
End Sub

Sub btnSubmit_onClick()
Dim objFileSystem, objShell, objConn, objXerox6180Driver, objCommand, objCommandType, objRecordset, objWMIService, objNewPort, objPrinter, objDriver
Dim intResult, ip, portName, strComputer

Set objRecordset = CreateObject("ADODB.Recordset")
Set objShell = CreateObject("WScript.Shell")
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

Select Case lstPrinter.Value
'Nothing selected
Case 0
MsgBox("You must select a printer.")
'Xerox Phaser 6180MFP
Case 1
Set objXerox6180Driver = objFileSystem.GetFolder("\\Path to Driver\Xerox 6180MFP\")

objRecordset.Open "SQL statement with listbox values", objConn2, 2

Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConn2
objCommand.CommandText = "SQL statement with listbox values"
objCommandType = 1

objRecordset.Close

Set objRecordset = objCommand.Execute

'Check if recordset is empty
'If it is empty, display error dialog or install printer otherwise
If objRecordSet.EOF AND objRecordset.BOF Then
MsgBox("The branch you selected does not have an entry for a Xerox 6180MFP. Please try again.")
Else
objFileSystem.CopyFolder objXerox6180Driver.Path, "C:\", True

ip = objRecordset.Fields("The IP address").Value
portName = "IP_" & ip

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

Set objNewPort = objWMIService.get("Win32_TCPIPPrinterPort").SpawnInstance_
Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_
Set objDriver = objWMIService.Get("Win32_PrinterDriver")

'Installs Printer Driver
objDriver.Name = "Xerox Phaser 6180MFP-N PS"
objDriver.SupportedPlatform = "Windows NT x86"
objDriver.Version = "3"
objDriver.FilePath = "C:\Xerox 6180MFP"
objDriver.InfName = "C:\Xerox 6180MFP\xrpsgbei.inf"
intResult = objDriver.AddPrinterDriver(objDriver)

'Installs Printer Port
objNewPort.Name = portName
objNewPort.Protocol = 1
objNewPort.HostAddress = ip
objNewPort.PortNumber = 9100
objNewPort.SNMPEnabled = True
objNewPort.Put_

'Install Printer
objPrinter.DriverName = "Xerox Phaser 6180MFP-N PS"
objPrinter.PortName = portName
objPrinter.DeviceID = lstBranch.Value & " - " & "Xerox 6180 MFP"
objPrinter.Location = ""
objPrinter.Network = True
objPrinter.Put_

MsgBox("Your printer should now be installed. If the following number is NOT zero, please restart and try again if your printer is missing. If it continues, contact the help desk. #: " & intResult)
End If
'HP 7780 All-In-One
Case 2
'Create and open Postgres connection
Set objConn = CreateObject("ADODB.Connection")

Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConn
objCommand.CommandText = "SQL statement with listbox values"
objCommandType = 1

Set objShell = CreateObject("WScript.Shell")

Set objRecordset = objCommand.Execute

'Check if recordset is empty
'If it is empty, display error dialog or install printer otherwise
If objRecordset.EOF AND objRecordset.BOF Then
MsgBox("The branch you selected does not have an entry for an HP 7780. Please try again.")
Else

ip = objRecordset.Fields("IPAddress").Value
portName = "IP_" & ip

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

Set objNewPort = objWMIService.get("Win32_TCPIPPrinterPort").SpawnInstance_
Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_
Set objDriver = objWMIService.Get("Win32_PrinterDriver")

'Due to the nature of the setup utility and drivers this command must be run to automatically install the 7780
objShell.Run "\\Path to driver\HP7780\\setup.exe -s -pi -p ""C:\HP"" -ipaddress " & ip & " -addadevice -r0"
End If
End Select
End Sub

'Exit button sub
Sub btnExit_onClick()
'Close the connection to the database
objConn.Close

Window.Close
End Sub

Convert Files to Word Documents with a Script

If you've ever needed to convert one or many garbled RTF files into a readable Word document you will appreciate this little script. Instead of having to go to each file, open it in Word, and save it into the .DOC format manually you can use this script to enumerate an entire folder of files and convert them into Word documents.

The script uses Word's API and a file system object to open each file, save it into the Word 2003 .DOC format and close it.

For my purposes, I only wanted to convert .RTF files because I was running it against a folder with .PDF and other file types. You can easily alter the file type or remove this check by deleting the If statement on line 36 - "If LCase(Right(objFile,3)) = "rtf" Then". Just make sure you leave what's inside the If block alone.

Download Link





'------------------------------
'Author: Christopher Maddalena
'Date: October 23, 2007
'Purpose: Convert garbled RTF files into Word .DOCs.
'How: This script enumerates through a folder specified as strFolder
' for every file present, opens the files and save them as .DOCs
' by using Word's API.
'------------------------------

Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Dim objWord, objFileSystem, objSrcFolder, objFile, objDoc, objSelection
Dim strFolder, strFile, strDOC, colFiles, File

Set objWord = CreateObject("Word.Application")
objWord.Visible = True
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

strFolder = "C:\Test" 'Put your folder's path here!

Set objSrcFolder = objFilesystem.GetFolder(strFolder)
Set colFiles = objSrcFolder.Files

For Each File In colFiles
Set objFile = objFileSystem.GetFile(strFolder & "\" & File.Name & "\")

strFile = objFile.Path

strDOC = objFileSystem.BuildPath(objFile.ParentFolder,objFileSystem.GetBaseName(objFile) & ".doc")

If LCase(Right(objFile,3)) = "rtf" Then
Set objDoc = objWord.Documents.Open(strFile)
Set objDoc = objWord.ActiveDocument
Set objSelection = objWord.Selection

'Save actibe document as the default Word .doc and close it
objDoc.SaveAs strDOC, 0
objDoc.Close
End If
Next
'Exit Word
objWord.Quit
End Sub

2008-08-27

InstallShield Scripting and Commands

About a year ago I had some issues scripting a silent installation for a piece of software we used across the company. It's used by almost every employee and must be updated every time the server is. The problem was the creators of the software did a horrible job programming it and one of their transgressions was using a custom InstallShield setup.

This caused a problem because Windows could not run the install silently. It would just hang and eventually crash because of the custom input the program was requesting. Even though the input was limited to "Next" and "Back" buttons.

This is where the lovely /r argument comes in handy. If you run the command c:\setup.exe /r the setup.exe will launch normally and you can run through the installer. The /r records the installation and creates an ISS file. The ISS file is a record of every action you took during the installation.

Then, you could uninstall the software and run c:\setup.exe /s /f1"c:\my-answer-file.iss" and the software would install silently without any user input.

The ISS file will be saved in the Windows directory as setup.iss, but you can save yourself the trouble by providing a file name and target location with /f1 - c:\setup.exe /r /f1"c:\this-will-be-my-answer-file.iss".

You can take this all one step further and use the /SMS as well. /SMS tells the script, batch file, or whatever you're running to wait until the installation is complete. If you do not use then the installation starts and is flagged as complete almost immediately. If you need to apply a patch or do something with the newly installed program in yourscript you will want to use /SMS like so: c:\setup.exe /s /SMS /f1"c:\my-answer-file.iss".

There are a few other tricks as well. Many times you may just want to extract the files from the setup.exe file and run the bundled .MSI files silently instead. To extract the files you can use the /extract_all. You specify a target folder like this c:\setup.exe /extract_all:"c:\temp".

You may want to delay the installation at times. I can't think of a reason to do this off the top of my head, but it is possible with /delayedstart:X. You replace X with the time in seconds and use it like this c:\setup.exe /delayedstart:10. That command will run setup.exe 10 seconds after I run that command.

Finally, there is a way to uninstall a program as well. You can use /uninst for this. It's not guaranteed to work with every InstallShield executable, but it may be a great shortcut for you one day. You use it just like any of the others c:\setup.exe /uninst.

2008-08-14

Removing Symantec AntiVirus via Script

As my company's IT Project Tech I was given the task of finding a replacement for our old desktop AntiVirus solution. That's not hard; the hard part was finding the most efficient way of removing the old AV clients (Symantec) from all of our workstations distributed across the country.

That's still not too hard, but there was a twist. Before I started with the company we had not stuck with a single client across the board for our desktops. One look at my software inventory showed I had not one, not two, but 4 different versions of Symantec AntiVirus on the network.

Each different version has it's own unique registry key. For this purpose I will leave the script at its current length for example IDs of the various Symantec versions. Speaking of length, it's not the most elegant script, but it gets the job done. I plan to give it a once-over later on to see if I can't make it even better.

The one thing this script does not do is remove Live Update. I could not lash together a way to bypass Live Update's warning about removing the service. The warning didn't break the script, but it would require the user to click "Yes" and then continue with the next step. I didn't trust the users to read my e-mail instructing them to click the correct button, so I ended up using my new anti-virus' command console to remove Live Update.

When I find out how they do it so easily (because it runs so smoothly and erases any trace of it) I'll update the script.

To remove Live Update manually you need to run LSETUP.EXE located in one of the Symantec folders. It's either in C:\Program Files\Symantec\Live Update\ or in C:\Program Files\Symantec AntiVirus\. LSETUP.EXE will install the Live Update, so you need to add the "/U" argument to the command:

"C:\Program Files\Symantec\Live Update\LSETUP.EXE" /U

That command will launch the uninstall process. You may also want to stop various services first. I did not need to, but you can do it with net stop:

cmd /c net stop "Symantec AntiVirus"

You can replace "Symantec AntiVirus" with any other service's name.

The other obstacle you may need to overcome is the password portection on the AntiVirus install. If you have a password requirement enabled the script disables it via the registry.

Once the script has removed the registry keys it can continue with the uninstall, also via the registry. It uses MsiExec.exe to silently uninstall the appropriate version.

Note: If your version is not listed you can find the registry key under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\.

Here you go:





'------------------------------
'Author: Christopher Maddalena
'Date: June 20, 2008
'Purpose: Uninstall various Symantec Anti-Virus clients
'How: This script runs MsiExec.exe with SAV's uninstall registry key.
'------------------------------

Option Explicit
Call Main()
WScript.Quit(0)

On Error Resume Next

Sub Main
Const HKEY_LOCAL_MACHINE = &H80000002

Dim objShell, objRegistry, objFileSystem
Dim strComputer, strKeyPath, strValueName, strValue, strSAV, strSAV0, strSAV1, strSAV2, strSAV3
Dim strFolder0, strFolder1, strFolder2

strFolder0 = "C:\Program Files\Symnatec"
strFolder1 = "C:\Program Files\Symantec AntiVirus"
strFolder2 = "C:\Program Files\Common Files\Symantec Shared"

strComputer = "."

Set objShell = WScript.CreateObject("WScript.Shell")
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
Set objFileSystem = WScript.CreateObject("Scripting.FileSystemObject")

strValueName = "DisplayName"

'Set registry keys to disable Symantec uninstall password
objShell.RegWrite "HKLM\SOFTWARE\Intel\LANDesk\VirusProtect6\CurrentVersion\AdministratorOnly\Security\LockUnloadServices", "0", "REG_DWORD"
objShell.RegWrite "HKLM\SOFTWARE\Intel\LANDesk\VirusProtect6\CurrentVersion\AdministratorOnly\Security\UseVPuninstallPassword", "0", "REG_DWORD"

'Check for SAV 10.1.4000.4
strSAV = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{46B63F23-2B4A-4525-A827-688026BE5E40}"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strSAV, strValueName, strSAV0

'Check for SAV 10.1.394.0
strSAV = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{A011A1DC-7F1D-4EA8-BD11-0C5F9718E428}"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strSAV, strValueName, strSAV1

'Check for SAV 10.1.5000.5
strSAV = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{78D891EF-9E2D-4FC8-A71F-E6F897BA1B21}"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strSAV, strValueName, strSAV2

'Check for SAV 10.0.2000.2
strSAV = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{46B63F23-2B4A-4525-A827-688026BE5E40}"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strSAV, strValueName, strSAV3

'Remove SAV 10.1.4000.4 if installed
If Not IsNull(strSAV0) Then
objShell.Run "MsiExec.exe /norestart /q /x {46B63F23-2B4A-4525-A827-688026BE5E40} REMOVE=ALL"
End If

'Remove SAV 10.1.394.0 if installed
If Not IsNull(strSAV1) Then
objShell.Run "MsiExec.exe /norestart /q /x {A011A1DC-7F1D-4EA8-BD11-0C5F9718E428} REMOVE=ALL"
End If

'Remove SAV 10.1.5000.5 if installed
If Not IsNull(strSAV2) Then
objShell.Run "MsiExec.exe /norestart /q /x {78D891EF-9E2D-4FC8-A71F-E6F897BA1B21} REMOVE=ALL"
End If

'Remove SAV 10.0.2000.2 if installed
If Not IsNull(strSAV3) Then
objShell.Run "MsiExec.exe /norestart /q /x {46B63F23-2B4A-4525-A827-688026BE5E40} REMOVE=ALL"
End If

' If objFileSystem.FolderExists(strFolder0) Then
' Set tempFolder = objFileSystem.GetFolder(strFolder0)
' tempFolder.Delete
' End If
'
' If objFileSystem.FolderExists(strFolder1) Then
' Set tempFolder = objFileSystem.GetFolder (strFolder1)
' tempFolder.Delete
' End If

' If objFileSystem.FolderExists(strFolder2) Then
' objFileSystem.DeleteFolder(strFolder2),True
' End If
End Sub