This article describes how to start Microsoft System Information programmatically from the application.
Introduction
Everyone has seen the "System Info ..." button in the About box of Microsoft applications. It can be found in Microsoft Office apps, Visual Studio .NET and others. When clicked, it starts the Microsoft System Information utility. System Information displays a comprehensive view of your hardware, system components, and software environment. On earlier versions of Windows, namely Microsoft Office installed it (thanks to Matt Philmon for noticing that). I have once found out how to get its path in case the utility is installed developing MDB to SQLServer database converter with VB 6.0 - the function retrieving its path and starting it is added automatically to all VB projects about box. Look at the code below, it reads the registry for the first path and if not found, checks the second one for MSInfo32.exe. I think that in the newer versions of MS Windows, the MSInfo32.exe is left for backward compatibility just to start real program located somewhere else. For example, in Windows 2000, System Information is Microsoft Management Console (MMC) snap-in MSInfo32.msc located in the "C:\Program Files\Common Files\Microsoft Shared\MSInfo\" and MSInfo32.exe only seems to launch it.
Source Code
MFC Source Code
#if ( _MFC_VER < 0x0700 && !defined _INC_SHLWAPI )
#include < Shlwapi.h >
#pragma comment( lib, "Shlwapi.lib" )
#endif
#include <atlbase.h>
#define IDS_REG_KEY_MSINFO_PATH1 _T(
"Software\\Microsoft\\Shared Tools\\MSInfo" )
#define IDS_REG_KEY_MSINFO_PATH2 _T(
"Software\\Microsoft\\Shared Tools Location" )
#define IDS_REG_VAL_MSINFO_PATH1 _T( "Path" )
#define IDS_REG_VAL_MSINFO_PATH2 _T( "MSInfo" )
#define IDS_MSINFO_EXE_NAME _T( "MSInfo32.exe" )
BOOL GetSysInfoPath( CString& strPath )
{
strPath.Empty();
LPTSTR pszPath = strPath.GetBuffer( MAX_PATH );
CRegKey reg;
DWORD dwSize = MAX_PATH;
LONG nRet = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH1,
KEY_READ );
if ( nRet == ERROR_SUCCESS )
{
#if ( _MFC_VER >= 0x0700 )
nRet = reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH1, pszPath,
&dwSize );
#else
nRet = reg.QueryValue(
pszPath, IDS_REG_VAL_MSINFO_PATH1, &dwSize );
#endif
reg.Close();
}
if ( nRet != ERROR_SUCCESS )
{
nRet = reg.Open(
HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH2, KEY_READ );
if ( nRet == ERROR_SUCCESS )
{
#if ( _MFC_VER >= 0x0700 )
reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH2, pszPath,
&dwSize );
#else
reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH2, &dwSize );
#endif
if ( nRet == ERROR_SUCCESS )
VERIFY( ::PathAppend( pszPath, IDS_MSINFO_EXE_NAME ) );
reg.Close();
}
}
strPath.ReleaseBuffer();
strPath.FreeExtra();
return ::PathFileExists( strPath );
}
C# Source Code
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;
public bool GetMsinfo32Path( ref string strPath )
{
strPath = string.Empty;
object objTmp = null;
RegistryKey regKey = Registry.LocalMachine;
if( regKey != null )
{
regKey = regKey.OpenSubKey(
"Software\\Microsoft\\Shared Tools\\MSInfo" );
if( regKey != null )
objTmp = regKey.GetValue( "Path" );
if( objTmp == null )
{
regKey = regKey.OpenSubKey(
"Software\\Microsoft\\Shared Tools Location" );
if( regKey != null )
{
objTmp = regKey.GetValue( "MSInfo" );
if( objTmp != null )
strPath = Path.Combine(
objTmp.ToString(), "MSInfo32.exe" );
}
}
else
strPath = objTmp.ToString();
try
{
FileInfo fi = new FileInfo( strPath );
return fi.Exists;
}
catch( ArgumentException )
{
strPath = string.Empty;
}
}
return false;
}
So we can get the full path to Msinfo32.exe and can run it:
MFC Sample
void CSomeDialog::StartSysInfo( void )
{
CString strMsinfo32( _T( "" ) );
if( GetSysInfoPath( strMsinfo32 ) )
{
#if _MSC_VER >= 1300 //Represents Microsoft Visual C++ .NET
#pragma warning( disable : 4311 )
#endif
UINT uRet = (UINT)::ShellExecute( GetSafeHwnd(), _T( "open" ),
strMsinfo32, NULL, NULL, SW_SHOWNORMAL );
#if _MSC_VER >= 1300 //Represents Microsoft Visual C++ .NET
#pragma warning( default : 4311 )
#endif
if( uRet < = HINSTANCE_ERROR )
{
AfxMessageBox( _T( "Error Executing \"MsInfo32.exe\" !" ),
MB_OK | MB_ICONEXCLAMATION );
}
}
else
{
AfxMessageBox( _T( "\"MsInfo32.exe\" cannot be found !" ),
MB_OK | MB_ICONEXCLAMATION );
}
}
Using with Chris Maunder's Hyperlink control:
#include "HyperLink.h"
public:
CHyperLink m_wndLinkSysInfo;
BOOL CSomeDialog::OnInitDialog( void )
{
CString strSysInfo( _T( "" ) );
if( GetSysInfoPath( strSysInfo ) )
m_wndLinkSysInfo.SetURL( strSysInfo );
else
m_wndLinkSysInfo.EnableWindow( FALSE );
}
C# Sample
private void StartSysInfo( string strSysInfo )
{
try
{
Process.Start( strSysInfo );
}
catch ( Win32Exception ex )
{
MessageBox.Show ( this, ex.Message, Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
}
}
private void lnkSysInfo_LinkClicked( object sender,
System.Windows.Forms.LinkLabelLinkClickedEventArgs e )
{
lnkSysInfo.Links[ lnkSysInfo.Links.IndexOf( e.Link ) ].Visited = true;
StartSysInfo( e.Link.LinkData.ToString() );
}
private void cmdSysInfo_Click( object sender, System.EventArgs e )
{
string strSysInfo = string.Empty;
if( GetMsinfo32Path( ref strSysInfo ) )
StartSysInfo( strSysInfo );
}
There is one more info tool on Windows NT 4.0 called WinMSD.exe - the descriptive name is Windows NT Diagnostics program. On Windows 2000 and XP platforms, the WinMSD tool has been replaced with MsInfo32.exe - so under Windows 2000/XP, WinMsd.exe is a stub executable file that starts Msinfo32.exe.
History
- 24th January, 2002: Posted article
- 5th February, 2002: Minor changes
- 28th July, 2002: Improved code for MFC 7.0, added C# code and download
- 4th August, 2002: Demo downloads fixed
- 5th October, 2002: New downloads
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.