Application Management






3.71/5 (5 votes)
Application Management makes your application's life easier. It will automatically do memory management, handle and log unhandled exceptions, profile your functions, make your application single instance, and also provide utility functions to get system information.
Table of Contents
- Introduction
- Supported platforms
- Background
- Using the code
- Classes in the library
- Instance class
- MemoryManagement class
- ExceptionHandler class
- Profiling class
- VistaSecurity class
- Putting it all together
- Did your project use this library?
- Donations
- Other homepages
- History
Introduction
Application Management makes your application life easier. It will automatic do memory management, handle and log unhandled exceptions, profile your functions, make your application single instance, and also provide utility functions to get system information.
Supported platforms
This library works on multiple platforms, and was tested on Windows XP, Windows 7, and Linux Ubuntu 9.10. For Linux, I have supplied Mono compilations that you can recompile or execute. The Debug and Release folders under bin were compiled used Visual Studio 2008 (Windows). The Mono folder under bin was compiled using MonoDevelop (Mono systems compatible).
Classes and functions are protected from incompatibility OS exceptions. All WinAPI functions wont work outside a Windows system.
If you want your own system verification, use the following code:
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
{
// Windows NT Platform
}
else
{
// Non Windows System
}
Background
This library does not replace your inline optimizations, you always have to Dispose
your objects whenever possible.
Using the code
Most of that classes should be used outside scope and declared as static
. I'm going to use public static
to allow me to access classes anywhere. Classes that have a Start();
also have a Stop();
.
Classes in the library
See the documentation file for more information about the classes.
WinAPI
(Contains all the Win API calls) namespaceDbghelp
(All API calls for Dbghelp.dll) static classKernel32
(All API calls for Kernel32.dll) static classAbout
(Store some constants about the library, author, webpage, etc...) static classAssemblyEx
(Util functions from the assembly) static classExceptionHandler
(Automatic handles and log unhandled exceptions) classsInstance
(Make your application single instance) classMemoryManagement
(Automatic memory management) classMiniDump
(Used to create mini dumps) static classProfiling
(Used for profiling your functions,Dictionary
ofProfilingData
) classProfilingData
(Class that holdd the profiling data, StartDate, EndDate, TimeTaken, ...) classSystemInformationEx
(Provides some GET functions related to system information) static classVistaSecurity
(Functions related to Windows Vista and/or above) static class
Instance vlass
public static Instance instance;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region Instance Class (Make single instance app)
// Check if that is a single instance, and name mutex as: "{ProductName}Mutex"
instance = new Instance(Application.ProductName);
// instance is created but make sure you call next line:
// First parameter is used to define mutex level (Global or this session only)
// Second parameter is used to check processes equality after check mutex
if (!instance.MakeSingleInstance(true, false))
{
Instance.ShowDuplicateInstanceDialogError();
// Stop and quit App.
return;
}
#endregion
Application.Run(new MainFrm());
// Note: by calling 'Instance.Dispose' method will release mutex,
// and app will be multi instance,
// But still checks for process equality!
// instance.Dispose();
}
MemoryManagement class
Note: MemoryManagement
only takes effect in WinNT systems; otherwise, you can still use static methods under any system.
public static MemoryManagement memory;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region Memory Management class
// MemoryManagement only make effect in WinNT Systems,
// if your app is multi system use that.
if (MemoryManagement.CanUseClass())
{
memory = new MemoryManagement();
memory.Start();
}
else
{
memory = null;
}
#endregion
Application.Run(new MainFrm());
}
ExceptionHandler class
Note: Please be sure you start before running your application. If you do not, please use the following code before running the application:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
This class can generate a .txt file with detailed error information. It also can create a dump (.dmp) file that can be debugged with a program like Visual Studio. Minidump Files (Windows) [^]
The default directory to store the logs is: APPEXEdir\Logs\AppErrors\. And, the filename format is: yyyy_MM_dd_HH_mm_ss.
public static ExceptionHandler exceptionHandler;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region Exception Handler Class
(Automatic cath and log unhandled exceptions)
// Automatic cath and log unhandled exceptions
exceptionHandler = new ExceptionHandler();
// Next two lines are optional
exceptionHandler.PrefixText =
"This file represets an error cath on our program";
exceptionHandler.SuffixText =
"Please fell free to send us that errors " +
"files via email: myapp@company.com";
exceptionHandler.StartHandlingExceptions();
#endregion
Application.Run(new MainFrm());
}
Here is a sample of an unhandled exception log (MyTestApp__2010_02_15_18_35_29.txt).
[MyTestApp]
Date=15-02-2010 18:35:29
Application=MyTestApp 1.0.0.0
ExecutablePath=D:\caza\c++\ApplicationManagement\MyTestApp\
bin\Release\MyTestApp.exe
Company=MyTestApp
This file represets an error cath on our program
########################
## Error ##
########################
[Exception1]
Message=O valor não pode ser nulo.
StackTrace= em MyTestApp.MainFrm.ButtonClick(Object sender, EventArgs e)
em D:\caza\c++\ApplicationManagement\MyTestApp\MainFrm.cs:line 115
em System.Windows.Forms.Control.OnClick(EventArgs e)
em System.Windows.Forms.Button.OnClick(EventArgs e)
em System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
em System.Windows.Forms.Control.WmMouseUp(
Message& m, MouseButtons button, Int32 clicks)
em System.Windows.Forms.Control.WndProc(Message& m)
em System.Windows.Forms.ButtonBase.WndProc(Message& m)
em System.Windows.Forms.Button.WndProc(Message& m)
em System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
em System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
em System.Windows.Forms.NativeWindow.Callback(
IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
TargetSite=Void ButtonClick(System.Object, System.EventArgs)
Source=MyTestApp
HelpLink=
########################
## System Information ##
########################
[System]
OperativeSystem=Windows 7 x86
ProcessorCount=2
########################
## Open Forms ##
########################
[Forms]
Form1=MyTestApp.MainFrm, Text: ApplicationManagement Library Test
########################
## Loaded Assemblies ##
########################
[mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]
Location=C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll
[MyTestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]
Location=D:\caza\c++\ApplicationManagement\
MyTestApp\bin\Release\MyTestApp.exe
[ApplicationManagement, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]
Location=D:\caza\c++\ApplicationManagement\MyTestApp\
bin\Release\ApplicationManagement.dll
[System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089]
Location=C:\Windows\assembly\GAC_MSIL\System.Windows.Forms\
2.0.0.0__b77a5c561934e089\System.Windows.Forms.dll
[System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]
Location=C:\Windows\assembly\GAC_MSIL\System\
2.0.0.0__b77a5c561934e089\System.dll
[System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]
Location=C:\Windows\assembly\GAC_MSIL\System.Drawing\
2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll
[System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]
Location=C:\Windows\assembly\GAC_32\System.Data\
2.0.0.0__b77a5c561934e089\System.Data.dll
[mscorlib.resources, Version=2.0.0.0, Culture=pt, PublicKeyToken=b77a5c561934e089]
Location=C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll
Please fell free to send us that errors files via email: myapp@company.com
Profiling class
Note: It is always better to work directly with Profiling.ProfilingData
. The Profiling
class is a Profiling.ProfilingData
Dictionary.
public static Profiling profiling;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region Profiling Class
// Our profiling will determinate the time taken by the app to initialize.
profiling = new Profiling();
Profiling.ProfilingData profilingData = profiling.Create("InitApp", true);
#endregion
// Wait 1.5s and see the output
Thread.Sleep(1500);
#region End started profile and show results
profilingData.Stop();
MessageBox.Show(
string.Format(
"Start Date: {0}\nEnd Date: {1}\nTime Taken: {2}ms",
profilingData.StartDate,
profilingData.EndDate,
profilingData.TimeTaken.TotalMilliseconds
),
"Our application initializes time");
#endregion
Application.Run(new MainFrm());
}
Another example
/// <summary>
/// Do some job and returns the time it takes
/// </summary>
Profiling.ProfilingData MyFunction()
{
// Note is better use a single class to all your profiling, but...
// Initialize class, create a profiling and start it
Profiling profiling = new Profiling("MyFunction", true);
// Also can use:
// Profiling.ProfilingData pData = profiling.Create("MyFunction");
// if (pData == null)
// Console.WriteLine("Won't execute profiling, name already exists.");
// Lets make some garbage
for(int i = 1; i <= 10000; i++)
{
Random rand = new Random();
Console.WriteLine(rand.Next(0, i));
}
// Function ends now let stop profiling and return the results.
Profiling.ProfilingData pData = profiling.Get("MyFunction");
// Note: you can check if pData is null if you not sure that exists
pData.Stop(); // profiling.Stop("MyFunction"); also works
return pData;
}
Profiling.ProfilingData pData = MyFunction();
if(pData.IsConcluded)
{
Console.WriteLine("Total time to execute 'MyFunction': {0} ({1}ms)",
pData.TimeTaken,
pData.TimeTaken.TotalMilliseconds);
}
else
{
Console.WriteLine("Developer doesn't write the function correct");
Console.WriteLine("A ProfilingData must be Stopped, " +
"before use EndDate and TimeTaken");
}
Note: To avoid duplicate keys and for fast coding, you can use Profiling.ProfilingData
. Again, the Profiling
class is optional and is just a wrapper of the Profiling.ProfilingData
class that holds a Dictionary<string, Profiling.ProfilingData>
. But, if you want to keep and store a profiling function to use later or to get results, it is better to use the Profiling
class.
Profiling.ProfilingData pData = new Profiling.ProfilingData();
pData.Start();
// Do your job here, time is counting!!!
// This way is more simple than use Profiling Class
pData.Stop();
/*
*
* pData.StartDate;
* pDate.EndDate;
* pDate.TimeTaken;
*
*/
// Discard variable
pData = null;
VistaSecurity class
/// <summary>
/// Under Windows Vista, if current user is not an administrator,
/// try elevate the permissions and exit from current application.
/// </summary>
if(!VistaSecurity.IsAdmin())
{
if(VistaSecurity.RestartElevated(Application.ExecutablePath))
Application.Exit();
}
Putting it all together
#region Variables
public static Instance instance;
public static MemoryManagement memory;
public static Profiling profiling;
public static ExceptionHandler exceptionHandler;
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region Profiling Class
// Our profiling will determinate
// the time taken by the app to initialize.
profiling = new Profiling();
Profiling.ProfilingData profilingData =
profiling.Create("InitApp", true);
#endregion
#region Instance Class (Make single instance app)
// Check if that is a single instance, and name
// mutex as: "{ProductName}Mutex"
instance = new Instance(Application.ProductName);
// instance is created but make sure you call next line:
// First parameter is used to define mutex level
// (Global or this session only)
// Second parameter is used to check
// processes equality after check mutex
if (!instance.MakeSingleInstance(true, false))
{
Instance.ShowDuplicateInstanceDialogError();
// Stop and quit App.
return;
}
#endregion
#region Memory Management class
// MemoryManagement only make effect in WinNT Systems,
// if your app is multi system use that.
if (MemoryManagement.CanUseClass())
{
memory = new MemoryManagement();
memory.Start();
}
else
{
memory = null;
}
#endregion
#region Exception Handler Class
(Automatic cath and log unhandled exceptions)
// Automatic cath and log unhandled exceptions
exceptionHandler = new ExceptionHandler();
// Next two lines are optional
exceptionHandler.PrefixText =
"This file represets an error cath on our program";
exceptionHandler.SuffixText =
"Please fell free to send us that errors " +
"files via email: myapp@company.com";
exceptionHandler.StartHandlingExceptions();
#endregion
#region End started profile and show results
profilingData.Stop();
MessageBox.Show(
string.Format(
"Start Date: {0}\nEnd Date: {1}\nTime Taken: {2}ms",
profilingData.StartDate,
profilingData.EndDate,
profilingData.TimeTaken.TotalMilliseconds
),
"Our application initializes time");
#endregion
Application.Run(new MainFrm());
// Note: by calling 'Instance.Dispose' method will release mutex,
// and app will be multi instance,
// But still checks for process equality!
// instance.Dispose();
}
Did your project use this library?
Please let me know if you are using my library in any of your projects. You can post your application name and link on discussions. This is also an incentive to me, knowing that people are using my libraries.
Donations
Writing libraries takes time and all my job is free. Donations are an incentive to me, and encourage me to make better libraries. Please consider making a donation: PayPal Donation[^].
You can alos donate using the SourceForge donations system:
Other homepages
History
Version 1.0
- First release.