Programming : C#

I have been itching to program in C# for a long time now.. finally got a chance to try it out due to requirement at work. Here’s a small snippet of code that does a bunch of things
1) Opens a directory and get a list of files in it
2) Parses the file name into multiple variables
3) Connects to Active Directory and gets properties for a user
4) Creates an error file with list of errors.
5) Creat an output file in csv format.

For the programming gurus out there, this should be pretty easy :).. I am sure that there are tons of errors in the way, I wrote the code, but this is a beginning :).


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.DirectoryServices;

namespace sortAssetData
{
class Program
{
static void Main(string[] args)
{
// Create a Log file and output file

System.IO.TextWriter infoLog = new System.IO.StreamWriter(“sortAssetDataLog.txt”);
System.IO.TextWriter outputLog = new System.IO.StreamWriter(“finalAssetData.csv”);

// Write the column headers into the output file
outputLog.WriteLine(“Last_Name, First_Name, Display_Name, Batt_Check_Version, Model_Type, Model_Number, Serial_Number, Batt_Manufacturer, Batt_Model, Batt_Serial_Number, Affected”);

// Define the folder where the data files are sitting
string fixDirectoy = “P:\\BatteryCheck_Results”;

// Change working directory to the folder with all the files
System.IO.Directory.SetCurrentDirectory(fixDirectoy);

// Create a directory object to get list of asset files
System.IO.DirectoryInfo tempDirObject = new System.IO.DirectoryInfo(fixDirectoy);

// Get list of *.csv files in the asset folder
System.IO.FileInfo[] listOfFiles = tempDirObject.GetFiles(“*.csv”);

// Process each file in the directory
foreach (System.IO.FileInfo tempFile in listOfFiles)
{
// Display the current file that is being processed
System.Console.WriteLine(“Processing : {0}”, tempFile.Name);
infoLog.WriteLine(“Processing : {0}”, tempFile.Name);
infoLog.Flush();

// Split the file name into Domain, Hostname, Username
string tempData = tempFile.Name;
// Removing the .csv at the end of the file name
tempData = tempData.Replace(“.csv”, “”);
string[] sortData = tempData.Split(new Char[] { ‘_’ });

// If file name doesn’t contain 3 records (Domain, ComputerName and UserName), we ignore it
if (sortData.Length != 3)
{
infoLog.WriteLine(“ERROR : Bad file format : {0}”, tempFile.Name);
infoLog.Flush();
continue;
}

// Display the userdata we got from the file name
System.Console.WriteLine(“\nDomain :\t {0}”, sortData[0]);
System.Console.WriteLine(“Computer Name :\t {0}”, sortData[1]);
System.Console.WriteLine(“User Name :\t {0}\n”, sortData[2]);

// Get the users full name from ActiveDirectory
System.DirectoryServices.DirectorySearcher searchUser = new System.DirectoryServices.DirectorySearcher();
searchUser.Filter = String.Format(“(SAMAccountName={0})”, sortData[2]);
searchUser.PropertiesToLoad.Add(“cn”);
searchUser.PropertiesToLoad.Add(“givenname”);
searchUser.PropertiesToLoad.Add(“sn”);
System.DirectoryServices.SearchResult resultFromAD = searchUser.FindOne();

// If the username doesn’t have a AD account, note and skip to the next file
if (resultFromAD == null)
{
System.Console.WriteLine(“ERROR : Bad User name : {0}”, sortData[2]);
infoLog.WriteLine(“ERROR : Bad User name : {0}”, sortData[2]);
infoLog.Flush();
continue;
}
else
{
//Parse the file and write data to the log file and also to the screen
System.IO.StreamReader tempSoureFile = new System.IO.StreamReader(tempFile.Name);
// Read the first line in the file and ignore it
string tempAssetData = tempSoureFile.ReadLine();
// Read the second line and store it to write to outputfile
tempAssetData = tempSoureFile.ReadLine();

string tempUserFirstName = resultFromAD.Properties[“sn”][0].ToString();
string tempUserLastName = resultFromAD.Properties[“givenname”][0].ToString();
string tempUserDisplayName = resultFromAD.Properties[“cn”][0].ToString();
outputLog.WriteLine(“{0},{1},{2},{3}”, tempUserFirstName, tempUserLastName, tempUserDisplayName, tempAssetData);
outputLog.Flush();
System.Console.WriteLine(“User First Name:\t {0}”, tempUserFirstName);
System.Console.WriteLine(“User Last Name:\t\t {0}”, tempUserLastName);
System.Console.WriteLine(“Display Name:\t\t {0}”, tempUserDisplayName);
}
}
System.Console.ReadKey();
infoLog.Close();
outputLog.Close();
}
}
}


Microsoft Excel : How to repair "Opening blank file when double clicking on an excel file"

Ran into an interesting problem with troubleshooting an Excel issue. Double clicking on an excel file opened a blank file on the affected machine. I thought it might be something related to the associations and checked them from “Tools -> Folder Options -> File Types” in the Windows Explorer menu. Everything was in order there. I then tried a reinstall of Office (note : would not do this in the future without additional troubleshooting 🙂 ). That didn’t help either. Finally, I gave up and did a Google search, which returned this URL

http://groups.google.com/group/microsoft.public.office.misc/browse_thread/thread/aa3da7b29cd55a93/3347ca4c2ea6673a%233347ca4c2ea6673a

Did the following according to the post and everything returned to default settings

1) Run Excel with “/safe” option.
2) Click on “help -> Detect and Repair” from the Excel menu
3) Close Excel for repair

Thx Google.

RDP over SSH tunnel

Necessity is the mother of invention.. Or so goes the old saying. I was on-call this weekend for off hour IT support. We usually provide our on-call engineers a wireless broadband card in case they need to get connected to the corporate network to troubleshoot/fix issues. This week, I was not able to get the wireless card, since we had to loan it to an exec. The only method to get onto the Internet was using my new 8700 blackberry. We have the EDGE service from T-mobile, which is not as fast as the Verizon BroadbandAccess.. We typically get ~128kbps with the EDGE connection and is enough to get our work done.. The problem with using the BB as a modem is that T-mobile blocks PPTP/IPSec traffic with this plan. Not to be outdone, I came up with a way to use the BB to connect to our internal network. Most of our support work is done on Windows, so we need to remote console into one of our servers to provide support. I did the following to get this working using our corporate SSH gateway to tunnel RDP traffic.

1) Download Putty (SSH Client).
2) Create a new session on Putty to the SSH gateway. In the “Tunnels” option, add the following options

Note: Replace the REMOTE_HOST with the IP address or hostname of your Windows server.
3) Click on ADD
4) Click on Open and connect to the SSH server with your credentials
5) Log into the remote serve by running the following command “mstsc /v:127.0.01:3390
Note: You can change the local port to any number you want. Make sure not to use 3389 as the local port, since it is already used by the remote desktop service on your windows workstation.

HOW TO : Update non-domain members using WSUS

WSUS is a free tool from Microsoft that enables administrators to easily manage and deploy updates across the organization. WSUS is mainly used is enterprises with AD deployments, where the WSUS settings can be easily propagated to the workstations using group policy. So how does one keep their workstation/server updated without being part of the AD domain? You can do it by

1) Edit the local computer policy of the workstation/server by running “gpedit.msc
2) Drill down to Computer Configuration -> Administrative Templates -> Windows Components -> Windows Update and change the settings for “Specify intranet Microsoft update service location“.
3) Restart the workstation.

Command Line and Scripting in all their glory!!

Challenge: You are asked to update ~500 records on your DNS servers running Windows 2003 SP1.

Solution : Spend hours and hours updating the entries using the pretty MMC based GUI
or
use some creative scripting to do the work for you. Here is the recipe

1) Download the Windows Support Tools for SP1 from here. The support tools contain a useful utility called “dnscmd”. The tool allows one to add/update/delete entries for Windows DNS servers through a command line interface. DnsCmd /help returns the following

Usage: DnsCmd []:
IP address or host name — remote or local DNS server
. — DNS server on local machine
:
/Info — Get server information
/Config — Reset server or zone configuration
/EnumZones — Enumerate zones
/Statistics — Query/clear server statistics data
/ClearCache — Clear DNS server cache
/WriteBackFiles — Write back all zone or root-hint datafile(s)
/StartScavenging — Initiates server scavenging
/ResetListenAddresses — Set server IP address(es) to serve DNS requests
/ResetForwarders — Set DNS servers to forward recursive queries to
/ZoneInfo — View zone information
/ZoneAdd — Create a new zone on the DNS server
/ZoneDelete — Delete a zone from DNS server or DS
/ZonePause — Pause a zone
/ZoneResume — Resume a zone
/ZoneReload — Reload zone from its database (file or DS)
/ZoneWriteBack — Write back zone to file
/ZoneRefresh — Force refresh of secondary zone from master
/ZoneUpdateFromDs — Update a DS integrated zone by data from DS
/ZonePrint — Display all records in the zone
/ZoneResetType — Change zone type
/ZoneResetSecondaries — Reset secondary\notify information for a zone
/ZoneResetScavengeServers — Reset scavenging servers for a zone
/ZoneResetMasters — Reset secondary zone’s master servers
/ZoneExport — Export a zone to file
/ZoneChangeDirectoryPartition — Move a zone to another directory partition
/EnumRecords — Enumerate records at a name
/RecordAdd — Create a record in zone or RootHints
/RecordDelete — Delete a record from zone, RootHints or cache
/NodeDelete — Delete all records at a name
/AgeAllRecords — Force aging on node(s) in zone
/EnumDirectoryPartitions — Enumerate directory partitions
/DirectoryPartitionInfo — Get info on a directory partition
/CreateDirectoryPartition — Create a directory partition
/DeleteDirectoryPartition — Delete a directory partition
/EnlistDirectoryPartition — Add DNS server to partition replication scope
/UnenlistDirectoryPartition — Remove DNS server from replication scope
/CreateBuiltinDirectoryPartitions — Create built-in partitions

As you can see, there is ton of stuff you can do with this utility. I am mainly interested in the /RecordAdd function for this example.

2) Write a small perl script to massage your raw data into the form you want. In this case, I was given the hostname and the IP address in an excel spreadsheet. I exported the spreadsheet to a command delimited file and the following perl script finished the job for me

#!/usr/bin/perl -w
# use strict;
my (@File, @Column, @HostID, @NetworkID, $Line);
my $infile = ‘NetworkCore.csv’;
my $outfile = ‘NetworkCore_Processed.txt’;

open(READ,”$infile”)
or die “Couldn’t open $infile for reading: $!\n”;
@File = ;
close READ;

open(OUTPUT,”>$outfile”)
or die(“Unable to open my $outfile: $!”);

foreach $Line(@File)
{
chomp($Line);
@Column = split(/,/,$Line);
@NetworkID = split(/\./, $Column[0]);
@HostID = split(/\./, $Column[1]);
print OUTPUT “dnscmd DNS_SERVER /RecordAdd DOMAIN_TO_ADD $HostID[0] A $Column[0]\n”;
print OUTPUT “dnscmd DNS_SERVER /RecordAdd xxx.xxx.in-addr.arpa $NetworkID[3].$NetworkID[2] PTR $Column[1]\n”;
}
close OUTPUT
;

Note : The DNS_SERVER, DOMAIN_TO_ADD and xxx.xxx.in-addr.arpa need to be replaced with your own values

3) Open a command prompt on the DNS server and copy and paste the contents of the file that the perl file spits out.. Did, I say that I love technology?? :)..

IP Address confusion and DHCP

Ran into a good case of Network troubleshooting today. We use the private 192.168.0.0/16 address range at work. All of a sudden, we had users calling us from a particular floor stating that they cannot access network resources. Here’s how the team solved the issue

1) Physical connectivity – Is the cable plugged into the workstation? Is there a green light on the NIC?
2) DNS Lookup – Open a command prompt and do a look up on a server in the network. In this case, one of our file servers. Users say that they are getting a “server inaccessible” error. Hmm.. Alright, so we have physical connectivity, but don’t have DNS resolution. Since the rest of the user population didn’t have any DNS resolution issues, the team dug deeper
3) IP Address Details – Open a command prompt and type in “ipconfig”. This showed that the affected users were getting a “172.16.0.x” address. This range does not exist in our user network segment. So looks like we have users getting an unqualified network. Since all users are configured to get their IP addresses through DHCP, the culprit might be DHCP.
4) DHCP Server : The Issue – Open a command prompt and type in “ipconfig /all”. This showed the following

Aha.. looks like there is a rouge DHCP server in our network. The team checked the LAN room on the floor and found the culprit server. Looks like the server was installed in it’s default state where it acted as a DHCP server.

Lesson learnt : DHCP broadcasts sent by the client are addressed by servers in the same broadcast (Layer 2) domain before being routed to other DHCP servers (IP Helper Addresses).

Windows : Explore running processes

One of the Windows server at work started running high on CPU for the last few days.. On checking the task manager, I could only see that “services.exe” was using ~30% of CPU. services.exe is part of the core Windows operating system and manages the starting and stopping of the services. To further investigate, what process was using the CPU, I lauched Sysinternals Process Explorer and voila!!, here’s what I see

Looks like the CPU utilization of the services that the services.exe starts show up under it. There are a bunch of other cool utilities at SysInternals that any Windows admin would find useful.

802.1x : RADIUS : IAS : Fiasco

We use 802.1x for our wireless security at work. The wireless controller uses Microsoft’s IAS as the RADIUS server. Recently during one of our maintenance windows, we installed a couple of critical patches and rebooted the IAS server. This was over the weekend and we didn’t check if wireless was working after the maintenance (one of the lessons learnt from his story :), put in automated monitoring so that you don’t have to worry about what services have come up or not after a maintenance window).

On Monday, our helpdesk gets swamped with calls of “wireless is not working”. We checked the controller and everything looked okay. Only error on the controller was that the RADIUS server was not responding. We checked the RADIUS server and the IAS service was running fine. But there were a ton of errors in the System event log with the following details

Access request for user XXXX\XXXXXX was discarded.
Fully-Qualified-User-Name = XXX.XXXX.NET/XXX.XXX/TECHNOLOGY/DEVELOPMENT/XXX XXXXXX
NAS-IP-Address = 192.168.128.10
NAS-Identifier = ACHIAS01IT
Called-Station-Identifier = 00-0B-85-06-0C-A0:wacker
Calling-Station-Identifier = 00-14-A4-28-4C-EE
Client-Friendly-Name = ACHIAS01IT
Client-IP-Address = 192.168.128.10
NAS-Port-Type = Wireless – IEEE 802.11
NAS-Port = 1
Proxy-Policy-Name = Use Windows authentication for all users
Authentication-Provider = Windows
Authentication-Server =
Reason-Code = 23
Reason = Unexpected error. Possible error in server or client configuration.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Unexpected error. Possible error in server or client configuration.“, now that is real informational :). We scratched our heads.. Thought it might be an issue with the controller (it was on an older firmware). Upgraded the firmware and rebooted the controller. Still no go. Same error. Finally frustrated, we opened up a case with MSFT. Even the eng. from MSFT was flabbergasted. The usual “Everything looks good, it should work!!”.

Finally we resolved the issue to an expired computer certificate for the IAS server. The certificate had expired a couple of weeks ago, but looks like the authentication was cached and when the server was rebooted, it caused the IAS service to error out. Renewing the cert caused the wireless clients to start authenticating immediately.

Am looking into what other services depend on a valid cert to work properly.