public new void Kill() { using (var hProcess = SafeProcessHandle.OpenProcess(SafeProcessHandle.ProcessAccessFlags.Terminate, false, Id)) { if (hProcess.IsInvalid) { var error = Marshal.GetLastWin32Error(); _debugLogger.Error("AsyncImpersonationProcess ({0}): Cannot kill proces; OpenProcess failed. ErrorCode: {1} ({2})", StartInfo.FileName, error, new Win32Exception(error).Message); return; } if (!TerminateProcess(hProcess, EXITCODE_OK)) { var error = Marshal.GetLastWin32Error(); _debugLogger.Error("AsyncImpersonationProcess ({0}): Cannot kill proces; TerminateProcess failed. ErrorCode: {1} ({2})", StartInfo.FileName, error, new Win32Exception(error).Message); } } }
/// <summary> /// Инициализация информации о модулях /// </summary> /// <param name="mainModuleName">главный модуль симулятора (fs9.exe)</param> /// <returns>true - simulator was found</returns> public InitializationState Initialize(string mainModuleName) { const string systemName = "MemoryPatcher"; // Без этого процессор грузится на 50%, пока симулятор не загружен if (DateTime.Now < _lastTimeTryToInitialize + new TimeSpan(0, 0, 0, 2)) { if (_lastInitStatus != null) { return(_lastInitStatus); } return(new InitializationState { System = systemName, ErrorCode = (int)InitializationStatus.AttemptToInitializeTooOften, ErrorMessage = "Attempted to initialize too often", IsOk = false }); } _lastTimeTryToInitialize = DateTime.Now; try { lock (_modules) { _modules.Clear(); var runningProcesses = Process.GetProcesses(); var processesWithCorrectName = runningProcesses.Where(x => x.ProcessName.ToLower() == mainModuleName.ToLower()); if (processesWithCorrectName.Count() == 0) { _lastInitStatus = new InitializationState { System = systemName, ErrorCode = (int)InitializationStatus.ModuleToPatchWasNotFound, ErrorMessage = "Module '" + mainModuleName + "' was not found in process list", IsOk = false }; return(_lastInitStatus); } if (processesWithCorrectName.Count() > 1) { _lastInitStatus = new InitializationState { System = systemName, ErrorCode = (int)InitializationStatus.MultipleModulesFound, ErrorMessage = "Multiple modules with name '" + mainModuleName + "' were found, don't know how to select correct one", IsOk = false }; return(_lastInitStatus); } var process = processesWithCorrectName.First(); _mainModuleProcessId = process.Id; _processHandle = SafeProcessHandle.OpenProcess(ProcessAccessFlags.VmOperation | ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VmRead | ProcessAccessFlags.VmWrite, false, _mainModuleProcessId); for (var i = 0; i < process.Modules.Count; i++) { var info = new ModuleInfo { BaseAddress = process.Modules[i].BaseAddress, Size = (uint)process.Modules[i].ModuleMemorySize, Name = process.Modules[i].ModuleName }; if (!_modules.ContainsKey(info.Name)) { _modules.Add(info.Name, info); } } process.Close(); _lastInitStatus = new InitializationState { System = systemName, ErrorCode = (int)InitializationStatus.Ok, ErrorMessage = "", IsOk = true }; return(_lastInitStatus); } } catch (Exception ex) { _lastInitStatus = new InitializationState { System = systemName, ErrorCode = (int)InitializationStatus.Exception, ErrorMessage = "An exception occuted: " + ex.Message, IsOk = false }; return(_lastInitStatus); } }
private void TimerCallback(object state) { try { // Get process handles. var process = Process.GetCurrentProcess(); var pid = process.Id; var handle1 = process.Handle; if (!_initialEmptyComplete) { // The first time through, empty the working set and return. _initialEmptyComplete = true; NativeMethods.EmptyWorkingSet(handle1); return; } // Get memory usage. var safeHandle = SafeProcessHandle.OpenProcess(pid, ProcessAccessFlags.QueryInformation); var handle2 = safeHandle.DangerousGetHandle(); var counters = new PROCESS_MEMORY_COUNTERS(); NativeMethods.GetProcessMemoryInfo(handle2, out counters, (uint)Marshal.SizeOf(counters)); var workingSetSize = counters.WorkingSetSize / 1024 / 1024; if (workingSetSize < _mediumThreshold) { // We're below the medium threshold, nothing to do. return; } if (workingSetSize < _highThreshold) { // We're above the medium threshold and below the high threshold. Get the // time since the last empty and bail if it was less than 10 minutes ago. var timeSinceLastEmpty = TimeSpan.FromTicks( Stopwatch.GetTimestamp() - _lastEmptyTimestamp); if (timeSinceLastEmpty < TimeSpan.FromMinutes(10)) { return; } } // Empty the working set. NativeMethods.EmptyWorkingSet(handle1); _lastEmptyTimestamp = Stopwatch.GetTimestamp(); // Get updated memory usage. NativeMethods.GetProcessMemoryInfo(handle2, out counters, (uint)Marshal.SizeOf(counters)); // Record the operation in the log. var newWorkingSetSize = counters.WorkingSetSize / 1024 / 1024; var highUsageDetected = workingSetSize > _highThreshold; Logger.Info( "{0} memory threshold ({1}MB) exceeded - working set reduced from: {2} to: {3}", highUsageDetected ? "High" : "Medium", highUsageDetected ? _highThreshold : _mediumThreshold, workingSetSize, newWorkingSetSize); } catch (Exception e) { Logger.Error("Error monitoring working set size", e); } finally { Thread.MemoryBarrier(); if (!_disposed) { _timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromMilliseconds(-1)); } } }