Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9701

C# NtQuerySystemInformation関数でSystemProcessInformationを取得するコード

$
0
0

C# (.NET Core 3.1)でNtQuerySystemInformation関数を用いてSystemProcessInformationの情報を取得するコードの覚書です。動作確認環境はMicrosoft Visual Studio Community 2019 Version 16.5.2です。

途中で以下の操作も行っています。

  • DllImportによる遅延バインディング
  • MarshalAs(UnmanagedType.ByValArray, SizeConst = ...)
  • Marshal.PtrToStructureによる固定長配列を含む構造体の扱い
  • Marshal.PtrToStringUniによるポインタから文字列の作成
  • System.Diagnostics.DebuggerDisplayによるデバッガーへの情報表示
  • GCHandleMarshal.PtrToStructureによるCスタイル可変長配列の読み込み
Program.cs
usingSystem;usingSystem.Collections.Generic;usingSystem.Diagnostics;usingSystem.Runtime.InteropServices;namespaceConsoleApp1{classProgram{privatestaticclassNativeMethods{[DllImport("ntdll.dll",SetLastError=false,ExactSpelling=true)]publicstaticexternintNtQuerySystemInformation(intSystemInformationClass,byte[]SystemInformation,uintSystemInformationLength,outuintReturnLength);}privateenumSYSTEM_INFORMATION_CLASS:int{// SystemBasicInformation = 0,// SystemPerformanceInformation = 2,// SystemTimeOfDayInformation = 3,SystemProcessInformation=5,// SystemProcessorPerformanceInformation = 8,// SystemInterruptInformation = 23,// SystemExceptionInformation = 33,// SystemRegistryQuotaInformation = 37,// SystemLookasideInformation = 45,// SystemCodeIntegrityInformation = 103,// SystemPolicyInformation = 134,}[StructLayout(LayoutKind.Sequential)]privatestructUNICODE_STRING{publicushortLength;publicushortMaximumLength;publicIntPtrBuffer;}[StructLayout(LayoutKind.Sequential)]privatestructSYSTEM_PROCESS_INFORMATION{publicuintNextEntryOffset;publicuintNumberOfThreads;[MarshalAs(UnmanagedType.ByValArray,SizeConst=48)]publicbyte[]Reserved1;publicUNICODE_STRINGImageName;publicintBasePriority;publicIntPtrUniqueProcessId;publicIntPtrReserved2;publicuintHandleCount;publicuintSessionId;publicIntPtrReserved3;publicUIntPtrPeakVirtualSize;publicUIntPtrVirtualSize;publicuintReserved4;publicUIntPtrPeakWorkingSetSize;publicUIntPtrWorkingSetSize;publicIntPtrReserved5;publicUIntPtrQuotaPagedPoolUsage;publicIntPtrReserved6;publicUIntPtrQuotaNonPagedPoolUsage;publicUIntPtrPagefileUsage;publicUIntPtrPeakPagefileUsage;publicUIntPtrPrivatePageCount;[MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]publiclong[]Reserved7;}/// <summary>/// SYSTEM_PROCESS_INFORMATION構造体のデータを保持するクラスです。/// </summary>[DebuggerDisplay("{ImageName} ({UniqueProcessId})")]privateclassSystemProcessInformation{publicreadonlyuintNumberOfThreads;publicreadonlystringImageName;publicreadonlyintBasePriority;publicreadonlyIntPtrUniqueProcessId;publicreadonlyuintHandleCount;publicreadonlyuintSessionId;publicreadonlyUIntPtrPeakVirtualSize;publicreadonlyUIntPtrVirtualSize;publicreadonlyUIntPtrPeakWorkingSetSize;publicreadonlyUIntPtrWorkingSetSize;publicreadonlyUIntPtrQuotaPagedPoolUsage;publicreadonlyUIntPtrQuotaNonPagedPoolUsage;publicreadonlyUIntPtrPagefileUsage;publicreadonlyUIntPtrPeakPagefileUsage;publicreadonlyUIntPtrPrivatePageCount;publicSystemProcessInformation(){}publicSystemProcessInformation(refSYSTEM_PROCESS_INFORMATIONinfo){NumberOfThreads=info.NumberOfThreads;ImageName=Marshal.PtrToStringUni(info.ImageName.Buffer);BasePriority=info.BasePriority;UniqueProcessId=info.UniqueProcessId;HandleCount=info.HandleCount;SessionId=info.SessionId;PeakVirtualSize=info.PeakVirtualSize;VirtualSize=info.VirtualSize;PeakWorkingSetSize=info.PeakWorkingSetSize;WorkingSetSize=info.WorkingSetSize;QuotaPagedPoolUsage=info.QuotaPagedPoolUsage;QuotaNonPagedPoolUsage=info.QuotaNonPagedPoolUsage;PagefileUsage=info.PagefileUsage;PeakPagefileUsage=info.PeakPagefileUsage;PrivatePageCount=info.PrivatePageCount;}}staticvoidMain(){constintSTATUS_INFO_LENGTH_MISMATCH=unchecked((int)0xC0000004);// SystemProcessInformationのすべての情報を取得します。varbuffer=Array.Empty<byte>();for(;;){varstatus=NativeMethods.NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemProcessInformation,buffer,(uint)buffer.LongLength,outvarbufferLength);if(status!=STATUS_INFO_LENGTH_MISMATCH){if(status==0)break;thrownewNTStatusException(status);}Array.Resize(refbuffer,(int)bufferLength);}// SystemProcessInformationの情報を解析します。varinfos=newList<SystemProcessInformation>();varbufferHandle=GCHandle.Alloc(buffer,GCHandleType.Pinned);try{varaddress=bufferHandle.AddrOfPinnedObject();for(;;){// GCHandleの解放後はSYSTEM_PROCESS_INFORMATIONのImageNameの値が無効となるため、// 文字列をメモリから変数に保持するクラスへ変換します。varinfo=Marshal.PtrToStructure<SYSTEM_PROCESS_INFORMATION>(address);infos.Add(newSystemProcessInformation(refinfo));if(info.NextEntryOffset==0)break;address=IntPtr.Add(address,(int)info.NextEntryOffset);}}finally{bufferHandle.Free();}// TODO: ここでSystemProcessInformationの内容を処理します。foreach(varinfoininfos){Console.WriteLine($"{info.ImageName}, {info.UniqueProcessId}");}}}}
NTStatusUtility.cs
usingSystem;usingSystem.Runtime.InteropServices;namespaceConsoleApp1{publicstaticpartialclassNTStatusUtility{publicstaticboolIsSuccess(intstatus)=>status>=0;publicstaticboolIsInformation(intstatus)=>(status>>30)==1;publicstaticboolIsWarning(intstatus)=>(status>>30)==2;publicstaticboolIsError(intstatus)=>(status>>30)==3;publicstaticintHResultFromNTStatus(intstatus){constintFACILITY_NT_BIT=0x10000000;returnstatus|FACILITY_NT_BIT;}}publicsealedclassNTStatusException:COMException{publicNTStatusException():base(){status=0;}publicNTStatusException(intstatus):base(null,NTStatusUtility.HResultFromNTStatus(status)){status=status;}publicNTStatusException(stringmessage,intstatus):base(message,NTStatusUtility.HResultFromNTStatus(status)){status=status;}publicNTStatusException(stringmessage,Exceptioninner):base(message,inner){status=0;}publicNTStatusException(stringmessage):base(message){status=0;}privateintstatus;publicintStatus=>status;}}

Viewing all articles
Browse latest Browse all 9701

Trending Articles