在.NET Compact Framework 的进程管理需要调用win32的API,也就是P/Invoke,在msnd上提供了这一P/Invoke的源代码, Creating a Microsoft .NET Compact Framework-based Process Manager Application,由于在技术交流群里有不同的人问同样的问题,因此打算写一下。
Win32 API
关键的API 如下:
privateconstintTH32CS_SNAPPROCESS=0x00000002;
[DllImport("toolhelp.dll")]
publicstaticexternIntPtrCreateToolhelp32Snapshot(uintflags,uintprocessid);
[DllImport("toolhelp.dll")]
publicstaticexternintCloseToolhelp32Snapshot(IntPtrhandle);
[DllImport("toolhelp.dll")]
publicstaticexternintProcess32First(IntPtrhandle,byte[]pe);
[DllImport("toolhelp.dll")]
publicstaticexternintProcess32Next(IntPtrhandle,byte[]pe);
[DllImport("coredll.dll")]
privatestaticexternIntPtrOpenProcess(intflags,boolfInherit,intPID);
privateconstintPROCESS_TERMINATE=1;
[DllImport("coredll.dll")]
privatestaticexternboolTerminateProcess(IntPtrhProcess,uintExitCode);
[DllImport("coredll.dll")]
privatestaticexternboolCloseHandle(IntPtrhandle);
privateconstintINVALID_HANDLE_VALUE=-1;
调用上面的API就能就能轮询出所有的进程,可以杀死指定进程了。
Structures
调用这些API需要下面的结构体 PROCESSENTRY32,结构体的转换是P/Invoke里面最难的部分,我曾经写过一篇这样的文章(.NET Compact Framework 下Win32 API P/Invoke 的使用),还是有很多需要学习和改进的地方,欢迎指教。
PROCESSENTRY32 implementation
#regionPROCESSENTRY32implementation
//typedefstructtagPROCESSENTRY32
//{
//DWORDdwSize;
//DWORDcntUsage;
//DWORDth32ProcessID;
//DWORDth32DefaultHeapID;
//DWORDth32ModuleID;
//DWORDcntThreads;
//DWORDth32ParentProcessID;
//LONGpcPriClassBase;
//DWORDdwFlags;
//TCHARszExeFile[MAX_PATH];
//DWORDth32MemoryBase;
//DWORDth32AccessKey;
//}PROCESSENTRY32;
privateclassPROCESSENTRY32
{
//constantsforstructuredefinition
privateconstintSizeOffset=0;
privateconstintUsageOffset=4;
privateconstintProcessIDOffset=8;
privateconstintDefaultHeapIDOffset=12;
privateconstintModuleIDOffset=16;
privateconstintThreadsOffset=20;
privateconstintParentProcessIDOffset=24;
privateconstintPriClassBaseOffset=28;
privateconstintdwFlagsOffset=32;
privateconstintExeFileOffset=36;
privateconstintMemoryBaseOffset=556;
privateconstintAccessKeyOffset=560;
privateconstintSize=564;
privateconstintMAX_PATH=260;
//datamembers
publicuintdwSize;
publicuintcntUsage;
publicuintth32ProcessID;
publicuintth32DefaultHeapID;
publicuintth32ModuleID;
publicuintcntThreads;
publicuintth32ParentProcessID;
publiclongpcPriClassBase;
publicuintdwFlags;
publicstringszExeFile;
publicuintth32MemoryBase;
publicuintth32AccessKey;
//Defaultconstructor
publicPROCESSENTRY32()
{
}
//createaPROCESSENTRYinstancebasedonabytearray
publicPROCESSENTRY32(byte[]aData)
{
dwSize=GetUInt(aData,SizeOffset);
cntUsage=GetUInt(aData,UsageOffset);
th32ProcessID=GetUInt(aData,ProcessIDOffset);
th32DefaultHeapID=GetUInt(aData,DefaultHeapIDOffset);
th32ModuleID=GetUInt(aData,ModuleIDOffset);
cntThreads=GetUInt(aData,ThreadsOffset);
th32ParentProcessID=GetUInt(aData,ParentProcessIDOffset);
pcPriClassBase=(long)GetUInt(aData,PriClassBaseOffset);
dwFlags=GetUInt(aData,dwFlagsOffset);
szExeFile=GetString(aData,ExeFileOffset,MAX_PATH);
th32MemoryBase=GetUInt(aData,MemoryBaseOffset);
th32AccessKey=GetUInt(aData,AccessKeyOffset);
}
#regionHelperconversionfunctions
//utility:getauintfromthebytearray
privatestaticuintGetUInt(byte[]aData,intOffset)
{
returnBitConverter.ToUInt32(aData,Offset);
}
//utility:setauintintthebytearray
privatestaticvoidSetUInt(byte[]aData,intOffset,intValue)
{
byte[]buint=BitConverter.GetBytes(Value);
Buffer.BlockCopy(buint,0,aData,Offset,buint.Length);
}
//utility:getaushortfromthebytearray
privatestaticushortGetUShort(byte[]aData,intOffset)
{
returnBitConverter.ToUInt16(aData,Offset);
}
//utility:setaushortintthebytearray
privatestaticvoidSetUShort(byte[]aData,intOffset,intValue)
{
byte[]bushort=BitConverter.GetBytes((short)Value);
Buffer.BlockCopy(bushort,0,aData,Offset,bushort.Length);
}
//utility:getaunicodestringfromthebytearray
privatestaticstringGetString(byte[]aData,intOffset,intLength)
{
StringsReturn=Encoding.Unicode.GetString(aData,Offset,Length);
returnsReturn;
}
//utility:setaunicodestringinthebytearray
privatestaticvoidSetString(byte[]aData,intOffset,stringValue)
{
byte[]arr=Encoding.ASCII.GetBytes(Value);
Buffer.BlockCopy(arr,0,aData,Offset,arr.Length);
}
#endregion
//createaninitializeddataarray
publicbyte[]ToByteArray()
{
byte[]aData;
aData=newbyte[Size];
//settheSizemember
SetUInt(aData,SizeOffset,Size);
returnaData;
}
publicstringName
{
get
{
returnszExeFile.Substring(0,szExeFile.IndexOf('\0'));
}
}
publiculongPID
{
get
{
returnth32ProcessID;
}
}
publiculongBaseAddress
{
get
{
returnth32MemoryBase;
}
}
publiculongThreadCount
{
get
{
returncntThreads;
}
}
}
#endregion
Wrapped Class
Process class#regionProcessclass
///<summary>
///SummarydescriptionforProcess.
///</summary>
publicclassProcess
{
privatestringprocessName;
privateIntPtrhandle;
privateintthreadCount;
privateintbaseAddress;
//defaultconstructor
publicProcess()
{
}
privateProcess(IntPtrid,stringprocname,intthreadcount,intbaseaddress)
{
handle=id;
processName=procname;
threadCount=threadcount;
baseAddress=baseaddress;
}
//ToStringimplementationforListBoxbinding
publicoverridestringToString()
{
returnprocessName;
}
publicintBaseAddress
{
get
{
returnbaseAddress;
}
}
publicintThreadCount
{
get
{
returnthreadCount;
}
}
publicIntPtrHandle
{
get
{
returnhandle;
}
}
publicstringProcessName
{
get
{
returnprocessName;
}
}
publicintBaseAddess
{
get
{
returnbaseAddress;
}
}
publicvoidKill()
{
IntPtrhProcess;
hProcess=OpenProcess(PROCESS_TERMINATE,false,(int)handle);
if(hProcess!=(IntPtr)INVALID_HANDLE_VALUE)
{
boolbRet;
bRet=TerminateProcess(hProcess,0);
CloseHandle(hProcess);
}
}
publicstaticProcess[]GetProcesses()
{
ArrayListprocList=newArrayList();
IntPtrhandle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if((int)handle>0)
{
try
{
PROCESSENTRY32peCurrent;
PROCESSENTRY32pe32=newPROCESSENTRY32();
//GetbytearraytopasstotheAPIcalls
byte[]peBytes=pe32.ToByteArray();
//Getthefirstprocess
intretval=Process32First(handle,peBytes);
while(retval==1)
{
//Convertbytestotheclass
peCurrent=newPROCESSENTRY32(peBytes);
//Newinstance
Processproc=newProcess(newIntPtr((int)peCurrent.PID),peCurrent.Name,(int)peCurrent.ThreadCount,(int)peCurrent.BaseAddress);
procList.Add(proc);
retval=Process32Next(handle,peBytes);
}
}
catch(Exceptionex)
{
thrownewException("Exception:"+ex.Message);
}
//Closehandle
CloseToolhelp32Snapshot(handle);
return(Process[])procList.ToArray(typeof(Process));
}
else
{
thrownewException("Unabletocreatesnapshot");
}
}
#endregion
Client
staticvoidMain(string[]args){
if(args.Length==0)
{
Console.WriteLine("Pleaseentertheprocessname.");
return;
}
stringprocessName=args[0].ToUpper()+".EXE";
Process[]processes=Process.GetProcesses();
foreach(Processprocinprocesses)
{
if(proc.ProcessName.ToUpper()==processName)
{
proc.Kill();
Console.WriteLine("{0}waskilled.",processName);
break;
}
}
}
这是一个简单的杀进程例子,要取出进程信息,读Process 的attribute就可以了,十分简单。
参考文献
Creating a Microsoft .NET Compact Framework-based Process Manager Application
上述代码来源于msnd,msnd的源代码