Click here to Skip to main content
15,887,683 members
Articles / Programming Languages / C#
Article

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

Rate me:
Please Sign up or sign in to vote.
4.50/5 (8 votes)
24 Oct 2007CPOL3 min read 94.2K   3.7K   63   13
A command-line tool that scans computers in your network using either a remote registry connection or the Windows Management Instrumentation (WMI).

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:

C#
// 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:

C#
// 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.

C#
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:

C#
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)


Written By
Software Developer (Senior)
Denmark Denmark
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralDetails on Localhost only Pin
D3s78-Nov-07 3:16
D3s78-Nov-07 3:16 
Generalrun NetInventory.exe Pin
JonnyTwoShoes1-Nov-07 1:28
JonnyTwoShoes1-Nov-07 1:28 
GeneralRe: run NetInventory.exe Pin
Henrik Thomsen1-Nov-07 10:01
Henrik Thomsen1-Nov-07 10:01 
GeneralRe: run NetInventory.exe Pin
JonnyTwoShoes1-Nov-07 20:41
JonnyTwoShoes1-Nov-07 20:41 
QuestionLarge network Pin
Nick__J25-Oct-07 1:54
Nick__J25-Oct-07 1:54 
I have tried this in a large network (3000+), it took around 20 minutes to complete.
Problem is, that I get an access denied on most machines because I don't have access right.

So I guess you have to be domain admin to let this work.
How can I run this application under another user?
Maybe also extra parameters? -u user -p password

Grtz,
Nick
AnswerRe: Large network Pin
Kristof Verbiest25-Oct-07 2:08
Kristof Verbiest25-Oct-07 2:08 
GeneralRe: Large network Pin
Nick__J25-Oct-07 2:15
Nick__J25-Oct-07 2:15 
GeneralRe: Large network Pin
Cool Cassis25-Oct-07 3:42
Cool Cassis25-Oct-07 3:42 
GeneralRe: Large network Pin
Nick__J25-Oct-07 3:47
Nick__J25-Oct-07 3:47 
AnswerRe: Large network Pin
Henrik Thomsen25-Oct-07 21:13
Henrik Thomsen25-Oct-07 21:13 
AnswerRe: Large network Pin
ESTAN25-Oct-07 21:46
ESTAN25-Oct-07 21:46 
GeneralStatistics Pin
ESTAN24-Oct-07 23:32
ESTAN24-Oct-07 23:32 
GeneralRe: Statistics Pin
Henrik Thomsen25-Oct-07 21:36
Henrik Thomsen25-Oct-07 21:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.