서비스를 제공하다보면 서버의 트래픽이나 스토리지 용량이 초과해서 긴급하게 조치를 취하는 경우가 많습니다.
그래서 이런 사고를 미리 예방하고자 위험 수준에 다가가면 관리자에게 SMS로 알려주는 서버 자원 감시 프로그램을 WMI(Windows Manangement Instrumentation)를 이용하여 만들었습니다.
아직 많이 다듬어야 되지만 PC 자원 검사를 지원하는 기본적인 사용법의 예시는 될 수 있을 것 같습니다.
![[C#] WMI를 이용한 시스템 자원 검사 프로그램 예제 1 wmi-server-inspector](https://helloblog.net/wp-content/uploads/2018/11/wmi-server-inspector-e1541648966572.jpg)
Form1.cs
ManagementScope ms; string smsSendFilePath; //SMS Moudle [DllImport(@"C:\\Balsong32u.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] public static extern int Balsong_Mobile_CallBack(string id, string pw); [DllImport(@"C:\\Balsong32u.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] public static extern int Balsong_SMS(string id, string pw, string subject, string CallBack, string MSG_Text, string SendDate, string DataFile); public Form1() { InitializeComponent(); this.Location = new Point(this.Location.X, this.Location.Y + 5000); WMI wmi = new WMI(); ip = wmi.getLocalIP(); //로컬 PC 아이피로 WMI 정보 획득 (Get WMI Info.) ms = new ManagementScope("\\\\" + ip + "\\root\\cimv2"); smsSendFilePath = "C:\\SMS_Send_List.txt"; //Get Config File Info. //체크 인터벌 string CheckInterval = ConfigurationManager.AppSettings["CheckInterval"]; if (CheckInterval != "") appCheckInterval = Convert.ToInt32(CheckInterval); //디스크 사이즈 string DiskSize = ConfigurationManager.AppSettings["DiskSize"]; if (DiskSize != "") appDiskSize = Convert.ToInt32(DiskSize); //체크할 폴더 경로 string DirectoryName = ConfigurationManager.AppSettings["DirectoryName"]; if (DiskSize != "") appDirectoryName = DirectoryName; //CPU 점유율 string CPURating = ConfigurationManager.AppSettings["CPURating"]; if (CPURating != "") appCPURating = Convert.ToInt32(CPURating); //프로세스 이름 string ProcessName = ConfigurationManager.AppSettings["ProcessName"]; if (ProcessName != "") appProcessName = ProcessName; //프로세스 사용 메모리크기 string ProcessMemorySize = ConfigurationManager.AppSettings["ProcessMemorySize"]; if (ProcessMemorySize != "") appProcessMemorySize = Convert.ToInt32(ProcessMemorySize); //DB 데이터베이스 이름 string DataBaseName = ConfigurationManager.AppSettings["DataBaseName"]; if (DataBaseName != "") appDataBaseName = DataBaseName; //DB서버 아이피 string DataBaseIP = ConfigurationManager.AppSettings["DataBaseIP"]; if (DataBaseIP != "") appDataBaseIP = DataBaseIP; //DB서버 아이디 string DataBaseID = ConfigurationManager.AppSettings["DataBaseID"]; if (DataBaseID != "") appDataBaseID = DataBaseID; //DB서버 패스워드 string DataBasePassword = ConfigurationManager.AppSettings["DataBasePassword"]; if (DataBasePassword != "") appDataBasePassword = DataBasePassword; //SMS 접속 아이디 string SMSId = ConfigurationManager.AppSettings["SMSId"]; if (SMSId != "") appSMSId = SMSId; //SMS 접속 패스워드 string SMSPassword = ConfigurationManager.AppSettings["SMSPassword"]; if (SMSPassword != "") appSMSPassword = SMSPassword; //수신 폰번호 string HPNumber = ConfigurationManager.AppSettings["HPNumber"]; if (HPNumber != "") appHPNumber = HPNumber; this.Opacity = 0; this.ShowInTaskbar = false; } private void Form1_Load(object sender, EventArgs e) { string result = ""; //체크 인터벌 string CheckInterval = ConfigurationManager.AppSettings["CheckInterval"]; result += "체크 인터벌 : " + CheckInterval + " 초 \r\n"; //디스크 사이즈 string DiskSize = ConfigurationManager.AppSettings["DiskSize"]; result += "최대 디스크 사이즈 : " + DiskSize + " GB \r\n"; //체크할 폴더 경로 string DirectoryName = ConfigurationManager.AppSettings["DirectoryName"]; result += "체크 폴더 경로 : " + DirectoryName + " \r\n"; //CPU 점유율 string CPURating = ConfigurationManager.AppSettings["CPURating"]; result += "최대 CPU 점유율 : " + CPURating + " % \r\n"; //프로세스 이름 string ProcessName = ConfigurationManager.AppSettings["ProcessName"]; result += "체크 프로세스 이름 : " + ProcessName + " \r\n"; //프로세스 사용 메모리크기 string ProcessMemorySize = ConfigurationManager.AppSettings["ProcessMemorySize"]; result += "프로세스 메모리 : " + ProcessMemorySize + " MB \r\n"; //DB서버 아이피 string DataBaseIP = ConfigurationManager.AppSettings["DataBaseIP"]; result += "체크 DB 주소 : " + DataBaseIP + " \r\n"; //DB 데이터베이스 이름 string DataBaseName = ConfigurationManager.AppSettings["DataBaseName"]; result += "체크 DB이름 : " + DataBaseName + " \r\n"; //DB서버 아이디 string DataBaseID = ConfigurationManager.AppSettings["DataBaseID"]; result += "DB 접속 아이디 : " + DataBaseID + " \r\n"; //DB서버 패스워드 string DataBasePassword = ConfigurationManager.AppSettings["DataBasePassword"]; result += "DB 접속 패스워드 : " + DataBasePassword + " \r\n"; //SMS 접속 아이디 string SMSId = ConfigurationManager.AppSettings["SMSId"]; result += "SMS 접속 아이디 : " + SMSId + " \r\n"; //SMS 접속 패스워드 string SMSPassword = ConfigurationManager.AppSettings["SMSPassword"]; result += "SMS 접속 패스워드 : " + SMSPassword + " \r\n"; //수신 폰번호 string HPNumber = ConfigurationManager.AppSettings["HPNumber"]; result += "SMS 수신 핸드폰번호: " + HPNumber + " \r\n"; textBox.Text = result; timer1.Interval = appCheckInterval * 1000; timer1.Start(); } //Timer Loop private void timer1_Tick(object sender, EventArgs e) { WMI wmi = new WMI(); string msg = ""; try { //디스크 용량 체크 (Storage Size Check) if (appDiskSize > 0) { string result = wmi.getDriveSize(ref ms, appDiskSize); if (result != "") { msg += result; } } //폴더체크 (Directory Check) if (appDirectoryName != null && appDirectoryName != "") { if (!wmi.getIsExistFolder(appDirectoryName)) msg += appDirectoryName + " 폴더가 존재하지 않습니다."; } //CPU 점유율 (Cpu Memory Check) if (appCPURating > 0) { double ret = wmi.getCPUPerformance(ref ms); if (appCPURating <= ret) msg += "CPU 점유율이 초과되고 있습니다."; } //프로세스검사 (Process Check) if (appProcessName != null && appProcessName != "") { if (wmi.IsExistProcess(appProcessName.Replace(".exe", ""))) { double ret = wmi.getProcessPerformace(ref ms, appProcessName); if (appProcessMemorySize <= ret) msg += appProcessName + " 의 메모리 점유율이 초과되고 있습니다."; } else { msg += appProcessName + "프로세스가 활성화 되지 않았습니다."; } } //DB체크 (DB Check) if (appDataBaseName != null && appDataBaseName != "") { if (!wmi.IsExistDatabase(appDataBaseIP, appDataBaseName, appDataBaseID, appDataBasePassword)) msg += "(" + appDataBaseIP + ") DB " + appDataBaseName + " 가 접속불가 상태입니다."; } //핸드폰 번호와 발송메세지가 있을때 if (appHPNumber != null && appHPNumber != "" && msg != "") { int smsRet = 0; msg = "IP " + ip + " " + msg; FileInfo fi = new FileInfo(smsSendFilePath); if (appHPNumber.IndexOf(',') > 0) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(smsSendFilePath, false, Encoding.Default)) { foreach (var hpNumber in appHPNumber.Split(',')) { file.WriteLine("서버상태" + "\t" + "서버상태" + "\t" + hpNumber.Replace("-", "") + "\t" + msg); } file.Close(); } } else { File.WriteAllText(smsSendFilePath, "서버상태" + "\t" + "서버상태" + "\t" + appHPNumber.Replace("-", "") + "\t" + msg, Encoding.Default); } //경고메세지 SMS 발송 (SMS Sand..) smsRet = Balsong_Mobile_CallBack(appSMSId, appSMSPassword); smsRet = Balsong_SMS(appSMSId, appSMSPassword, "서버상태", "0519667000", " ", "", smsSendFilePath); Application.Exit(); } } catch (Exception ex) { MessageBox.Show("시스템 검사중 오류가 발생했습니다." + ex.ToString()); } } } }
WMI.cs
namespace ServerAlarm { class WMI { ManagementObjectSearcher query; ManagementObjectCollection queryCollection = null; ObjectQuery oq; ConnectionOptions co; /// /// 로컬서버 아이피 조회 (IP Check) /// /// 아이피 정보 public string getLocalIP() { IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName()); string ClientIP = string.Empty; try { for (int i = 0; i < host.AddressList.Length; i++) { if (host.AddressList[i].AddressFamily == AddressFamily.InterNetwork) { ClientIP = host.AddressList[i].ToString(); } } } catch { } return ClientIP; } /// /// 드라이브 크기 체크 (Storage Size Check) /// ///Management ///최소사이즈(GB) /// 체크 결과 public string getDriveSize(ref ManagementScope ms, int minSize) { string result = ""; try { string drive = ""; double freespace = 0.0; ManagementObjectCollection queryCollection = getDrives(ref ms); foreach (ManagementObject mo in queryCollection) { if (mo["DriveType"].ToString().Equals("3")) //하드드라이브만 검색 { drive = mo["Name"].ToString(); freespace = double.Parse(mo["FreeSpace"].ToString()); // 컬렉션으로부터 Freesize를 들고옴 if (minSize >= ((freespace / 1024) / 1024) / 1024) result += drive + " 용량이 부족합니다.\r\n"; } } } catch { } return result; } /// /// 폴더 체크 (Directory Check) /// ///경로 /// 결과값 public bool getIsExistFolder(string folderPath) { DirectoryInfo dir = new DirectoryInfo(folderPath); if (dir.Exists) return true; else return false; } /// /// CPU점유율을 계산 (CPU per Process Check) /// /// 점유율 % public double getCPUPerformance(ref ManagementScope ms) { double CurrentCPU = 0; try { // CPU의 PercentProcessorTime 을 컬렉션에 담음 ManagementObjectCollection queryCollection = this.getServiceCollection(ref ms, "SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'"); foreach (ManagementObject mo in queryCollection) { CurrentCPU = Convert.ToDouble(ulong.Parse(mo["PercentProcessorTime"].ToString())); //%로 계산 } } catch { } return CurrentCPU; } /// /// 프로세스 존재여부 확인 (Process Exist Check) /// ///프로세스이름 /// public bool IsExistProcess(string ProcessName) { Process[] processList = Process.GetProcessesByName(ProcessName); if (processList.Length < 1) return false; else return true; } /// /// 프로세스당 메모리 사용량 계산 (Process Memory Check) /// ///계산할 프로세스 이름 /// 해당 프로세스 메모리 용량 public double getProcessPerformace(ref ManagementScope ms, string ProcessName) { double CurrentPorcess = 0; try { Process[] processes = Process.GetProcessesByName("excel"); if (processes.Count() > 0) { Process process = processes[0]; CurrentPorcess = process.VirtualMemorySize64; CurrentPorcess = CurrentPorcess / (1024f * 1024f); } } catch { } return CurrentPorcess / 1024; } /// /// DB 접속 체크 (DB Connection Check) /// ///DB 이름 /// 결과값 public bool IsExistDatabase(string DataBaseIP, string DataBaseName, string DataBaseID,string DataBasePassword) { string connectionString = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3}",DataBaseIP, DataBaseName, DataBaseID, DataBasePassword); string sqlCreateDBQuery; bool result = false; try { SqlConnection tmpConn = new SqlConnection(connectionString); SqlDataReader reader; sqlCreateDBQuery = string.Format("SELECT database_id FROM sys.databases WHERE Name = '{0}'", DataBaseName); using (tmpConn) { using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn)) { tmpConn.Open(); reader = sqlCmd.ExecuteReader(); if (reader.HasRows) result = true; tmpConn.Close(); } } } catch (Exception ex) { result = false; } return result; } //드라이브 정보를 가져오기 위한 쿼리(Storage Info.) private ManagementObjectCollection getDrives(ref ManagementScope ms) { ManagementObjectCollection queryCollection = this.getServiceCollection(ref ms, "SELECT * FROM Win32_LogicalDisk"); return queryCollection; } //쿼리를 가지고 해당 서버에서 가져오고자 하는 데이터를 Collection에 담아옴 private ManagementObjectCollection getServiceCollection(ref ManagementScope ms, string stringQuery) { oq = new ObjectQuery(stringQuery); query = new ManagementObjectSearcher(ms, oq); try { queryCollection = query.Get(); } catch (Exception ex) { } return queryCollection; } } }
WMI의 자세한 내용은 마이크로 소프트 개발자 센터에서 참고 할 수 있습니다.