There's an old tool I've had on my desktop for many years. It was originally called NetMedic, and I think I paid $50 for it back in, oh, about 1997. At some point it was sold, rebranded as VitalAgentIT and given away for free. Then it was built into some expensive, high-end IT solution and never heard from again. Here's the classic UI, still one of the nicest Windows apps ever.
Without this neat app, I always feel a little blind. It tells you exactly what kind of traffic is moving over your network in a slick, easy-to-grasp user interface.
I've been installing this puppy since NT4.0 days. It has some occasional startup problems with XP Pro, but overall, it's held up remarkably well.
Until XP x64 Edition. It won't run on my HP xw8200 workstation, and I won't really expect it to fair better on Vista, so it's getting to be the end of the road for this app. But it's just so useful, and I haven't found an inexpensive solution to replace it. So it's time to write my own.
Ideally, I'd like to write an almost exact replica of the original NetMedic app. WPF provides an ideal presentation stack to mimic arbitrary UI, so this makes a good project for learning WPF. It would be really neat if I could apply a "NetMedic" style, as well as other cool styles like USS Enterprise control panels. To pick the geekiest possible example.
NetMedic/VitalAgentIT shares similarities with another system monitoring app, Norton System Doctor.
Both programs are built on Win32 APIs. NetMedic is (probably) built on NetMon, and Norton System Doctor is built on the performance monitor API (PerfMon).
Since there might be several different APIs for monitoring, I wanted to abstract the data source. I whipped up the generic ISignalGenerator interface.
public interface ISignalGenerator<T> { void Start(); void Stop(); double SampleRate { get; } T Seed { get; } long StartSample { get; } double Gain { get; set; } double DCOffset { get; set; } double Frequency { get; set; } event NewSamplesEventHandler<T> NewSamples; }
The Start method turns on the firehose, and the performance monitor samples the underlying data stream every SampleRate milliseconds. Data samples are returned through the NewSamples event. The underlying implementation is assumed to be asynchronous.
The .NET Framework provides the convenient PerformanceCounter wrapper type around the Win32 implementation. This type lives in the System.Diagnostics namespace.
I wanted to abstract the PerformanceCounter type a bit, and I wanted to give it a buffer for its data stream. The IPerformanceMonitor interface defines the controller part of the Model-View-Controller pattern.
namespace SystemMonitorLib.PerformanceMonitors { public interface IPerformanceMonitor : INotifyPropertyChanged
namespace SystemMonitorLib { public interface ISignalView<T> : INotifyPropertyChanged { ISignalGenerator<T> SignalSource { get; } T[] DisplayBuffer { get; } int DisplayBufferSize { get; set; } T MinValue { get; } T MaxValue { get; } } }
My PerformanceMonitorControl type derives from System.Windows.Controls.UserControl. As far as layout is concerned, there isn't much to it.
<UserControl x:Class="PerformanceMonitorControlLib.PerformanceMonitorControl"
Ideally, I want to be able to drop individual PerformanceMonitorControl instances onto a WPF page from the Cider Toolbox, then set their properties in Cider's property grid. But we're not quite there yet, so here's some hand-tooled code.
<Window x:Class="SystemMedic.Window1"
The neat thing about this code is that I was able to compose two different PerformanceMonitorControl instances (one a numeric display, the other a signal trace) to form a new display (bolded code). Ultimately, all the hard-coded property values will be factored into styles.
Here's what the app looks like. I call it SystemMedic, since it's trying to be a combination of NetMedic and Norton System Doctor.
There's a lot more I can do with this object model, but this is a start. Ultimately, I want it to look much more similar to NetMedic. It would also be cool to come up with a style that looks like the USS Enterprise displays from, say, Star Trek: The Next Generation. Which is to say, I want to be able to apply arbitrary styling to each control instance. Being able to do that at design time would be the sweetest, and between Sparkle and Cider, it should be quite doable.
Update: By popular demand, I've posted the source code, with the caveat that it's quite prototypical.
Here are a few things you'll need to know:
Since this is a prototype that I haven't touched since May, I'll describe a few design details for future work.
In general, the code needs to be refactored to adhere more closely to the Framework Design Guidelines. I would start by removing the interfaces and replacing them with abstract base classes.
I think the framework should be simplified greatly, as well. I originally had in mind a much more general signal-display framework, which could handle fast (kHz) signals, but that's largely unnecessary for this application.
In any case, have fun, and let me know how it works for you.