Menu

Category Archives: Projects

As part of a migration from Windows XP to Windows 7, I was asked to come up with a way to export the network printers installed on the XP machines such that they could be reinstalled on the Windows 7 machines. We did not want to capture local printers (printers installed via TCP/IP or connected via USB) or virtual printers (like the Adobe PDF virtual printer or the Microsoft XPS Document Writer). I thought that migrating the printers was less attractive because the source machines are 32-bit Windows XP but the destination machines are 64-bit Windows 7 and the drivers are therefore different.

There are a number of ways to export print queues, printer settings, and printer ports, but for my purposes, I decided that all I wanted was to determine the name of each printer (eg.: \\SERVER\Printer) on the XP machine, export that to a text file on a network share, and then run PrintUI.exe /ga on the Windows 7 machine, looping through the lines from the text file as input.

(Check out the Printer Migration wizard by launching PrintBrmUI.exe, or the command line version %WINDIR%\System32\Spool\Tools\Printbrm /?, for alternatives to printui.exe.)

As an added benefit, I’m also exporting the name of the default printer so that it can be set programatically in the new environment.

importPrinters.vbs

Note that, if your users in Windows 7 are not administrators, you will need to run the script as an administrator (there are a few different ways) or else you’ll get a UAC prompt for each printer installation and the restarting of the print spooler.

Again, watch the paths. This is a home-grown script for my specific environment.

Option Explicit
'This script must be run with administor privileges
'If it is not run with administrator privileges, it will launch a UAC prompt for each printer as it loops through the list
'Here's an interesting article about running VBS as a different user:
'http://blogs.technet.com/b/heyscriptingguy/archive/2006/04/28/how-can-i-use-the-runas-command-to-run-a-script-under-alternate-user-credentials.aspx
'For example:
'runas /profile /user:[username]\[password] "cscript.exe \"F:\Printer Driver Research\Automation\printers-import.vbs"\"
Dim objNetwork, strComputer, strName, strFolder, objFSO, strTextFile, strData, strLine, arrLines, strRunCmd, WshShell
CONST ForReading = 1
'Create a Network Object
Set objNetwork = CreateObject("Wscript.Network")
'Get the local machine name from the Network Object
strComputer = objNetwork.ComputerName
'Get the user's username from the Network Object
strName = objNetwork.UserName
'Create a File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Save the name of the text file as a variable
'Note that the script must be run as an administrator and that invoking the script with
'Run As causes the script to run as though it's located in the same directory as "%SystemRoot%\System32\WScript.exe"
'Hence the need to pass the full path to the printers.txt file
strTextFile = "H:\PRINTERS\printers.txt"
'Open the text file - strData now contains the whole file
strData = objFSO.OpenTextFile(strTextFile,ForReading).ReadAll
'Split the text file into lines
arrLines = Split(strData,vbCrLf)
'Initialize the wshShell
Set WshShell = WScript.CreateObject("WSCript.shell")
'Step through the lines
For Each strLine in arrLines
If Len(strLine) > 0 Then
'Only run the process on lines that aren't blank
' strRunCmd = "rundll32 printui.dll,PrintUIEntry /ga /c\\" & strComputer & " /n" & strLine & ""
strRunCmd = """printui.exe"" /ga /q /c\\" & strComputer & " /n" & strLine & ""
'Echo back the command to be run
' WScript.Echo strRunCmd
'This launches printui.exe
' strRunCmd = """printui.exe"""
'Run the command, display the window, and wait for the command to complete before continuing
Dim result
result = WshShell.Run(strRunCmd, 1, True)
' WScript.Echo result
'Write to the application log that the printer was installed
If result = 0 Then
WshShell.LogEvent 0, "User: " & strName & " - Event: attempted to install printer " & strLine & " with [" & strRunCmd & "] (success unknown)"
End If
' WScript.Echo "Processed printer: " & strLine
End If
Next
'Cleanup
Set objFSO = Nothing
'Wait 10 seconds
WScript.Sleep 10000
'Restart the Print Spooler
RestartService "Print Spooler", True
Sub RestartService( myService, blnQuiet )
' This subroutine restarts a service
' Arguments:
' myService use the service's DisplayName
' blnQuiet if False, the state of the service is displayed
' every second during the restart procedure
'
' Written by Rob van der Woude
' http://www.robvanderwoude.com
' Standard housekeeping
Dim colServices, colServicesTest, objService
Dim objServiceTest, objWMIService, strQuery, strTest
' Create a WMI object
Set objWMIService = GetObject( "winmgmts:\\.\root\CIMV2" )
' Query the services for "our" service
strQuery = "SELECT * FROM Win32_Service WHERE DisplayName='" & myService & "'"
Set colServices = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objService In colServices
' See if we need to tell the user we're going to stop the service
If Not blnQuiet Then
WScript.Echo "Stopping " & myService
End If
' Stop the service
objService.StopService
' Wait until the service is stopped
Do Until strTest = "Stopped"
' Create a new object for our service; this work-around is required
' since otherwise the service's state information isn't properly updated
Set colServicesTest = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objServiceTest In colServicesTest
' Check the service's state
strTest = objServiceTest.State
' See if we need to show the progress
If Not blnQuiet Then
WScript.Echo "State: " & strTest
End If
' Wait 1 second
WScript.Sleep 1000
Next
' Clear the temporary object
Set colServicesTest = Nothing
Loop
' See if we need to tell the user we're going to (re)start the service
If Not blnQuiet Then
WScript.Echo "Starting " & myService
End If
' Start the service
objService.StartService
' Wait until the service is running again
Do Until strTest = "Running"
' Create a new object for our service; this work-around is required
' since otherwise the service's state information isn't properly updated
Set colServicesTest = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objServiceTest In colServicesTest
' Check the service's state
strTest = objServiceTest.State
' See if we need to show the progress
If Not blnQuiet Then
WScript.Echo "State: " & strTest
End If
' Wait 1 second
WScript.Sleep 1000
Next
' Clear the temporary object
Set colServicesTest = Nothing
Loop
Next
End Sub

setDefaultPrinter.vbs

Finally, we want to set the default printer. The printer will have to already exist (obviously). If you’ve just fired off the printui.exe /ga command to install the printer, it won’t be available until the print spooler is restarted. So wait a minute or two before running the script.

I just picked up an old Dell Precision 690 workstation, which I intend to develop into a file server, a Windows IIS server, and an Ubuntu LAMP server. This monster was built in 2006, but it still has some neat specs and tons of capacity (7 PCI slots, 4 hard drive bays, etc…), should I want to expand further.

This is not a normal tower

Right away, the size of this thing suggests it isn’t a normal tower. It’s about up to my knee and weights 70 lbs. It feels like it’s made with heavier gauge steel than the typical chassis, but that may be me projecting.

I immediately shopped around for more RAM, obviously. 2GB seems a little thin, even by 2006 standards, when considering the way everything else is high-end. The mainboard has 8 slots and supports up to 32GB, but I figure 6GB is a safe place to start.

The workstation has three enormous fans, like, big-as-your-hand big. Running it with the chassis open causes some sort of thermal protection system to kick in and it spins the fans up to the point that they were blowing stuff on the floor half-way across the room.

The CPU has a big, passive heat sink with six copper pipes and sits between two of those fans. I’m tempted to buy a second CPU, but I’ll hold off.

I’m still on the fence about the SCSI drive. It should be super fast, but I’m a little spoiled by the SSD in my machine at work, so it’s hard to get excited about a mechanical drive, even one running at 15k RPM.

The Nvidia Quadro card is also fanless, and has a bizarre DMS-59 connector. An adapter converts the DMS-59 connector into two DVI outputs.

For some time, I’ve felt that Ardamis.com was being pulled in two directions. It started out as something of a business card, then it landed me a job, and so the focus changed and it became more of a personal blog. A few years later, I found myself posting mainly code snippets from personal projects and announcements of new site launches.

So, I’ve determined that I’ll keep Ardamis.com as a place for experimentation and create a new site to handle the web development business – Aleph Studios. It’s so new that I have to think sometimes about how Aleph is spelled as I type it.

I’ll be migrating some of the pages away from Ardamis over the next week or two.

A friend who does a lot of selling on eBay asked me to develop a web application for generating HTML templates that could be copied and pasted into his auctions. He wanted to be able to add a title, a description, and some terms and conditions, and also to be able to upload images so the auction template would display thumbnails that could be clicked to display full-sized versions in a new window or tab. The more we talked, the more it sounded like something that would be both useful for a good number of people, and potentially a source of ad revenue for us. And so was born Simple Auction Wizard, an online HTML template generator for auction websites like eBay.

I was looking for just this kind of a project because I wanted a reason to play with TinyMCE, an Open Source, platform independent, web-based JavaScript HTML WYSIWYG editor control, and SWFUpload, a small JavaScript/Flash library that does very neat things with file uploads.

The most difficult part was actually getting the templates to look good in a variety of browsers. Because the template HTML appears inside of a larger page, I couldn’t rely on Doctype switching to place IE into standards mode. This meant the templates would have to be developed so that they would look approximately the same in standards-compliant browsers like Firefox, Chrome, and Safari, as well as horrible browsers like IE6 in quirks-mode. I tried very hard to minimize the use of tables, but they eventually crept in. I was able to use CSS, for the most part, though if any more issues come up, I’m going to throw in the towel and just do inline styles.

The web app is open to the public, but realize that it’s very early in its development and I intend to continue making changes.