MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как проверить является ли процесс системным?"
Answer 758249
Если приложение запускается с правами администратора, можно воспользоваться Restart Manager API:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; using System.Text; using System.Diagnostics; using System.Windows.Forms; namespace WindowsFormsTest1 { public partial class Form1 : Form { [DllImport("Rstrtmgr.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)] public static extern UInt32 RmStartSession(out UInt32 pSessionHandle, UInt32 dwSessionFlags, string strSessionKey); [DllImport("Rstrtmgr.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)] public static extern UInt32 RmRegisterResources(UInt32 dwSessionHandle, UInt32 nFiles, string[] rgsFilenames, UInt32 nApplications, ref RM_UNIQUE_PROCESS rgApplications, UInt32 nServices, string[] rgsServiceNames); [DllImport("Rstrtmgr.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)] public static extern UInt32 RmGetList(UInt32 dwSessionHandle, out UInt32 pnProcInfoNeeded, ref UInt32 pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref UInt32 lpdwRebootReasons); [DllImport("Rstrtmgr.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)] public static extern UInt32 RmEndSession(UInt32 dwSessionHandle); public const UInt32 RmRebootReasonNone = 0x0; public const int ERROR_MORE_DATA = 234; /// <summary> /// Преобразование DateTime в структуру FILETIME /// </summary> public static System.Runtime.InteropServices.ComTypes.FILETIME FileTimeFromDateTime(DateTime date) { long ftime = date.ToFileTime(); System.Runtime.InteropServices.ComTypes.FILETIME ft = new System.Runtime.InteropServices.ComTypes.FILETIME(); ft.dwHighDateTime = (int)(ftime >> 32); ft.dwLowDateTime = (int)ftime; return ft; } /// <summary> /// Получение типа процесса /// </summary> public static RM_APP_TYPE GetProcessType(Process proc) { uint handle; string key = Guid.NewGuid().ToString(); uint res = RmStartSession(out handle, (uint)0, key); if (res != 0) { throw new ApplicationException("Could not begin restart session. "); } try { uint pnProcInfoNeeded = 0, pnProcInfo = 0, lpdwRebootReasons = RmRebootReasonNone; RM_UNIQUE_PROCESS uniqueprocess = new RM_UNIQUE_PROCESS(); uniqueprocess.dwProcessId = proc.Id; System.Runtime.InteropServices.ComTypes.FILETIME ft = FileTimeFromDateTime(proc.StartTime); uniqueprocess.ProcessStartTime = ft; res = RmRegisterResources(handle, 0, null, 1, ref uniqueprocess, 0, null); if (res != 0) { throw new ApplicationException("Could not register resource."); } res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons); if (res == ERROR_MORE_DATA) { RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; pnProcInfo = pnProcInfoNeeded; // Get the list. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons); if (res == 0) { if (pnProcInfo == 0) throw new ApplicationException("Process not found"); return processInfo[0].ApplicationType; } else { throw new ApplicationException("Could not list processes"); } } else if (res != 0) { throw new ApplicationException("Failed to get size of result."); } } finally { RmEndSession(handle); } throw new ApplicationException("Process not found"); } public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //пример использования Process p=Process.GetProcessesByName(textBox1.Text)[0]; MessageBox.Show(GetProcessType(p).ToString()); /*Для системных процессов выведет RmCritical*/ } } /* Определения структур */ [StructLayout(LayoutKind.Sequential)] public struct RM_UNIQUE_PROCESS { // The product identifier (PID). public int dwProcessId; // The creation time of the process. public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct RM_PROCESS_INFO { const int CCH_RM_MAX_APP_NAME = 255; const int CCH_RM_MAX_SVC_NAME = 63; // Contains an RM_UNIQUE_PROCESS structure that uniquely identifies the // application by its PID and the time the process began. public RM_UNIQUE_PROCESS Process; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)] // If the process is a service, this parameter returns the // long name for the service. public string strAppName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] // If the process is a service, this is the short name for the service. public string strServiceShortName; // Contains an RM_APP_TYPE enumeration value. public RM_APP_TYPE ApplicationType; // Contains a bit mask that describes the current status of the application. public uint AppStatus; // Contains the Terminal Services session ID of the process. public uint TSSessionId; // TRUE if the application can be restarted by the // Restart Manager; otherwise, FALSE. [MarshalAs(UnmanagedType.Bool)] public bool bRestartable; } public enum RM_APP_TYPE { // The application cannot be classified as any other type. RmUnknownApp = 0, // A Windows application run as a stand-alone process that // displays a top-level window. RmMainWindow = 1, // A Windows application that does not run as a stand-alone // process and does not display a top-level window. RmOtherWindow = 2, // The application is a Windows service. RmService = 3, // The application is Windows Explorer. RmExplorer = 4, // The application is a stand-alone console application. RmConsole = 5, // A system restart is required to complete the installation because // a process cannot be shut down. RmCritical = 1000 } }
Код основан на данном примере: https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4
Метод
GetProcessType
возвращает тип процесса, для системных процессов он равен значениюRM_APP_TYPE.RmCritical
.Если приложение не имеет прав администратора, все проще: попытка получить дескриптор системного процесса просто упадет с ошибкой "Отказано в доступе". Нужно лишь ловить
Win32Exception
.
Другие способы
С использованием (нерекомендуемой) функции NtQueryInformationProcess из Native API:
const uint ProcessBreakOnTermination = 29; [DllImport("NTDLL.DLL")] static extern int NtQueryInformationProcess(IntPtr hProcess, uint pic, ref uint pi, int cb, out int pSize); public static bool IsProcessCritical(Process pr) { uint val = 0; int size; int res = NtQueryInformationProcess(pr.Handle, ProcessBreakOnTermination, ref val, sizeof(uint), out size); if (res != 0 || size != sizeof(uint)) throw new Win32Exception("NtQueryInformationProcess failed"); return (val != 0); }
Начиная с Windows 8.1 можно использовать функцию IsProcessCritical - пример.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.