Что-то я сильно разленился
До такой степени разленился, что мне стало лень изменять приоритет процесса используя стандартный диспетчер процессов.
Только думайте что пишу какой-то бред, сейчас все объясню.
Иногда занимаюсь обработкой видео. Делаю небольшие клипы наших велопоездок. Каждый раз, когда запускаю кодирование видео, захожу в диспетчер процессов и увеличиваю приоритет процесса кодирования. Чтобы ускорить обработку (ускоряет кстати неплохо). А после завершения кодирования опять захожу в диспетчер и уменьшаю приоритет.
Казалось бы что тут такого, но на это небольшое действие теряется время (а время дорого стоит) - найти процесс в списке, щелкнуть мышкой, выбрать нужный приоритет, подтвердить изменение.
Учитывая, что выше описанную процедуру я повторяю по несколько раз, было принято решение написать программу, которая упростит эти действия. Что собственно я и сделал. За 15-20 минут написал.
А теперь к сути статьи.
На примере моей небольшой программки (написаной на делфи) я хочу рассказать о том как правильно писать программы.
Но я буду писать не о программных алгоритмах, не о красивом коде и тому подобным вещам(хотя и это затрону немного), я буду писать о оптимальном(ИМХО) подходе человека к выполнению поставленного задания. Начнем
Часть первая. Техническое задание.
Начать надо именно с технического задания (сокращенно тз). По сути это самый важный момент. От того насколько правильно и точно составить тз зависит весь последующий процесс. Само тз лучше написать на бумаге и держать всегда под рукой, время от времени в него поглядывать. Писать надо подробно и точно, дабы потом не думать "а что я имел ввиду под этой фразой".
Вы можете подумать, что для мелких проектов, где только один разработчик или где программа пишется только для себя тз не нужно, но как показывает практика - нужно. На работе я сталкивался с подобными случаями, из за отсутствия тз (или из за его неточного составления) огромные части программы переписывались по несколько раз, доходило даже до удаления проекта и создания всего с нуля. Это все потеря времени которая никому не нужна, поэтому надо писать четкое тз.
Первым делом в тз надо описать требуемый функционал. Чем подробнее, тем лучше. Не надо думать о способе реализации, это будет позднее, надо во всех подробностях написать что должно делать конечное приложение.
После функционала желательно придумать оптимальный/удобный/красивый интерфейс, в котором можно реализовать описанный ранее функционал.
Также можно написать и список других требований.
Тз для моей программки оказалось небольшим.
Что программа должна делать? Изменять приоритет процесса.
Какой интерфейс у нее должен быть? Минимальный. Программа должна проверить приоритет процесса и спросить изменять его или нет.
Какие дополнительные требования? Минимальные затраты ресурсов компьютера и количество кликов для изменения приоритета должно быть меньше чем в стандартном диспетчере процессов.
Часть вторая. Изучение теории и разработка алгоритма.
Без теории и практики не будет. Можно конечно пытаться что-то делать не понимая что, можно даже добиться требуемых результатов. Но это не оптимально. Лучше всего изучить теорию, потратить не это время, разобраться во всем и после этого продолжить работу. Даже если это займет намного больше времени, чем поиск готового кода в инете. Знания еще никому не помешали. Есть большая вероятность, что выученная информация пригодится не только в вашем конкретном проекте, но и каком-то проекте в будущем.
По мере изучения теоретической части у нас в голове и на бумаге (или компе) должен формироваться алгоритм (или части алгоритма) работы программы. Записывать не только желательно, но и обязательно, не стоит доверять памяти.
Какая теория в моей небольшой программке? Сложная теория, но мне повезло и я уже ранее сталкивался с подобным и уже почти все знал (это как раз тот случай, когда выученная ранее теория пригодилась в будущем).
Я уже примерно представлял принцип ее работы. Я знал, что для какого либо взаимодействия с процессом нужно узнать его PID. Также я знал наиболее оптимальный способ поиска (tlhelp32). И это не тот способ, который находиться в гугле на первых страницах (как раз тот случай, когда лучше понимать теории, а не использовать готовый, но не понятный код).
Чего я не знал, так это алгоритма изменения приоритета, но без трудов нашел в спецификации функцию из kernel32 для изменения приоритета процесса (SetPriorityClass) и рядом с ней функцию для определения текущего приоритета (GetPriorityClass).
Одним из требований в тз было минимальное использование ресурсов компьютера и я решил что меньше всего ресурсов использует программа, которая не запущена.
После этого я нарисовал минимальную блок схему программы. Собственно вот она:
[Ссылки могут видеть только зарегистрированные пользователи. ]
Часть третья. Разработка подробного алгоритма.
Казалось бы, зачем что-то еще делать, можно уже начинать писать код. Но нет
Надо разработать подробный алгоритм работы программы. Конкретно определится с способами реализации тех или иных задач. Определится для каких задач желательно создавать функции/процедуры или объявлять методы. Какие создавать классы, какие объявлять переменные. Придумать где и как хранить данные. Если планируется использование БД, то сразу же подробно описать ее структуру и поля. Решить какие настройки/параметры хранить в реестре, какие в ини файле или в облачном хранилище, а какие выгружать при закрытии программы. Короче чем подробнее все продумать, тем проще и быстрее пройдет написание кода.
Для моей мелкой программы эта часть прошла незаметно. Я сразу определился, что надо создать 3 функции (поиск PID процесса по его имени, определение текущего приоритета процесса, изменение приоритета процесса) и что весь интерфейс взаимодействия с пользователем будет средствами стандартного окна MessageDlg.
Даже расписывать ничего не стал, но в принципе, для больших проектов желательно все записывать.
Часть четвертая. Написание программы.
Добрались таки
Переходим наконец к написанию кода. Создаем новый проект. Выставляем все нужные настройки. Создаем модули и кодим.
Я создал пустое приложение (без формы, типа консольного). Написал функцию определения PID процесса.
Код:
function GetProcessId(pName: PChar): DWORD;
var
hSnap: THandle;
pe: TProcessEntry32;
begin
Result := 0;
pe.dwSize := SizeOf(pe);
hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
If Process32First(hSnap, pe) then
While Process32Next(hSnap, pe) do
if lstrcmpi(pe.szExeFile, pName) = 0 then
Result := pe.th32ProcessID;
end;
Написал функции для определения и изменения приоритета процесса:
Код:
function GetPriority(ExeName: string): Cardinal;
var
q: Cardinal;
begin
q := openprocess(PROCESS_QUERY_INFORMATION, false,
GetProcessId(PChar(ExeName)));
Result := GetPriorityClass(q);
CloseHandle(q);
end;
function SetPriority(ExeName: string; PRIORITY_CLASS: Cardinal): boolean;
var
q: Cardinal;
begin
q := openprocess(PROCESS_SET_INFORMATION, false,
GetProcessId(PChar(ExeName)));
Result := SetPriorityClass(q, PRIORITY_CLASS);
CloseHandle(q);
end;
Подключил требуемые модули (это все что используются, у меня же не будет формы и тому подобных вещей):
Описал все переменных (аж 1 шт. - имя процесса приоритет которого собираемся менять):
Код:
const
Name = 'container.exe';
И перешел к написанию главного блока программы. Так как у меня возможны 3 ситуации (процесс с приоритетом Средний, процесс с приоритетом Высокий, процесс не запущен) использовал оператор case. Вот что получилось:
Код:
begin
case GetPriority(name) of
32:
begin
if MessageDlg('Пріоритет процесу - Середній.' + #13 + #10 +
'Збільшити пріоритет?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
SetPriority(name, 128);
end;
128:
begin
if MessageDlg('Пріоритет процесу - Високий.' + #13 + #10 +
'Зменшити пріоритет?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
SetPriority(name, 32);
end;
0:
begin
ShowMessage('Процес не знайдено.');
end;
end;
end.
Программа запустилась и заработала с первого раза. Комментариев в коде у меня нету, но в принципе неплохо их оставлять.Лишними не будут.
Переходим к последней части.
Часть пятая. Проверка программы.
Последний этап. Проверка программы сложный и нужный процесс. Сначала надо проверить работоспособность всех пунктов указанных в тз. После этого проверить все исключительные ситуации, вообще все, даже те которые возникнуть в теории не могут, если их не проверить, то они по законам подлости возникнут
Желательно, по возможности, попробовать оптимизировать код, украсить его комментариями.
Свою программу я проверил быстро. Нужный функционал работает. При проверке исключительных ситуаций нашел недоработку (программа работает в холостую если приоритет процесса не высокий и не средний), но исправлять этого не стал.
Также появилась идея передавать программе имя процесса как параметр командной строки, а то изначально имя задавалось в коде и изменять его, без компиляции, не было возможности. Идею воплотил в жизнь.
В результате у меня получилась маленькая и быстрая программа, которая выполняет все возложенные на нее задачи. В редакторе видео, на панели инструментов я добавил кнопку, при нажатии на которую запускается моя программа и изменяет приоритет процесса. Два клика мышкой вместо четырех, я крутой оптимизатор
program Project1;
uses
Winapi.Windows,
tlhelp32,
Vcl.Dialogs,
Vcl.Controls,
ShellAPI;
{$R *.res}
var
Name: string;
function GetProcessId(pName: PChar): DWORD;
var
hSnap: THandle;
pe: TProcessEntry32;
begin
Result := 0;
pe.dwSize := SizeOf(pe);
hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
If Process32First(hSnap, pe) then
While Process32Next(hSnap, pe) do
if lstrcmpi(pe.szExeFile, pName) = 0 then
Result := pe.th32ProcessID;
end;
function GetPriority(ExeName: string): Cardinal;
var
q: Cardinal;
begin
q := openprocess(PROCESS_QUERY_INFORMATION, false,
GetProcessId(PChar(ExeName)));
Result := GetPriorityClass(q);
CloseHandle(q);
end;
function SetPriority(ExeName: string; PRIORITY_CLASS: Cardinal): boolean;
var
q: Cardinal;
begin
q := openprocess(PROCESS_SET_INFORMATION, false,
GetProcessId(PChar(ExeName)));
Result := SetPriorityClass(q, PRIORITY_CLASS);
CloseHandle(q);
end;
begin
// Коди пріоритетів процесу О_о
// 64 - низький
// 16384 - нижче середнього
// 32 - середній
// 32768 - вище середнього
// 128 - високий
// 256 - реального часу
if ParamCount > 0 then
begin
name := ParamStr(1);
case GetPriority(name) of
32:
begin
if MessageDlg('Пріоритет процесу - Середній.' + #13 + #10 +
'Збільшити пріоритет?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
then
SetPriority(name, 128);
end;
128:
begin
if MessageDlg('Пріоритет процесу - Високий.' + #13 + #10 +
'Зменшити пріоритет?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
then
SetPriority(name, 32);
end;
0:
begin
ShowMessage('Процес не знайдено.');
end;
end;
end
else
ShowMessage('Вкажіть ім''я процессу.');
end.
Часть шестая. Заключение.
Надеюсь что моя статья окажется вам более полезной чем программа взятая для примера. Также надеюсь что вы возьмете ее на заметку и она хоть немного упростит вам жизнь.
Всем котиков
[Ссылки могут видеть только зарегистрированные пользователи. ]
________________
В любом из нас спит гений. И с каждым днем все крепче.
Запомните раз и навсегда:= 'Помочь' <> 'Сделайте за меня';