tags:

views:

269

answers:

5

What are some ways that I can query the local machine's specifications (a range of things from CPU specs, OS version, graphics card specs and drivers, etc.) through a programmatic interface? We're writing a simple app in C# to test compatibility of our main app and want to have it dump out some system metrics, but I can't seem to find where to even start, what interfaces to use, libraries, anything.

I've tried all kinds of searches, but can only find programs, and GUI ones at that, which require a user to interact with, or have to install.

Alternatively, a small, command-line program would work just as well, as long as we'd be permitted to distribute it with the test app.

I have found one program that gets some of the specs I'd want, PsInfo. However, it seems to require each user to agree to some license when it is first run, even though it's a command line app. Plus, it only deals with OS/CPU info, and I will need more than that.

Also: forgot to mention explicitly, but this indeed is only going to be necessary for Windows machines. You folks are quick!

Edit: This WMI does look like what I need, thanks! Quite a can of worms though, so I've got to dive in. It mentions that for some things the user has to have administrator privileges; this probably won't be a big problem, but it might limit it a little.

+3  A: 

For this type of information WMI is your friend. Fortunately dealing with WMI in .NET is much easier than in the unmanaged world. There are quite a lot of articles out there to get started with, like this one, or this one to retrieve processor information.

You will end up writing SQL-like queries against objects in the WMI namespace to retrieve the information you want.

Rob Walker
+5  A: 

Maybe look into using Windows Management Instrumentation (WMI), assuming it's a Windows machine your planning to query. Take a look at the WMI Code Creator from Microsoft. It can easily get you going with code samples for in a few languages.

WMI works excellent all the way back to the Windows 2000 era, but can also work in Win98 machines too with some help.

As long as you have, or can provide, administrator credentials for the machine you're trying to query, WMI is definitely the way to go.

Matt Hanson
A: 

For the odd case that you would be developing for linux, you could find awesome stuff inside the /proc pseudofilesystem.

Henrik Paul
+1  A: 

I might as well post the basic code I used to get everything I needed, using WMI as was suggested here.

Gotta include a reference to System.Management in the c# project. Then, the source itself is probably terribly formed c#, but I've never really written in it before and it's for an internal tool, so that's kind of besides the point. I've simplified it a bit so it's only really dealing with outputting machine specs (the tool does other things besides that). Each call to LogClass() dumps out all of its properties. For more classes to dump out, just check out the MSDN section on WMI Classes.

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

namespace SyTest
{
  class Program
  {
    static StreamWriter specStream;

    static void Main(string[] args)
    {
      FileStream specFile =
          new FileStream("machine-specs.txt",FileMode.Create,FileAccess.Write);
      specStream = new StreamWriter(specFile);

      LogClass("Win32_DesktopMonitor");
      LogClass("Win32_VideoController");
      LogClass("Win32_Processor");
      // etc

      specStream.Close();
      specFile.Close();
    }

    static void LogClass(string strTable)
    {
      if (strTable.Length <= 0) return;
      specStream.Write("--- " + strTable + " ---\r\n\r\n");
      WqlObjectQuery wqlQuery =
          new WqlObjectQuery("SELECT * FROM " + strTable);
      ManagementObjectSearcher searcher =
          new ManagementObjectSearcher(wqlQuery);
      try
      {
        if (searcher.Get().Count <= 0)
        {
          specStream.Write("Class has no instances\r\n\r\n");
        }
        foreach (ManagementObject obj in searcher.Get())
        {
          specStream.Write("* " + obj.ToString() + "\r\n");

          if (obj.Properties.Count <= 0)
          {
            specStream.Write("Class instance has no properties\r\n");
            continue;
          }

          foreach (System.Management.PropertyData prop in obj.Properties)
          {
            LogAttr(obj, prop.Name);
          }

          specStream.Write("\r\n");
        }
      }
      catch { specStream.Write("Class does not exist\r\n\r\n"); }
    }
    static void LogAttr(ManagementObject obj, string str)
    {
      if (str.Length <= 0) return;
      string strValue = "";
      try
      {
        strValue = obj[str].ToString();
        try
        {
          string[] pstrTmp = ((string[])obj[str]);
          if (pstrTmp.Length > 0) strValue = String.Join(", ", pstrTmp);
        }
        catch { } // Problem casting, fall back on original assignment
      }
      catch { strValue = "[UNDEFINED]"; }
      specStream.Write(str + ": " + strValue + "\r\n");
    }
  }
}
Doug Kavendek
A: 

If you decide to go with WMI, you might want to check out the WMI Code Creator from Microsoft. It makes dealing with WMI pretty easy.

Millhouse