Those Commercials
As I sit here watching the big game, with the Patriots not in it, I find myself like many others; looking forward to the commercials. The first break just concluded and offered up the first three commercials. The first was a beer commercial (I forget the sponsor) that was a Rock, Paper, Scissors spin off. This was ok, but it did not compare to the Doritos and Blockbuster Video commercials that followed. The Blockbuster commercial with the bunny clicking and dragging the mouse did make me burst out in laughter. There was something sadistically funny about the Doritos commercial that had me laughing quite loudly. Was it the ‘bold’ girl falling on her face or the ‘cheesy’ guy crashing and whacking his 'crunchy' face on the steering wheel? Those will be tough to beat…. I am still undecided on who to cheer for. Being a Patriots fan, I can't say I have a like for either team.
System Information and the PerformanceCounter Class
The other day I discussed retrieving system information using the .NET framework. I guess the main focus of that post was to discuss using PInvoke to call unmanaged WIN32 DLL exports, more so than actually retrieving different pieces of system information.
The objective of that post was retrieving memory information (I also retrieve disk information in my ‘AboutBox’ discussed in that post). In the 'managed codeworld' there is another way to get different information values. Using the System.Diagnostics.PerformanceCounter Class you can retrieve ‘counter’ information from a local or remote machine. Many of you may be familiar with some of the information accessible through PerformanceCounters if you run the
performance monitor control panel applet.
The information accessible via the System.Diagnostics.PerformanceCounter Class is not limited to just system information. Many services and applications also make ‘counter’ information available for retrieval. Performance Counters are broken out by category (System.Diagnostics.PerformanceCounterCategory). Within each category there many be multiple instances, for example the Logical Disk category will have an instance for each drive, as well as an instance for the _Total of all drives. Each instance will have its own set of counters that can be retrieved. In keeping with the same example, the _Total instance of the Logical Disk category has counters such as ‘% Free Space’, ‘Free Megabytes’ and ‘% Disk Write Time’ to name a few.
Reading counter information is a lot easier than one would expect (the .NET Framework almost made things too easy). I had created a basic-sample PerformanceCounter application that allows for the selection of one of the available (on the local machine) performance counter categories. Once the category is selected, each instance is listed (if there is more than one). Once the counter to be retrieved is selected the value is displayed in a System.Windows.Forms.ListBox (using a System.Timers.Timer for interval). Note: When I use Delphi for development I use the TChart component to display graphs (as I had in BPSNMPMon). If anyone knows of a decent charting control that works with Visual Studio 2005 let me know.
System.Diagnostics.PerformanceCounter perfcounter;
private void cbxPerfCategories_SelectedIndexChanged( object sender, EventArgs e )
{
cbxInstances.Enabled = true;
cbxInstances.Items.Clear ();
cbxCounters.Items.Clear ();
lstOutput.Items.Clear ();
timer1.Enabled = false;
if ( cbxPerfCategories.SelectedIndex != -1 )
{
if ( PerformanceCounterCategory.Exists ( cbxPerfCategories.Text ) )
{
PerformanceCounterCategory perfcategory =
new PerformanceCounterCategory ( cbxPerfCategories.Text );
cbxInstances.Items.AddRange ( perfcategory.GetInstanceNames () );
if ( cbxInstances.Items.Count == 0 )
{
cbxInstances.Enabled = false;
// Get the counters for a category that has only one
// instance
GetCounters ( perfcategory, "", cbxCounters );
}
}
}
}
private void GetCounters( PerformanceCounterCategory perfcategory,
string instancename,
ComboBox combobox )
{
System.Diagnostics.PerformanceCounter[] counters;
if ( instancename.Equals ( "" ) )
{
counters = perfcategory.GetCounters ();
}
else
{
counters = perfcategory.GetCounters ( instancename );
}
for ( int i = 0; i < counters.Length; i++ )
{
combobox.Items.Add ( counters[i].CounterName );
}
}
private void frmMain_Load( object sender, EventArgs e )
{
PerformanceCounterCategory[] perfcategories;
try
{
perfcategories = PerformanceCounterCategory.GetCategories ();
for ( int i = 0; i < perfcategories.Length; i++ )
{
cbxPerfCategories.Items.Add ( perfcategories[i].CategoryName );
}
}
catch ( Exception ex )
{
MessageBox.Show ( ex.Message, ex.Source, MessageBoxButtons.OK,
MessageBoxIcon.Error );
}
}
private void cbxInstances_SelectedIndexChanged( object sender, EventArgs e )
{
cbxCounters.Items.Clear ();
lstOutput.Items.Clear ();
timer1.Enabled = false;
if ( cbxInstances.SelectedIndex != -1 )
{
if ( PerformanceCounterCategory.InstanceExists ( cbxInstances.Text, cbxPerfCategories.Text ) )
{
PerformanceCounterCategory perfcategory =
new PerformanceCounterCategory ( cbxPerfCategories.Text );
GetCounters ( perfcategory, cbxInstances.Text, cbxCounters );
}
}
}
private void cbxCounters_SelectedIndexChanged( object sender, EventArgs e )
{
lstOutput.Items.Clear ();
if ( cbxInstances.Text.Equals ( "" ) )
{
perfcounter = new System.Diagnostics.PerformanceCounter ( cbxPerfCategories.Text,
cbxCounters.Text, true );
}
else
{
perfcounter = new System.Diagnostics.PerformanceCounter ( cbxPerfCategories.Text,
cbxCounters.Text, cbxInstances.Text, true );
}
timer1.Enabled = true;
}
private void timer1_Tick( object sender, EventArgs e )
{
float value;
value = perfcounter.NextValue ();
lstOutput.Items.Insert ( 0, value.ToString ( "#,##0.00" ) );
}
Cryptography hash and a class - to go
One of the things I appreciate the most in OOP is the concept of classes. I have found that the use of classes allows for code to be easily maintained and reused. I look at classes as neat little packaged objects that can be ‘moved around’ and ‘worked with’ as their own. Another big benefit of classes is the concept of inheritance and polymorphism. In three previous posts (1, 2, 3) I discussed using the System.Security.Cryptography Namespace to calculate the hash values of text (strings) and files. I actually did create a class (that I actively use) from that sample.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace BPSoftware.BPCrypto
{
public class CryptoHash
{
/// <summary>
/// public enum hashtypes { MD5, SHA1, SHA256, SHA384, SHA512 };
/// </summary>
public enum hashtypes
{
MD5, SHA1, SHA256, SHA384, SHA512
};
#region Properties
private Int64 _bytesread;
/// <summary>
/// Int64 Bytesread returns the number of bytes read when calculating the hash
/// value.
/// </summary>
public Int64 Bytesread
{
get
{
return _bytesread;
}
}
private hashtypes _hashtype;
/// <summary>
/// hashtypes Hashtype specifies the type of hash to calculate.
/// </summary>
public hashtypes Hashtype
{
get
{
return _hashtype;
}
set
{
_hashtype = value;
}
}
#endregion
#region Constructors
public CryptoHash()
{
}
public CryptoHash( hashtypes inhashtype )
{
_hashtype = inhashtype;
}
#endregion
#region Methods
private string GetByteString( byte[] data )
{
StringBuilder sb = new StringBuilder ();
for ( int i = 0; i < data.Length; i++ )
{
sb.Append ( data[i].ToString ( "x2" ) );
}
string bytestring = sb.ToString ();
return bytestring.ToUpper ();
}
private string GetHash( byte[] data )
{
HashAlgorithm ha;
switch ( _hashtype )
{
case hashtypes.MD5:
ha = MD5CryptoServiceProvider.Create ();
break;
case hashtypes.SHA1:
ha = SHA1Managed.Create ();
break;
case hashtypes.SHA256:
ha = SHA256Managed.Create ();
break;
case hashtypes.SHA384:
ha = SHA384Managed.Create ();
break;
case hashtypes.SHA512:
ha = SHA512Managed.Create ();
break;
default:
ha = MD5CryptoServiceProvider.Create ();
break;
}
_bytesread = data.Length;
byte[] res = ha.ComputeHash ( data );
return GetByteString ( res );
}
/// <summary>
/// GetStringHash calculates the hash value for a string.
/// </summary>
/// <param name="inputtext">String value.</param>
/// <returns>Returns the hash value of a file.</returns>
public string GetStringHash( string inputtext )
{
return GetHash ( Encoding.Default.GetBytes ( inputtext ) );
}
/// <summary>
/// GetFileHash calculates the hash value for a file.
/// </summary>
/// <param name="filename">Full file path for the file.</param>
/// <returns>Returns the hash value of a file.</returns>
public string GetFileHash( string filename )
{
_bytesread = 0;
byte[] filecontents;
FileInfo instance = new FileInfo ( filename );
if ( !instance.Exists )
{
throw new FileNotFoundException ();
}
else
{
try
{
FileStream ofs = instance.OpenRead ();
filecontents = new byte[ofs.Length];
int offset = 0;
int count = filecontents.Length;
while ( count > 0 )
{
int bytesread = ofs.Read ( filecontents, offset, count );
count -= bytesread;
offset += bytesread;
}
// ofs.Read(filecontents, 0, filecontents.Length);
ofs.Close ();
}
catch ( Exception e )
{
throw e;
}
}
return GetHash ( filecontents );
}
/// <summary>
/// CompareStrings compares the hash value of two strings to determine
/// if they are the same.
/// </summary>
/// <param name="string1">The first string to compare.</param>
/// <param name="string2">The second string to compare.</param>
/// <returns>Returns True if the strings are identical (same hash value).</returns>
public bool CompareStrings( string string1, string string2 )
{
string1 = GetStringHash ( string1 );
string2 = GetStringHash ( string2 );
return ( ( string1.CompareTo ( string2 ) == 0 ) );
}
/// <summary>
/// CompareFiles compares the hash value of the contents of two files to determine
/// if they are the same.
/// </summary>
/// <param name="filename1">Full file path for the first file to compare.</param>
/// <param name="filename2">Full file path for the second file to compare.</param>
/// <returns>Returns True if the files are identical (same hash value).</returns>
public bool CompareFiles( string filename1, string filename2 )
{
filename1 = GetFileHash ( filename1 );
filename2 = GetFileHash ( filename2 );
return ( ( filename1.CompareTo ( filename2 ) == 0 ) );
}
/// <summary>
/// CompareStringToHash compares a string's hash with a hash to determine if the hash values are the same.
/// </summary>
/// <param name="string1">The string to compare.</param>
/// <param name="hash">The hash to compare to.</param>
/// <returns>Returns True if the string1 hash and hash match.</returns>
public bool CompareStringtoHash( string string1, string hash )
{
return ( hash.CompareTo ( GetStringHash ( string1 ) ) == 0 );
}
/// <summary>
/// CompareFileToHash compares a file's hash with a hash to determine if the hash values are the same.
/// </summary>
/// <param name="filename1">Full file path for the file to compare.</param>
/// <param name="hash">The hash to compare to.</param>
/// <returns>Returns True if the filename1 hash and hash match.</returns>
public bool CompareFiletoHash( string filename1, string hash )
{
return ( hash.CompareTo ( GetFileHash ( filename1 ) ) == 0 );
}
#endregion
}
}