5,702,921 members and growing! (14,810 online)
Email Password   helpLost your password?
General Programming » Internet / Network » Network     Intermediate License: The Code Project Open License (CPOL)

How to Scan Computers in Your Network Using the Registry or WMI

By Henrik Thomsen

A command-line tool that scans computers in your network using either a remote registry connection or the Windows Management Instrumentation (WMI).
C# 2.0, C#, Windows, .NET, .NET 2.0VS2005, Visual Studio, Dev

Posted: 24 Oct 2007
Updated: 24 Oct 2007
Views: 15,984
Bookmarked: 32 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
5 votes for this Article.
Popularity: 3.05 Rating: 4.36 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 20.0%
3
1 vote, 20.0%
4
3 votes, 60.0%
5

Introduction

This is an inventory application that scans computers in your network. You can list computers of particular types (i.e., SQL servers), and you can extract computer information from two different sources: the registry or Windows Management Instrumentation (WMI).

Run netinventory.exe -? to see how it is used. Here is an example:

Screenshot - NetInventory.jpg

The command above will produce a file, NetInventory.xml - 3.3 KB, containing the operating system name and the service pack for all SQL servers in the network.

Background

I built the tool to solve recurring problems such as:

  • List SQL servers in the network (you can use Server Management Objects (SMO), but that is painfully slow)
  • List primary domain controllers
  • List operating systems for computers in the network
  • List computer types and serial number
  • List installed software for computers in the network

In order to get this kind of inventory information, I needed MS System Center Configuration Manager, or some other inventory system or asset management system. This tool requires no installation, and does the job (almost) as well.

Using the code

There are five basic problems to solve in this application:

  • List computers in the network
  • Control the timeout of the network connection to a computer that doesn't respond
  • Get registry information from a remote computer
  • Get WMI information from a remote computer
  • Manage command line switches

Listing computers in the network is described in another article. The class NetWorkBrowser, written by Sacha barber, encapsulates the use of the Win32 API function Netapi32.dll: NetServerEnum. I used Sacha's class as is, except for adding the enumeration ServerType. To list SQL servers in your network, simply call the function getNetworkComputers() and specify the server type:

// List SQL servers in your network

NetworkBrowser nb = new NetworkBrowser();
ArrayList arr = nb.getNetworkComputers(ServerType.SV_TYPE_SQLSERVER);
Console.WriteLine("{0} : {1}", serverType.ToString(), arr.Count);
foreach (string name in arr)
{
  Console.WriteLine(name);
}
Console.WriteLine();

One of the issues that need to be addressed when connecting to computers in your network is dealing with computers that don't respond. When connecting to the registry or WMI on a remote computer, you don't have control over the timeout. If a number of computers don't respond and you have to wait, say 30 seconds for each connection timeout, scanning the network will take forever. The class TimeoutOperation is designed to run operations impatiently. To use the class, inherit it and override DoWork() with the operation logic. On timeout, isCancelled will be set to true and the main thread will resume execution:

// Implement an impatient operation

class WaitAMinute : TimeoutOperation
{
  public int counter = 0;
  public WaitAMinute(int timeoutMiliseconds) : base(timeoutMiliseconds)
  {
  }
  protected override void DoWork()
  {
    for (counter = 0; counter < 60; counter++)
    {
      if (isCancelled)
        break;
      Thread.Sleep(1000);
    }
  }
}

// Run the operation with timeout

WaitAMinute w = new WaitAMinute(3000);
w.Start();
Console.WriteLine("{0}", w.counter); // 3

Getting registry information from a remote computer is encapsulated in the class RegistryReader. To use the class, call the static method GetRegistryKey(). In the example below, the method is used to get all the values from the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion on the machine with the hostname MYPC. The timeout is set to 500 milliseconds. If the machine does not respond within the timeout period, an ApplicationException will be thrown.

ArrayList arr = new ArrayList();
try
{
  RegistryReader.GetRegistryKey("MYPC",
    @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion", 
    null, 500, ref arr);
}
catch (Exception exc)
{
  Console.WriteLine(exc.Message); // Timed out

}
foreach (IDictionary dict in arr)
{
  foreach (DictionaryEntry de in dict)
  {
    Console.WriteLine("{0} = {1}", de.Key, de.Value);
    // Registry.ProgramFilesDir = C:\Program Files

    // Registry.CommonFilesDir = C:\Program Files\Common Files

    // ...

  }
}

Getting WMI information from a remote computer is encapsulated in the class WMIQuery. To use the class, call the static method Execute(). You must specify a valid query using the WQL syntax, a valid WMI namespace, hostname of the remote computer, and a connection timeout. The timeout works the same way as in the class RegistryReader as described above. This example will get the BIOS name and the serial number from the machine with the hostname MYPC:

ArrayList arr = null;
try
{
  arr = WMIQuery.Execute("select Caption, SerialNumber from Win32_BIOS", 
    @"root\CIMV2", "MYPC", 500);
}
catch (Exception exc)
{
  Console.WriteLine(exc.Message); // Timed out

}
foreach (IDictionary dict in arr)
{
  foreach (DictionaryEntry de in dict)
  {
    Console.WriteLine("{0} = {1}", de.Key, de.Value);
    // Win32_BIOS.Caption = KBC Version 43.1C

    // Win32_BIOS.SerialNumber = CNU5510SRH  

  }
}

To manage command line switches, I used the classes Parser and CommandLineSwitchAttribute written by Ray Hayes. These are described in another article. I made one modification to the class Parser (actually to SwitchRecord.BuildPattern(), to be precise) that allowed enumerated values as integers, because I wanted to be able to combine ServerType values.

Points of interest

TimeoutOperation may not scale well up to thousands of computers since the number of running threads waiting to connect to remote computers could be growing depending on your network configuration and the specified timeout value. I recommend setting the timeout to 0 when scanning large networks, letting the program run overnight, setting the timeout to the default value of 500 milliseconds when scanning a limited number of workstations, and getting the result set immediately.

History

  • Version 1.0.0.0 - November 2007.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Henrik Thomsen



Occupation: Software Developer (Senior)
Location: Denmark Denmark

Other popular Internet / Network articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 13 of 13 (Total in Forum: 13) (Refresh)FirstPrevNext
GeneralDetails on Localhost onlymemberD3s74:16 8 Nov '07  
Generalrun NetInventory.exememberJonnyTwoShoes2:28 1 Nov '07  
GeneralRe: run NetInventory.exememberHenrik Thomsen11:01 1 Nov '07  
GeneralRe: run NetInventory.exememberJonnyTwoShoes21:41 1 Nov '07  
QuestionLarge networkmembernick_journals2:54 25 Oct '07  
AnswerRe: Large networkmemberKristof Verbiest3:08 25 Oct '07  
GeneralRe: Large networkmembernick_journals3:15 25 Oct '07  
GeneralRe: Large networkmemberCool Cassis4:42 25 Oct '07  
GeneralRe: Large networkmembernick_journals4:47 25 Oct '07  
AnswerRe: Large networkmemberHenrik Thomsen22:13 25 Oct '07  
AnswerRe: Large networkmemberESTANNY22:46 25 Oct '07  
GeneralStatisticsmemberESTANNY0:32 25 Oct '07  
GeneralRe: StatisticsmemberHenrik Thomsen22:36 25 Oct '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Oct 2007
Editor: Smitha Vijayan
Copyright 2007 by Henrik Thomsen
Everything else Copyright © CodeProject, 1999-2008
Web13 | Advertise on the Code Project