1) 根据“程序集的签名”获取已运行的实例
/// <summary>
/// 根据“程序集的签名”获取已运行的实例
/// .EXE 文件改名或路径改变,此方法可正常工作
/// </summary>
/// <param name="runningProcess">前一个实例的 Process</param>
/// <returns>是否有相同的实例在运行 ture/false</returns>
/// <remarks>需要对程序集进行签名。存在问题:速度稍慢。</remarks>
private static bool GetRunningProcessByAssemblyName(out Process runningProcess)
{
bool returnValue = false;
runningProcess = null;
AssemblyName currentAssemblyName =
AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location);
AssemblyName processAssemblyName = new AssemblyName();
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
// 排除一些其他进程,可以加快点速度。
if (process.Id != current.Id &&
process.ProcessName != "System" &&
process.ProcessName != "csrss" &&
process.ProcessName != "svchost" &&
process.ProcessName != "services" &&
process.ProcessName != "smss" &&
process.ProcessName != "winlogon" &&
process.ProcessName != "explorer" &&
process.ProcessName != "pds" &&
process.ProcessName != "alg" &&
process.ProcessName != "msdtc" &&
process.ProcessName != "spoolsv" &&
process.ProcessName != "lsass" &&
process.ProcessName != "Idle" &&
process.ProcessName != "iexplore" &&
process.ProcessName != "sqlserver" &&
process.ProcessName != "notepad" &&
process.ProcessName != "360tray" &&
process.ProcessName != "XDict"
)
{
try
{
// 获取文件的程序集
processAssemblyName = AssemblyName.GetAssemblyName(process.MainModule.FileName);
}
catch (Exception)
{
processAssemblyName = null;
}
// 通过 GetPublicKey() 来获取程序集的公钥;需要对程序集签名,否则 GetPublicKey() 返回的是 Null。
if (processAssemblyName != null &&
CompareBytes(currentAssemblyName.GetPublicKey(),
processAssemblyName.GetPublicKey()))
{
runningProcess = process;
returnValue = true;
break;
}
}
}
return returnValue;
}
2) 根据“进程名称”获取已运行的实例
/// <summary>
/// 根据“进程名称”获取已运行的实例
/// </summary>
/// <param name="runningProcess">前一个实例的 Process</param>
/// <returns>是否有相同的实例在运行 ture/false</returns>
/// <remarks>存在问题:1)有可能有相同的进程名; 2)修改了文件名,此方法失效。</remarks>
private static bool GetRunningProcessByProcessName(out Process runningProcess)
{
bool returnValue = false;
runningProcess = null;
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (process.ProcessName == current.ProcessName)
{
runningProcess = process;
returnValue = true;
break;
}
}
}
return returnValue;
}
3) 根据“进程名称和路径”获取已运行的实例
/// <summary>
/// 根据“进程名称和路径”获取已运行的实例
/// </summary>
/// <param name="runningProcess">前一个实例的 Process</param>
/// <returns>是否有相同的实例在运行 ture/false</returns>
/// <remarks>存在问题:修改了文件名或改变了文件路径,此方法失效。</remarks>
private static bool GetRunningProcessByProcessFullName(out Process runningProcess)
{
bool returnValue = false;
runningProcess = null;
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (process.MainModule.FileName ==
Assembly.GetExecutingAssembly().Location)
{
runningProcess = process;
returnValue = true;
break;
}
}
}
return returnValue;
}
4) 根据“Mutex”判断是否有相同的实例在运行
/// <summary>
/// 根据“Mutex”判断是否有相同的实例在运行
/// </summary>
/// <param name="runningProcess">总是 null</param>
/// <returns>是否有相同的实例在运行 ture/false</returns>
/// <remarks>存在问题:不能返回前一个实例的 Process</remarks>
private static bool GetRunningProcessByMutex(out Process runningProcess)
{
bool returnValue = false;
runningProcess = null;
bool isCreated;
Mutex m = new Mutex(false, "OneInstance", out isCreated);
if (!(isCreated))
{
MessageBox.Show("已经有相同的实例在运行。", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
returnValue = !isCreated;
return returnValue;
}
#region 私有方法
/// <summary>
/// 设置指定进程的窗口为活动
/// </summary>
private static void SetForegroundProcess(Process process)
{
bool isIcon = IsIconic(process.MainWindowHandle);
// 窗口是否已最小化
if (isIcon)
{
// 还原窗口
ShowWindowAsync(process.MainWindowHandle, SW_RESTORE);
}
else
{
// 将窗口设为前台窗口
SetForegroundWindow(process.MainWindowHandle);
}
}
/// <summary>
/// 比较两个字节数组是否相等
/// </summary>
private static bool CompareBytes(byte[] bytes1, byte[] bytes2)
{
if (bytes1 == null || bytes2 == null)
return false;
if (bytes1.Length != bytes2.Length)
return false;
for (int i = 0; i < bytes1.Length; i++)
{
if (bytes1[i] != bytes2[i])
return false;
}
return true;
}
#endregion
#region Windows API 声明
/// <summary>
/// 恢复一个最小化的程序,并将其激活
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool OpenIcon(IntPtr hWnd);
/// <summary>
/// 窗口是否已最小化
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
/// <summary>
/// 将窗口设为系统的前台窗口
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
/// <summary>
/// 与ShowWindow相似,只是这时的ShowWindow命令会投递到指定的窗口,然后进行异步处理。
/// 这样一来,就可控制从属于另一个进程的窗口的可视情况。
/// 同时无须担心另一个进程挂起的时候,自己的应用程序也会牵连其中返回值
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">为窗口指定可视性方面的一个命令</param>
/// <returns>如窗口之前是可见的,则返回TRUE(非零),否则返回FALSE(零)</returns>
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
private const int SW_HIDE = 0; //隐藏窗口,活动状态给令一个窗口
private const int SW_SHOWNORMAL = 1; //用原来的大小和位置显示一个窗口,同时令其进入活动状态
private const int SW_SHOWMINIMIZED = 2; //最小化窗口,并将其激活
private const int SW_SHOWMAXIMIZED = 3; //最大化窗口,并将其激活
private const int SW_SHOWNOACTIVATE = 4; //用最近的大小和位置显示一个窗口,同时不改变活动窗口
private const int SW_RESTORE = 9; //用原来的大小和位置显示一个窗口,同时令其进入活动状态
private const int SW_SHOWDEFAULT = 10; //根据默认 创建窗口时的样式 来显示
#endregion
分享到:
相关推荐
273 实例191 判断文件是否正在被使用 274 实例192 在程序中调用.HLP文件 275 实例193 C#中实现文件拖放 276 实例194 文件比较 276 第7章 操作系统与Windows相关程序 279 7.1 启动相关...
实例050 只允许输入数字的TextBox控件 57 实例051 在TextBox控件底端显示下划线 59 实例052 屏蔽TextBox控件上的粘贴功能 61 实例053 屏蔽TextBox控件上默认的右键菜单 62 2.2 ComboBox控件应用 63 实例054 ...
实例032 开发一个猜数字游戏 第4章 字符与字符串 实例033 字母与ascii码的转换 实例034 获取字符串中汉字的个数 实例035 从字符串中分离文件路径、文件名及扩展名 实例036 对字符串进行加密与解密 实例037 开发一个...
实例050 只允许输入数字的TextBox控件 57 实例051 在TextBox控件底端显示下划线 59 实例052 屏蔽TextBox控件上的粘贴功能 61 实例053 屏蔽TextBox控件上默认的右键菜单 62 2.2 ComboBox控件应用 63 实例054 ...
实例050 只允许输入数字的TextBox控件 57 实例051 在TextBox控件底端显示下划线 59 实例052 屏蔽TextBox控件上的粘贴功能 61 实例053 屏蔽TextBox控件上默认的右键菜单 62 2.2 ComboBox控件应用 63 实例054 ...
实例032 开发一个猜数字游戏 45 第4章 字符与字符串 47 实例033 字母与ascii码的转换 48 实例034 获取字符串中汉字的个数 50 实例035 从字符串中分离文件路径、文件名及扩展名 51 实例036 对字符串进行加密与解密 53...
实例050 只允许输入数字的TextBox控件 57 实例051 在TextBox控件底端显示下划线 59 实例052 屏蔽TextBox控件上的粘贴功能 61 实例053 屏蔽TextBox控件上默认的右键菜单 62 2.2 ComboBox控件应用 63 实例054 ...
第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 3.5 小 结 .27 第二部分 C#程序设计基础.28 第四章 数 据 类 型 .28 4.1 值 类 型...