(view source code of listprogs.cs as plain text)
using System;
using System.Collections.Generic;
using System.Management;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace RobvanderWoude{ class ListProgs {static string progver = "1.03";
static SortedList<string, string[]> reglist = new SortedList<string, string[]>( );
static string pattern = String.Empty;
static int Main( string[] args )
{ #region Initialize Variablesstring display = "List";
bool separators = false;
int rc = 0;
int switchcount = 0;
#endregion Initialize Variables #region Command Line parsingif ( args.Length > 2 )
{return ErrorMessage( "Too many command line arguments" );
}foreach ( string arg in args )
{switch ( arg.ToUpper( ) )
{case "/?":
return ErrorMessage( );
case "/A":
if ( switchcount > 0 )
{return ErrorMessage( "Invalid command line argument(s)" );
}display = "Aligned";
switchcount += 1;
break;
case "/S":
if ( switchcount > 0 )
{return ErrorMessage( "Invalid command line argument(s)" );
}display = "Aligned";
separators = true;
switchcount += 1;
break;
case "/T":
if ( switchcount > 0 )
{return ErrorMessage( "Invalid command line argument(s)" );
}display = "TabDelimited";
switchcount += 1;
break;
default:
if ( String.IsNullOrEmpty( pattern ) && VerifyRegExPattern( arg ) )
{pattern = arg;
} else {return ErrorMessage( "Invalid command line argument \"{0}\"", arg );
}break;
} }if ( args.Length - switchcount > 1 )
{return ErrorMessage( "Invalid command line argument(s)" );
} #endregion Command Line parsing #region Read Registry // Check 32-bit software on 32-bit OS or 64-bit software on 64-bit OSbool listreg = ListReg( "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" );
// Check 32-bit software on 64-bit OSif ( Is64bitOS( ) )
{bool listreg2 = ListReg( "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" );
listreg = listreg || listreg2;
}if ( !listreg )
{return ErrorMessage( "Error reading the registry.\n\tMake sure you have sufficient permissions to read the registry." );
} #endregion Read Registry #region Show Resultsswitch ( display )
{case "Aligned":
rc = ShowTable( separators );
break;
case "TabDelimited":
rc = ShowTabDelimited( );
break;
default:
rc = ShowList( );
break;
} #endregion Show Resultsreturn rc;
} #region Subroutinesstatic int ErrorMessage( params string[] errmsg )
{ /* ListProgs.exe, Version 1.03 List "all" installed program names and versions found in the registry Usage: LISTPROGS [ "pattern" ] [ /A | /S | /T ] Where: "pattern" limits output to DisplayName values matching the regular expression "pattern" (case insensitive) /A shows results in Aligned table (default: List) /S aligned table with Separator lines (default: List) /T shows results Tab delimited (default: List) Notes: Searches HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall and HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall for subkeys that have both DisplayName and DisplayVersion set. Registry keys are displayed in the default List output, but not in Aligned output nor in Tab delimited output. With Aligned output (/A) a window width of 110 columns or wider is recommended - may be set with the command: MODE CON COLS=110 Written by Rob van der Woude http://www.robvanderwoude.com */if ( errmsg.Length > 0 )
{List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
}Console.Error.WriteLine( );
Console.Error.WriteLine( "ListProgs.exe, Version {0}", progver );
Console.Error.WriteLine( "List \"all\" installed program names and versions found in the registry" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ListProgs [ \"pattern\" ] [ /A | /S | /T ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Where: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "\"pattern\"" );
Console.ResetColor( );
Console.Error.WriteLine( " limits output to DisplayName values matching the regular" );
Console.Error.Write( " expression " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "\"pattern\"" );
Console.ResetColor( );
Console.Error.WriteLine( " (case insensitive)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /A" );
Console.ResetColor( );
Console.Error.Write( " shows results in " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.WriteLine( "ligned table (default: List)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /S" );
Console.ResetColor( );
Console.Error.Write( " aligned table with " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "S" );
Console.ResetColor( );
Console.Error.WriteLine( "eparator lines (default: List)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /T" );
Console.ResetColor( );
Console.Error.Write( " shows results " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "T" );
Console.ResetColor( );
Console.Error.WriteLine( "ab delimited (default: List)" );
Console.Error.WriteLine( );
Console.Error.WriteLine( @"Notes: Searches HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall and" );
Console.Error.WriteLine( @" HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" );
Console.Error.WriteLine( " for subkeys that have both DisplayName and DisplayVersion set." );
Console.Error.WriteLine( " Registry keys are displayed in the default List output, but not in" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " A" );
Console.ResetColor( );
Console.Error.Write( "ligned output nor in " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "T" );
Console.ResetColor( );
Console.Error.WriteLine( "ab delimited output." );
Console.Error.Write( " With " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.Write( "ligned output (" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/A" );
Console.ResetColor( );
Console.Error.WriteLine( ") a window width of 110 columns or wider" );
Console.Error.Write( " is recommended - may be set with the command: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "MODE CON COLS=110" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "http://www.robvanderwoude.com" );
return 1;
}static bool Is64bitOS( )
{UInt16 addresswidth = 0;
ManagementObjectSearcher searcher = new ManagementObjectSearcher( "root\\CIMV2", "SELECT * FROM Win32_Processor" );
foreach ( ManagementObject queryObj in searcher.Get( ) )
{addresswidth = (UInt16) ( queryObj["AddressWidth"] );
}return ( addresswidth == 64 );
}static bool ListReg( string regpath )
{ try {Regex regex = new Regex( pattern, RegexOptions.IgnoreCase );
RegistryKey regkey = Registry.LocalMachine.OpenSubKey( regpath );
foreach ( var regsubkey in regkey.GetSubKeyNames( ) )
{RegistryKey subkey = regkey.OpenSubKey( regsubkey );
try {string displayname = subkey.GetValue( "DisplayName" ).ToString( );
if ( !String.IsNullOrEmpty( displayname ) )
{if ( String.IsNullOrEmpty( pattern ) || regex.IsMatch( displayname ) )
{string displayversion = subkey.GetValue( "DisplayVersion" ).ToString( );
if ( !String.IsNullOrEmpty( displayversion ) )
{ // Chop DisplayVersion string at first occurence of linebreak or null characterif ( displayversion.IndexOfAny( "\0\n\r".ToCharArray( ) ) > -1 )
{displayversion = displayversion.Split( "\0\n\r".ToCharArray( ) )[0];
} // Remove all but the version numberstring trimpattern = @"(?:\b|\s|^)(?:v\.?)?(\d+(?:\.\d+)+[a-z]?)(?:\b|\s|$)";
Regex trimregex = new Regex( trimpattern, RegexOptions.IgnoreCase );
if ( trimregex.IsMatch( displayversion ) )
{displayversion = trimregex.Match( displayversion ).ToString( );
} // Add the entry to the list, if it wasn't added beforestring[] progval = new string[] { displayversion, subkey.ToString( ) };
if ( !reglist.ContainsKey( displayname ) )
{reglist.Add( displayname, progval );
} } } } }catch ( Exception )
{ // ignore }subkey.Close( );
}regkey.Close( );
return true;
}catch ( Exception )
{return false;
} }static int ShowList( )
{foreach ( KeyValuePair<string, string[]> prog in reglist )
{Console.WriteLine( "Registry Key = {0}", prog.Value[1] );
Console.WriteLine( "Display Name = {0}", prog.Key );
Console.WriteLine( "Display Version = {0}", prog.Value[0] );
Console.WriteLine( );
}return 0;
}static int ShowTabDelimited( )
{foreach ( KeyValuePair<string, string[]> prog in reglist )
{Console.WriteLine( "{0}\t{1}", prog.Key, prog.Value[0] );
}return 0;
}static int ShowTable( bool separators = false )
{string separator;
int maxnamelen = 0;
int maxverlen = 0;
int totalwidth = Console.WindowWidth;
if ( separators )
{separator = new String( '-', totalwidth - 1 );
} else {separator = String.Empty;
}foreach ( KeyValuePair<string, string[]> prog in reglist )
{maxnamelen = Math.Max( maxnamelen, prog.Key.Length );
maxverlen = Math.Max( maxverlen, prog.Value[0].Length );
}int col2width = maxverlen + 2;
int col1width = totalwidth - col2width - 3;
foreach ( KeyValuePair<string, string[]> prog in reglist )
{Console.Write( separator );
string key = prog.Key;
if ( key.Length > col1width )
{key = key.Substring( 0, col1width - 2 ) + "...";
}Console.WriteLine( " {0,-" + col1width + "} {1," + col2width + "}", key, prog.Value[0] );
}Console.Write( separator );
return 0;
}static bool VerifyRegExPattern( string testpattern )
{ // Test validity of RegEx pattern // Based on http://stackoverflow.com/questions/218680/can-i-test-if-a-regex-is-valid-in-c-sharp-without-throwing-exceptionif ( String.IsNullOrWhiteSpace( testpattern ) )
{return false;
} try {Regex.Match( "", testpattern );
return true;
}catch ( ArgumentException )
{return false;
} } #endregion Subroutines }}page last modified: 2025-10-11; loaded in 0.0094 seconds