Selective searching in Windows XP: When search all doesn’t search all

A company I do work for upgraded their desktops from Windows NT 4.0 to Windows XP a few weeks back. Recently, one of the workers at this firm came to me with a problem. He used to use the “Find Files” feature in Windows NT 4.0 to search for files based on file content. In Windows XP, he does the same with the “Search for a word or phrase in the file” feature… but he doesn’t find files under XP that he used to find under NT.

A quick little Google search (using the keywords "windows xp" search "word or phrase in the file" "not found") landed right on a Microsoft Knowledge Base article, 309173: Using the "A word or phrase in the file" search criterion may not work. Apparently, Windows XP “improved” the file content search feature by not actually searching for the content in all the files and file types you specify. As a result, doing a content for search in files with extensions like .SQL or .CSS will not work.

OK, I can handle a feature change, but they probably should clarify exactly what they mean when you are searching for “a word or phrase in the file” when your file criteria is *.*. Even more, the resolution to the problem (as outlined in the support article) is about the most obscure “fix” I’ve ever seen. At least they documented it!

Toggling your HOSTS file

I use my laptop (a highly-recommended Toshiba Portege M100) for most of my development work. Typically, I develop on my laptop (a sandbox environment), then push data to another server (either a staging or production server). One of the problems I run into is my ever-changing physical location. When I’m at home, certain Web sites need internal IP addresses; at other places, they need external IP addresses.

The solution to this problem is by toggling the use of your HOSTS file. I enterd all the static entries into my HOSTS file, and created a small batch file to “toggle” the HOSTS file on and off. (When the HOSTS file exists, it is used, so renaming it to something other than HOSTS – with no file extension – turns it “off”.)

The batch file for toggling the HOSTS file is:

if exist c:\windows\system32\drivers\etc\hosts goto :hosts_off
:hosts_on
ren c:\windows\system32\drivers\etc\hosts.toggle hosts
goto :end
:hosts_off
ren c:\windows\system32\drivers\etc\hosts hosts.toggle
goto :end
:end
ipconfig /flushdns

The batch file simply changes the file from hosts to hosts.toggle and back again. The command ipconfig /flushdns is executed at the end to ensure the DNS cache is flushed.

Configuring Trusted SQL Connections in ASP.Net and Windows 2003

While configuring a new server running Microsoft Windows Server 2003, I decided to start using trusted SQL connections from ASP.Net Web sites (instead of specific SQL user accounts). One of the differences between Windows 2000 and Windows 2003 is the ASP.Net process account; the former uses ASPNET, the latter NETWORK SERVICE.

One thing you’ll notice is that when creating a new login for SQL Server is that you can’t select the NETWORK SERVICE account. (Oddly, you can select the ASPNET account, but I don’t know what it is used for in Windows 2003/IIS 6.0, since it’s been replaced with NETWORK SERVICE.) After plenty of searching I found a newsgroup posting from Microsoft that solved the problem.

In brief: Either specify the username as NT AUTHORITY\NETWORK SERVICE in SQL Enterprise Manager’s New Login window, or run the following query:

exec sp_grantlogin [NT AUTHORITY\NETWORK SERVICE]

Yet another example of Microsoft hiding the obvious.

SSL stopped working in IIS? It might be Verisign’s certificates

One of my IIS servers at work suddenly stopped responding to SSL traffic. Normal HTTP (port 80) traffic worked fine. SSL traffic over any port (the standard port 443 as well as others) would make a connection but not transfer any data.

It wasn’t a network problem, or a firewall problem, or an IIS problem. It turned out to be a problem with the Verisign certification authority certificate. Apparently this is a known problem within Microsoft and Verisign. Read about it in Microsoft’s Knowledge Base Article #834438.

The solution is easy, and is Verisign has a certificiate authority replacement Web site with all the details. You can implement the solution even if you don’t have the problem – just to be safe.

A free Offline NT Password and Registry Editor

From time to time, the open source/freeware community comes along with a product so simple and so frightening that it makes me smile. This is one that’s been around since 1997, but somehow I never stumbled across it.

A fine Norseman, Petter Nordahl-Hagen, wrote the first version of his Windows registry and password hacker back in 1997. He’s updated it continually over the years, and today the Offline NT Password & Registry Editor is available as a free download. (It works with Windows 2000 and Windows XP as well as Windows NT, so don’t let the name fool you.) The Web site includes an excellent FAQ and the source code, should you choose to confound yourself further.

Why is this frightening? Because after all the years of Microsoft touting security, there’s still a freelance programmer that can beat the billion dollar behemoth.

Fixing Internet Explorer’s disappearing status bar

I generally use Internet Explorer to browse Web pages — not because I’m a huge fan of Microsoft, but because IE is the most common web browser (and thus something you should try to code against). Recently, the status bar — the little bar at the bottom of the window that tells you page loading progress and other useful information — would insist on not appearing until I explicitly turned it on (from the menu: View / Status Bar). The setting did not persist between IE sessions, which was rather frustrating.

Apparently this is a known problem, as Microsoft documents it in Knowledge Base Article 330216. Oddly, their workaround is to turn the option on (duh), or to jump through some hoops using IE and Windows Explorer to get the setting to persist.

And I thought there would be a registry hack to fix it… Obviously, that would be too easy!

Decoding event log errors with EventID.Net

While at work one day this week, users started complaining about slow access times to a particular application. After confirming that all applicable servers (an application server and a SQL server) were online, and that there were no SQL problems (such as deadlocks), we took a look at the event log, and found an obscure entry:

Type:  Error
Source:  Userenv
Event ID:  1000
Description:  Windows cannot determine the user or computer name. Return value (1722).

Like many good event log messages this told me little about the actual problem. Rather than scratch my head until an answer mysteriously appeared, I went to perhaps the best resource for understanding event log entries: EventID.net (www.eventid.net).

EventID.net provides a searchable index to events, and has extensive information provided by other users that can be invaluable in troubleshooting problems. Using the site is simple: enter the event ID number and the source and click a search button. The site returns a list of possible matches, including descriptions. Find the one that matches your problem the best and click a link to obtain the details.

In my case, a search for “event ID 1000, source Userenv”  brought me to a results page with a few dozen hits. One of those hits matched my event, so I went to the details page. There’s a lot of information here provided from other users, and one common thread in their posts: check your DNS servers and settings.

Sure enough, there were two problems. This server never had its primary DNS server updated some months ago when we changed DNS servers. Further, we also found out that the secondary server, which was previously processing all DNS requests for this server, had stopped running. We changed the primary DNS server and within a minute were operating normally.

The moral of this story: Look at the event log periodically and whenever there is a problem that doesn’t have a clear solution, and when you do, be sure to use resources such as EventID.net to get a complete understanding of the problem and to use other people’s experiences to solve your problem more quickly.

Windows Server/SQL Server Performance Monitor Template

One of the nice things about Performance Monitor in Windows 2000/2003 is that it can be plugged into an HTML page as an ActiveX control. Even nicer than that is the fact that you can easily edit the parameters for the console by editing the HTML page.

Where I work, we have a handful of SQL servers. To monitor them, I created a performance monitor view with a handful of core counters on one server and saved it as an HTML file. (This is done using the Performance Monitor’s System Monitor. Simply set up your counters then right-click the monitor window and choose Save As.) Making subsequent views for other servers was as simple as making a copy of the HTML file, opening it in Notepad, and changing all server name instances.

Below is the contents of a simple performance monitor HTML page that can be used to monitor a server running Microsoft SQL Server 7.0 or higher. To use it, copy the contents into a text file, rename all instances of SERVERNAME to the name of your server, save it as a .htm file, and open it in Internet Explorer. Viola! Quick and easy view to your server’s core performance counters.

< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html>
<head>
<meta NAME="GENERATOR" Content="Microsoft System Monitor">
</meta></head><body>
<object ID="DISystemMonitor1" WIDTH="100%" HEIGHT="100%"
CLASSID="CLSID:C4D2D8E0-D1DD-11CE-940F-008029004347">
 <param NAME="_Version" VALUE="393219">
 </param><param NAME="_ExtentX" VALUE="28549">
 </param><param NAME="_ExtentY" VALUE="23839">
 </param><param NAME="DisplayType" VALUE="1">
 </param><param NAME="ReportValueType" VALUE="0">
 </param><param NAME="MaximumScale" VALUE="100">
 </param><param NAME="MinimumScale" VALUE="0">
 </param><param NAME="ShowLegend" VALUE="-1">
 </param><param NAME="ShowToolbar" VALUE="-1">
 </param><param NAME="ShowScaleLabels" VALUE="-1">
 </param><param NAME="ShowHorizontalGrid" VALUE="0">
 </param><param NAME="ShowVerticalGrid" VALUE="0">
 </param><param NAME="ShowValueBar" VALUE="-1">
 </param><param NAME="ManualUpdate" VALUE="0">
 </param><param NAME="Highlight" VALUE="0">
 </param><param NAME="ReadOnly" VALUE="0">
 </param><param NAME="MonitorDuplicateInstances" VALUE="-1">
 </param><param NAME="UpdateInterval" VALUE="5">
 </param><param NAME="DisplayFilter" VALUE="1">
 </param><param NAME="BackColorCtl" VALUE="-2147483633">
 </param><param NAME="ForeColor" VALUE="-1">
 </param><param NAME="BackColor" VALUE="-2147483633">
 </param><param NAME="GridColor" VALUE="8421504">
 </param><param NAME="TimeBarColor" VALUE="255">
 </param><param NAME="Appearance" VALUE="-1">
 </param><param NAME="BorderStyle" VALUE="0">
 </param><param NAME="NextCounterColor" VALUE="7">
 </param><param NAME="NextCounterWidth" VALUE="0">
 </param><param NAME="NextCounterLineStyle" VALUE="0">
 </param><param NAME="GraphTitle" VALUE="">
 </param><param NAME="YAxisLabel" VALUE="">
 </param><param NAME="DataSourceType" VALUE="1">
 </param><param NAME="SqlDsnName" VALUE="">
 </param><param NAME="SqlLogSetName" VALUE="">
 </param><param NAME="LogFileCount" VALUE="0">
 </param><param NAME="AmbientFont" VALUE="-1">
 </param><param NAME="LegendColumnWidths" VALUE="0.042654028436019 0.042654028436019 0.218957345971564 5.78199052132701E-02 4.92890995260664E-02 0.17914691943128 7.20379146919431E-02">
 </param><param NAME="LegendSortDirection" VALUE="0">
 </param><param NAME="LegendSortColumn" VALUE="2097272">
 </param><param NAME="CounterCount" VALUE="6">
 </param><param NAME="MaximumSamples" VALUE="100">
 </param><param NAME="SampleCount" VALUE="100">
 </param><param NAME="SampleIndex" VALUE="5">
 </param><param NAME="StepNumber" VALUE="8">
 </param><param NAME="Counter00001.Path" VALUE="\\SERVERNAME\Memory\Pages/sec">
 </param><param NAME="Counter00001.Color" VALUE="4210752">
 </param><param NAME="Counter00001.Width" VALUE="1">
 </param><param NAME="Counter00001.LineStyle" VALUE="0">
 </param><param NAME="Counter00001.ScaleFactor" VALUE="0">
 </param><param NAME="Counter00001.StatisticStatus" VALUE="0">
 </param><param NAME="Counter00002.Path" VALUE="\\SERVERNAME\Processor(_Total)\% Processor Time">
 </param><param NAME="Counter00002.Color" VALUE="128">
 </param><param NAME="Counter00002.Width" VALUE="1">
 </param><param NAME="Counter00002.LineStyle" VALUE="0">
 </param><param NAME="Counter00002.ScaleFactor" VALUE="0">
 </param><param NAME="Counter00002.StatisticStatus" VALUE="0">
 </param><param NAME="Counter00003.Path" VALUE="\\SERVERNAME\SQLServer:Buffer Manager\Buffer cache hit ratio">
 </param><param NAME="Counter00003.Color" VALUE="65535">
 </param><param NAME="Counter00003.Width" VALUE="1">
 </param><param NAME="Counter00003.LineStyle" VALUE="0">
 </param><param NAME="Counter00003.ScaleFactor" VALUE="0">
 </param><param NAME="Counter00003.StatisticStatus" VALUE="0">
 </param><param NAME="Counter00004.Path" VALUE="\\SERVERNAME\SQLServer:General Statistics\User Connections">
 </param><param NAME="Counter00004.Color" VALUE="16711680">
 </param><param NAME="Counter00004.Width" VALUE="1">
 </param><param NAME="Counter00004.LineStyle" VALUE="0">
 </param><param NAME="Counter00004.ScaleFactor" VALUE="-1">
 </param><param NAME="Counter00004.StatisticStatus" VALUE="0">
 </param><param NAME="Counter00005.Path" VALUE="\\SERVERNAME\SQLServer:Locks(_Total)\Average Wait Time (ms)">
 </param><param NAME="Counter00005.Color" VALUE="16711935">
 </param><param NAME="Counter00005.Width" VALUE="1">
 </param><param NAME="Counter00005.LineStyle" VALUE="0">
 </param><param NAME="Counter00005.ScaleFactor" VALUE="0">
 </param><param NAME="Counter00005.StatisticStatus" VALUE="0">
 </param><param NAME="Counter00006.Path" VALUE="\\SERVERNAME\System\Processor Queue Length">
 </param><param NAME="Counter00006.Color" VALUE="16776960">
 </param><param NAME="Counter00006.Width" VALUE="1">
 </param><param NAME="Counter00006.LineStyle" VALUE="0">
 </param><param NAME="Counter00006.ScaleFactor" VALUE="1">
 </param><param NAME="Counter00006.StatisticStatus" VALUE="0">
 </param><param NAME="Selected" VALUE="\\SERVERNAME\Memory\Pages/sec">
</param></object>
</body>
</html>

Running a Windows NT Domain / Active Directory Audit

Getting an audit of your IT environment is incredibly useful. When you consider an audit from a security perspective – in the Windows NT domain or Active Directory model – there are a few items of significant importance: domains, users, groups, computers, and services.

The first step in conducting an audit is discovery – find out what’s out there. Fortunately, we have a great scripting tool for this: ADSI (Active Directory Services Interface). ADSI can pull the information for us, but to utilize it, we need to store it somewhere – such as in a SQL database.

To save you the trouble of figuring this out, below is a (rather long) script which uses ADSI to poll your network and store data into text files. To run it successfully, you must have at least query access to your entire directory. (The script has been tested on an NT 4.0 domain and on an Active Directory site.) The script queries each domain, obtaining all users, groups (including group memberships), and computers; and for each computer, obtains all local users, groups (and group memberships), and services. The output is saved into pipe-delimited text files for easy import into a database.

The script, which I save as netquery.vbs, has the following syntax:

cscript.exe netquery.vbs [nodomainusers] [nodomaingroups] [nocomputers] [nolocalusers] [nolocalgroups] [noservices]

nodomainusers    Suppresses querying of domain users and groups
nodomaingroups   Suppresses querying of domain groups
nocomputers      Suppresses querying of computers, local users and groups, and services
nolocalusers     Suppresses querying of local users and groups
nolocalgroups    Suppresses querying of local groups
noservices       Suppresses querying of services

The script generates text files in the current directory. Note that existing files will be overwritten! Each text file has a header as its first row. Import each text file into a database table with the exact same name. References between tables is logical if you look at the column names. Each object has an ADSPath, which is unique. Objects may reference an ADSOwner, which is the object’s parent (such as the domain or computer for which a user or group belongs, or the computer which a service is installed on). One special file exists – the groupmembers file. This has only two fields – ADSOwner and ADSMember – which are used to correlate the group (ADSOwner) with its many members (ADSMember).

Play around with it and it’ll make sense. If your network is huge, this will take a long time to run! You can tell things are working if data is being added to the output files.

And now, with no further delays, is the master script: netquery.vbs!

Option Explicit

On Error Resume Next

Const ForWriting = 2

'ARGUMENTS
Dim blnDomainUsers, blnDomainGroups, blnComputers, blnLocalUsers, blnLocalGroups, blnServices

blnDomainUsers = True
blnDomainGroups = True
blnComputers = True
blnLocalUsers = True
blnLocalGroups = True
blnServices = True
For Each item In WScript.Arguments
	Select Case LCase(item)
		Case "nodomainusers" 
			blnDomainUsers = False
			blnDomainGroups = False
		Case "nodomaingroups"
			blnDomainGroups = False
		Case "nocomputers"
			blnComputers = False
			blnLocalUsers = False
			blnLocalGroups = False
			blnServices = False
		Case "nolocalusers"
			blnLocalUsers = False
			blnLocalGroups = False
		Case "nolocalgroups"
			blnLocalGroups = False
		Case "noservices"
			blnServices = False
	End Select
Next

'CREATE FILESYSTEMOBJECT
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")

Dim objDomainsFile, objUsersFile, objGroupsFile, objGroupMembersFile, objComputersFile, objServicesFile
Set objDomainsFile = objFSO.OpenTextFile("domains.txt", ForWriting, True)
Set objUsersFile = objFSO.OpenTextFile("users.txt", ForWriting, True)
Set objGroupsFile = objFSO.OpenTextFile("groups.txt", ForWriting, True)
Set objGroupMembersFile = objFSO.OpenTextFile("groupmembers.txt", ForWriting, True)
Set objComputersFile = objFSO.OpenTextFile("computers.txt", ForWriting, True)
Set objServicesFile = objFSO.OpenTextFile("services.txt", ForWriting, True)

objDomainsFile.WriteLine "adspath|name"
objUsersFile.WriteLine "adspath|adsowner|name|fullname|description|passwordage|lastlogin|lastlogoff|raspermissions|accountdisabled"
objGroupsFile.WriteLine "adspath|adsowner|name"
objGroupMembersFile.WriteLine "adsowner|adsmember"
objComputersFile.WriteLine "adspath|adsowner|name|passwordage|owner|division|operatingsystem|osversion|processor|processorcount"
objServicesFile.WriteLine "adspath|adsowner|name|displayname|account"

Dim objDomains, objDomain, objUsers, objUser, objGroups, objGroup
Dim objComputers, objComputer, objComputerAccount, objServices, objService
Dim s1, s2, s3, s4, s5, s6, s7, obj, cls, op, item

Set objDomains = GetObject("WinNT:")

For Each objDomain in objDomains
	objDomainsFile.Write objDomain.AdsPath
	objDomainsFile.Write "|"
	objDomainsFile.Write objDomain.Name
	objDomainsFile.WriteLine
	
	'DOMAIN USERS
	If blnDomainUsers Then
		Set objUsers = Nothing
		Set objUser = Nothing
		Set objUsers = GetObject(objDomain.AdsPath)
		objUsers.Filter = Array("User")

		For Each objUser in objUsers
			objUsersFile.Write objUser.AdsPath
			objUsersFile.Write "|"
			objUsersFile.Write objDomain.AdsPath
			objUsersFile.Write "|"
			objUsersFile.Write objUser.Name
			objUsersFile.Write "|"
			objUsersFile.Write objUser.FullName
			objUsersFile.Write "|"
			objUsersFile.Write objUser.Description
			objUsersFile.Write "|"
			objUsersFile.Write objUser.PasswordAge
			objUsersFile.Write "|"
			objUsersFile.Write objUser.LastLogin
			objUsersFile.Write "|"
			objUsersFile.Write objUser.LastLogoff
			objUsersFile.Write "|"
			objUsersFile.Write objUser.RasPermissions
			objUsersFile.Write "|"
			If objUser.UserFlags And &H0002 Then 
				objUsersFile.Write "1"
			Else 
				objUsersFile.Write "0"
			End If
			objUsersFile.WriteLine
		Next
	End If
	
	'DOMAIN GROUPS
	If blnDomainGroups Then
		Set objGroups = Nothing
		Set objGroup = Nothing
		Set objGroups = GetObject(objDomain.AdsPath)
		objGroups.Filter = Array("Group")

		For Each objGroup in objGroups
			objGroupsFile.Write objGroup.AdsPath 
			objGroupsFile.Write "|"
			objGroupsFile.Write objDomain.AdsPath
			objGroupsFile.Write "|"
			objGroupsFile.Write objGroup.Name
			objGroupsFile.WriteLine

			For Each objUser In objGroup.Members
				If Right(objUser.Name, 1) <> "$" Then
					objGroupMembersFile.Write objGroup.AdsPath
					objGroupMembersFile.Write "|"
					objGroupMembersFile.Write objUser.AdsPath
					objGroupMembersFile.WriteLine
				End If
			Next
		Next
	End If
	
	'COMPUTERS
	If blnComputers Then
		Set objComputers = Nothing
		Set objComputer = Nothing
		Set objComputers = GetObject(objDomain.AdsPath)
		objComputers.Filter = Array("Computer")

		For Each objComputer in objComputers
			Set objComputerAccount = GetObject(objComputer.AdsPath & "$,user")

			objComputersFile.Write objComputer.AdsPath
			objComputersFile.Write "|"
			objComputersFile.Write objDomain.AdsPath
			objComputersFile.Write "|"
			objComputersFile.Write objComputer.Name 
			objComputersFile.Write "|" 
			objComputersFile.Write objComputerAccount.PasswordAge 
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.Owner
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.Division
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.OperatingSystem
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.OperatingSystemVersion
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.Processor
			objComputersFile.Write "|" 
			objComputersFile.Write objComputer.ProcessorCount
			objComputersFile.WriteLine

			'COMPUTER USERS
			If blnLocalUsers Then
				Set objUsers = Nothing
				Set objUser = Nothing
				Set objUsers = GetObject(objComputer.AdsPath & ",computer")
				objUsers.Filter = Array("User")

				For Each objUser in objUsers
					objUsersFile.Write objUser.AdsPath
					objUsersFile.Write "|"
					objUsersFile.Write objComputer.AdsPath
					objUsersFile.Write "|"
					objUsersFile.Write objUser.Name
					objUsersFile.Write "|"
					objUsersFile.Write objUser.FullName
					objUsersFile.Write "|"
					objUsersFile.Write objUser.Description
					objUsersFile.Write "|"
					objUsersFile.Write objUser.PasswordAge
					objUsersFile.Write "|"
					objUsersFile.Write objUser.LastLogin
					objUsersFile.Write "|"
					objUsersFile.Write objUser.LastLogoff
					objUsersFile.Write "|"
					objUsersFile.Write objUser.RasPermissions
					objUsersFile.Write "|"
					If objUser.UserFlags And &H0002 Then 
						objUsersFile.Write "1"
					Else 
						objUsersFile.Write "0"
					End If
					objUsersFile.WriteLine
				Next
			End If
			
			'COMPUTER GROUPS
			If blnLocalGroups Then
				Set objGroups = Nothing
				Set objGroup = Nothing
				Set objGroups = GetObject(objComputer.AdsPath & ",computer")
				objGroups.Filter = Array("Group")

				For Each objGroup in objGroups
					objGroupsFile.Write objGroup.AdsPath 
					objGroupsFile.Write "|"
					objGroupsFile.Write objComputer.AdsPath
					objGroupsFile.Write "|"
					objGroupsFile.Write objGroup.Name
					objGroupsFile.WriteLine

					For Each objUser In objGroup.Members
						If Right(objUser.Name, 1) <> "$" Then
							objGroupMembersFile.Write objGroup.AdsPath
							objGroupMembersFile.Write "|"
							objGroupMembersFile.Write objUser.AdsPath
							objGroupMembersFile.WriteLine
						End If
					Next
				Next
			End If

			'SERVICES
			If blnServices Then
				Set objServices = Nothing
				Set objService = Nothing
				Set objServices = GetObject(objComputer.AdsPath & ",computer")
				objServices.Filter = Array("Services")

				For Each objService In objServices
					objServicesFile.Write objService.AdsPath 
					objServicesFile.Write "|"
					objServicesFile.Write objComputer.AdsPath
					objServicesFile.Write "|"
					objServicesFile.Write objService.Name
					objServicesFile.Write "|"
					objServicesFile.Write objService.DisplayName
					objServicesFile.Write "|"
					objServicesFile.Write objService.ServiceAccountName
					objServicesFile.WriteLine
				Next
			End If
		Next
	End If
	
Next

objServicesFile.Close
objComputersFile.Close
objGroupMembersFile.Close
objGroupsFile.Close
objUsersFile.Close
objDomainsFile.Close
Set objServicesFile = Nothing
Set objComputersFile = Nothing
Set objGroupMembersFile = Nothing
Set objGroupsFile = Nothing
Set objUsersFile = Nothing
Set objDomainsFile = Nothing