应用程序管理






3.71/5 (5投票s)
Application Management 让您的应用程序生活更轻松。它将自动进行内存管理,处理和记录未处理的异常,分析您的函数,使您的应用程序成为单实例,并提供用于获取系统信息的实用函数。
目录
引言
Application Management 让您的应用程序生活更轻松。它将自动进行内存管理,处理和记录未处理的异常,分析您的函数,使您的应用程序成为单实例,并提供用于获取系统信息的实用函数。
支持的平台
该库可在多个平台上运行,并在 Windows XP、Windows 7 和 Linux Ubuntu 9.10 上进行了测试。对于 Linux,我提供了 Mono 编译版本,您可以重新编译或执行。bin 下的 Debug 和 Release 文件夹是使用 Visual Studio 2008 (Windows) 编译的。bin 下的 Mono 文件夹是使用 MonoDevelop (Mono 系统兼容) 编译的。
类和函数受操作系统不兼容异常的保护。所有 WinAPI 函数在 Windows 系统外都将无法正常工作。
如果您想进行自己的系统验证,请使用以下代码
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
{
// Windows NT Platform
}
else
{
// Non Windows System
}
背景
此库不能替代您的内联优化,只要可能,您始终必须 Dispose
您的对象。
使用代码
大多数类都应该在作用域之外使用,并声明为 static
。我将使用 public static
来允许我从任何地方访问类。具有 Start();
方法的类也具有 Stop();
方法。
库中的类
有关类的更多信息,请参阅文档文件。
WinAPI
(包含所有 Win API 调用) 命名空间Dbghelp
(Dbghelp.dll 的所有 API 调用) 静态类Kernel32
(Kernel32.dll 的所有 API 调用) 静态类About
(存储有关库、作者、网页等的常量...) 静态类AssemblyEx
(来自程序集的 Util 函数) 静态类ExceptionHandler
(自动处理和记录未处理的异常) 类Instance
(使您的应用程序成为单实例) 类MemoryManagement
(自动内存管理) 类MiniDump
(用于创建迷你转储) 静态类Profiling
(用于分析函数,ProfilingData
的Dictionary
) 类ProfilingData
(存储分析数据的类,StartDate、EndDate、TimeTaken,...) 类SystemInformationEx
(提供一些与系统信息相关的 GET 函数) 静态类VistaSecurity
(与 Windows Vista 及更高版本相关的函数) 静态类
Instance 类
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 类
注意: MemoryManagement
仅在 WinNT 系统中生效;否则,您仍然可以在任何系统下使用 **静态方法**。
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 类
注意: 请确保在运行应用程序之前启动。如果未启动,请在运行应用程序之前使用以下代码
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
此类可以生成包含详细错误信息的 .txt 文件。它还可以创建可使用 Visual Studio 等程序进行调试的转储 (.dmp) 文件。Minidump 文件 (Windows) [^]
日志存储的默认目录是:APPEXEdir\Logs\AppErrors\。文件名格式为: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());
}
以下是未处理异常日志的示例 (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 类
注意:最好直接使用 Profiling.ProfilingData
。Profiling
类是 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());
}
另一个例子
/// <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");
}
注意:为了避免重复键并方便编码,您可以使用 Profiling.ProfilingData
。**再次强调**,Profiling
类是可选的,只是一个包装器,用于存储 Profiling.ProfilingData
类,其中包含一个 Dictionary<string, Profiling.ProfilingData>
。**但是**,如果您想保留和存储一个分析函数以供以后使用或获取结果,最好使用 Profiling
类。
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 类
/// <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();
}
整合所有内容
#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();
}
您的项目是否使用了这个库?
如果您在任何项目中使用我的库,请告诉我。您可以在讨论区发布您的应用程序名称和链接。这对我来说也是一种激励,知道人们正在使用我的库。
捐赠
编写库需要时间,而我的所有工作都是免费的。捐赠对我来说是一种激励,鼓励我制作更好的库。请考虑捐赠:PayPal 捐赠[^]。
您也可以使用 SourceForge 的捐赠系统进行捐赠
其他主页
历史
版本 1.0
- 首次发布。