C#中遍历当前所有进程时存在的陷阱

有时候我们希望我们所写的exe在机器上同一时间只能有一个实例进行运行。通常我们会采取遍历当前所有的进程,如果有的进程exe所在的物理路径就是当前exe的物理路径的话,那么说明这个exe已经启动过一次了,就不再启动了。但是注意,这里有一些需要注意的小细节。

有时候对于编写一个应用程序的守护进程的时候,也要用到这个遍历方法。即我需要另外启动一个进程,这个进程启动后,要查看所有的进程,看看其所检测的进程是否已经启动。那么怎么判断遍历的那个进程是否是其目标进程呢?那么就需要看这个进程exe所在的路径是否与其检测的exe的路径是完全一致的。

首先,对于System与Idle进程的访问是没有权限的,一旦遍历到这个进程,并且调用p.MainModule.FileName方法的时候,就会抛出异常说Access denied. 这也容易理解,毕竟这是操作系统很高层次的进程,是不允许任何人有任何操作的。但是有时候不仅仅是这两个进程,如果你登录电脑的用户不是administrator用户,只是一般的用户,那么可能有更多的进程是不允许访问的。

其实对于我们的程序判断没有太大的影响,因为我们这个exe的层次跟那些拒绝访问的进程的层次不太一样。如果我的exe启动了一个进程,那么我的这个exe遍历所有进程的时候,对于这个已经启动的进程是肯定能访问的。也就是说,我们遍历的时候,肯定能访问我们想要访问的进程,只要它存在我们就能找到。所以对于这些抛出异常的进程,它如果抛出异常,我们程序就没法执行了,我们现在要做的就是,catch到异常,不去任何处理,继续运行我们的程序就行。

  Process[] processes = Process.GetProcesses();
  Process process = null;
  foreach (Process p in processes)
  {
		try
		{
		   //这里加if就是因为这两个进程的某些属性一旦访问就抛出没有权限的异常
		   if (p.ProcessName != "System" && p.ProcessName != "Idle")
                   {
                     if (p.MainModule.FileName == address)
                     {
                        process = p;
                        break;
                     }
                   }
		}
		catch(Exception ex)
		{
 		    Log.Info(ex.Message);
                }
   }

这里还有一个要注意的东西很重要,就是Console控制台程序的进程。对于一个控制台程序如果你不想同一个时间内有多个实例来运行,那么用这种方法是行不通的!

对于一般Windows Form程序来讲,如果我的程序名为FormApplicationA.exe,那么启动的进程就是FormApplicationA.exe,如果我的程序名为FormApplicationB.exe,那么启动的进程就是FormApplicationB.exe,而且其exe地址也就是真正的地址,比如说C:\\MyFolder\\FormApplicationA.exe 但是Console程序不一样,所有的控制台程序的进程名都是cnhost.exe,不管你的控制台程序名字是什么,这个exe是哪里。比如说,你启动了一个完全不相关的控制台程序ConsoleA.exe,这时遍历所有进程,你会得到cnhost.exe这个进程,而这个进程与ConsoleB.exe要启动的进程是同名,会错误的认为这个ConsoleB.exe已经启动了,就不再启动这个B.
所以这个遍历所有进程的方法对于控制台程序是行不通的。所以,一个控制台进程去守护另外一个控制台进程,使用这种方法是行不通的。

而且有一个cnhost.exe进程,是操作系统在开机的时候自己启动的,它有一定的自己的作用

What
is conhost.exe and Why Is It Running?

You are no doubt reading this article because you are wondering what on earth this conhost.exe process is doing in Task Manager, and why it’s running on your shiny new Windows 7 PC. We’ve got the answer for you.

So What Is It?

The conhost.exe process fixes a fundamental problem in the way previous versions of Windows handled console windows, which broke drag & drop in Vista.

It’s a completely legitimate executable—as long as it’s running from the system32 folder, and is signed by Microsoft. Scanning your computer for viruses is never a bad idea, though.

Wait, What? So Why Do I Need It?

Oh, you wanted more information? I suppose I can oblige with some background information. Essentially, there’s a problem with the way the console process works on previous versions of Windows—they are all
hosted under the csrss.exe
 (Client Server Runtime Process) service. This process runs as a system-privileged account.

If you take a look at the command prompt on Windows XP, you’ll probably notice that the window doesn’t use the active theme at all. This is because the CSRSS process doesn’t have the ability to be themed.

If you take a look at the console in Windows Vista, it looks like it uses the same theme as everything else, but you’ll notice that the scrollbars are still using the old style (look closely). This is because the DWM
(Desktop Window Manager) process
 handles drawing the title bars, but underneath it still works the same way, and the scrollbars are part of the window itself.

You might also notice that Windows Vista broke the ability to drag and drop files from Explorer straight into the command prompt. It just flat out doesn’t work, because of security issues between the CSRSS process running with a higher level of privileges.

Windows 7 Does It Differently

Checking it out in Process Explorer under Windows 7 shows that the conhost.exe process is running underneath the csrss.exe process.

The conhost.exe process sitting in the middle between CSRSS and cmd.exe allows Windows 7 to fix both of the problems in previous versions of Windows—not only do the scrollbars draw correctly, but you can actually drag and drop a file from Explorer straight
into the command prompt:

And it’ll paste in the path onto the command line. (of course this example isn’t very useful).

Still Aren’t Convinced?

I can see our relationship has some trust issues. If you really want to be sure, check out the file properties for the conhost.exe executable, and you’ll see that the description says Console Window Host:

If you look at the details of the process from within Process Explorer, you’ll notice that the ComSpec is set to cmd.exe, a clear indication that it’s hosting the command prompt.

So now you know what the conhost.exe process does, and why you should never attempt to delete it. Ever.

C#中遍历当前所有进程时存在的陷阱

时间: 2024-10-04 10:06:15

C#中遍历当前所有进程时存在的陷阱的相关文章

解决v-for中遍历多个el-select时,下拉选择框同步选择问题

当v-for遍历多个el-select时,由于v-model绑定的值为同一个,导致下拉选择时多个下拉选择框同步选择问题 如图是v-model绑定的同一个seatValue数据: 解决办法: 一.为el-select绑定不同的v-mode值,将v-for传递的index值绑定在v-model的参数上( v-model="seatValue[index]" ) 二.通过axios获取数据时,创建一个新的seatValue空数组,通过map遍历获取到的fourthContentArr里的每一

警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的陷阱

mer_stage 表有 216423 条记录,DDL: CREATE TABLE `mer_stage` ( `STAGE_ID` int(11) NOT NULL AUTO_INCREMENT, `MER_ID` int(11) NOT NULL, `MER_CODE` varchar(16) DEFAULT NULL, `MER_NAME` varchar(80) NOT NULL, `INS_CODE` varchar(16) NOT NULL, `INS_NAME` varchar(6

VC中遍历目标进程中的模块

VC中遍历目标进程中的模块 MFC代码win32 也可以用 在下面代码进行修改转换就可以了CString strModule; 可以换成 char* 但是MODULEENTRY32结构中的szModule是WCHAR 由于博主基础知识较差 所以使用的MFC里的Cstring函数 #include <Tlhelp32.h> /***************************************************/ /* 函数: 查找目标进程中是否有指定模块信息 /* 参数:DWO

C#/.NET 中启动进程时所使用的 UseShellExecute 设置为 true 和 false 分别代表什么意思?

原文:C#/.NET 中启动进程时所使用的 UseShellExecute 设置为 true 和 false 分别代表什么意思? 在 .NET 中创建进程时,可以传入 ProcessStartInfo 类的一个新实例.在此类型中,有一个 UseShellExecute 属性. 本文介绍 UseShellExecute 属性的作用,设为 true 和 false 时,分别有哪些进程启动行为上的差异. 本文内容 本质差异 效果差异 如何选择 本质差异 Process.Start 本质上是启动一个新的

创建进程时注入DLL

#include "stdafx.h" #include <Windows.h> // 函数声明 typedef BOOL (WINAPI* Proc_CreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInherit

Java中遍历Map的常用方法

以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等): 方式一(推荐): 1 // 推荐 2 // 在for-each循环中使用entries来遍历 3 // 注意:for-each循环在Java 5中被引入所以该方法只能应用于java 5或更高的版本中. 4 // 如果你遍历的是一个空的map对象,for-each循环将抛出NullPointerException,因此在遍历前你总是应该检查空引用. 5 private s

在GNU Linux中如何得到一个进程当前的流量

/*********************************************************************  * Author  : Samson  * Date    : 11/19/2014  * Test platform:  *              3.13.0-24-generic  *              GNU bash, 4.3.11(1)-release  * ************************************

IIS6与IIS7中的w3wp工作进程

在IIS6中,每一个网站都有对应的应用程序池,在应用程序池有运行着网站的Application,在默认情况下,所有的网站的应用程序都会分配到默认的应用程序池当中, 当然,我们可以新建一个应用程序池,然后更改网站所在的应用程序池. 添加一个应用程序池: 在网站的属性的主目录选项卡下修改网站所在的应用程序池: 查看结果: 因为此时默认的情况下,所有的网站都在同一个应用程序池中,所以它们都会共享同一个w3wp进程,因为在默认的应用程序池中默认设置的Web园的最大进程数为1,如图所示. 此时我们分别访问

Java中遍历Map对象

下面列出一些最常用的Java遍历Map对象的方法 1.在for-each中使用entrySet遍历 这是最常用的遍历方式.在键值都需要时使用. Map<String,String> map = new HashMap<String,String>(); for(Map.Entry<String, String> entry : map.entrySet()){ System.out.println(entry.getKey()+" : "+entry