Исправление ошибок

Программа позволяет в автоматическом режиме устранить имеющиеся ошибки планировщика заданий, а если это не удастся — следует перейти в раздел с перечнем всех ошибок, который располагается в меню сайта.
Отыскав в этом разделе описание своей ошибки — следуйте инструкциям, чтобы исправить ее вручную.
Открыв планировщик заданий что отключить, вы сможете выбрать на свое усмотрение — закрыв ненужные задачи, замедляющие работу компьютера, тем самым проведя своеобразную оптимизацию Windows.
Нужно снова открыть окно планировщика и выбрать в левом разделе его библиотеку.
В среднем разделе данного окна будут отображаться все работающие задачи.
Вам останется лишь выбрать по вашему усмотрению — и, перейдя в разделе действий к параметрам элемента, кликнуть по пункту «Удалить».

Удаление выбранной задачи
После этого окно планировщика можно закрыть.
Получение кода для анализа
К сожалению, получить текст кода ядра для анализа не так-то просто. Т.е. ядро ntoskrnl.exe невозможно просто загрузить в память с помощью какого-нибудь ntsd или windbg. Конечно, есть и специальные средства, и отладочные версии, и виртуальные машины, но в данном случае хотелось бы получить просто ассемблерный код как текст, который можно даже хотя бы частично распечатать и спокойно анализировать «за столом». Для этой цели проще создать небольшую программу (я назвал ее sd.exe) самому. Поскольку в используемых мною средствах есть встроенный отладчик, легко написать небольшую программу, просто загружающую файл ntoskrnl в память и затем сдвигающую на нужную величину каждую секцию, перечисленную в таблице заголовка exe-файла. Выполнив эти действия, программа останавливается в контрольной точке (т.е. на команде INT 3). В результате в памяти получается правильно «развернутый» образ ядра из ntoskrnl, который теперь можно вывести на экран или в файл командами «U» и «D» встроенного интерактивного отладчика. Сложность такого дизассемблирования в том, что команды и данные идут вперемежку, и если весь файл вывести как команды, данные выведутся как набор бессмысленных команд, часто портящих начало участков настоящих команд. Приходится предварительно все просматривать на экране как данные и на глаз определять очередные границы команд и данных. Результаты просмотра оформляются в виде текста как последовательность команд «U» и «D» для будущего получения «распечатки»:
Кстати, найденный адрес 409150 исключения INT 0D «нарушение общей защиты» еще пригодится далее.
Теперь если отладчик выполнит последовательность команд «U» и «D», получается текст вот такого, уже более правильного вида:
Таким образом, команды отделяются от данных. Всю последовательность команд для отладчика я записал в файл ud.txt и одной командой:
получил первый вариант кода ядра в текстовом файле ntos.txt. Этот вариант еще достаточно «слепой». Однако теперь уже несложно создать еще одну небольшую программу, которая обработает полученный результат, добавляя в текст названия импортируемых процедур, используя таблицу импорта исходного exe-файла, а также расставит метки по тексту, используя адреса таблицы экспортируемых функций. Кроме этого, программа вставляет всякие удобные мелочи вроде пустой строки после каждой команды RET, чтобы легче читать анализируемые участки и т.д.
Самое главное, что теперь в этом большом (26 Мбайт) текстовом файле легко искать нужный контекст, например, переход на заданный адрес. А значит, можно приступать собственно к анализу кода ядра.
Постановка задачи
Конкретизируем задачу. Требуется проанализировать код ядра Windows в части переключения с одного потока на другой. Нужно убедиться, что никаких других случаев переключения, кроме трех перечисленных, в ядре нет. Используя результаты анализа и знание конкретного кода, переключающего потоки, требуется организовать работу планировщика так, чтобы заданный поток в течение 20-30 минут не прерывался потоками с более низким приоритетом (из-за работы диспетчера баланса), но при этом не обладал приоритетом «реального времени» и поэтому не мешал различным высокоприоритетным служебным потокам и сервисам.
Как создать задание планировщика с помощью PowerShell?
В современных версиях PowerShell (начиная с PowerShell 3.0 в Windows Server 2012/Windows 8) для создания заданию планировщика нужно использовать командлеты New-ScheduledTaskTrigger и Register-ScheduledTask.
Предположим, наша задача создать задание планировщика, которое должно запускаться при загрузке компьютера (или в определенное время) и выполнять какой-то PowerShell скрипт. Создадим задание планировщика с именем StartupScript_PS. Данное задание должно каждый день в 10:00 запускать PowerShell скрипт, хранящийся в файле C:PSStartupScript.ps1 из-под учетной записи системы (SYSTEM). Задание будет выполняться с повышенными привилегиями (галка “Run with highest privileges”).
Если задание успешно создано, появится надпись Ready.

Теперь ваш PowerShell скрипт будет запускаться по указанному расписанию. Если на вашем компьютере настроена PowerShell Execution Policy, блокирующая запуск скриптов PS1, вы можете запустить скрипт их планировщика с параметром –Bypass.
Используйте такую строку при создании нового задания:
$Action= New-ScheduledTaskAction -Execute “PowerShell.exe” -Argument “-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File C:PSStartupScript.ps1″
Совет. Если нужно, чтобы задание запускалось каждый раз при загрузке компьютера, первая строка должна быть такой:
$Trigger= New-ScheduledTaskTrigger -AtStartup
Если нужно выполнять задание при входе пользователя:
$Trigger= New-ScheduledTaskTrigger –AtLogo
n
Откройте консоль
Taskschd.msc
и проверьте, что проверьте, что в Task Scheduler Library появилось новое задание планировщика.

В версии Powershell 2.0 (Windows 7, Windows Server 2008 R2) для создания повторяющегося задания (ScheduledJob) из PowerShell необходимо воспользоваться COM интерфейсом Schedule.Service (либо обновите версию PowerShell). В этом примере мы создадим задание планировщика, которое во время запускает определённый файл с PowerShell скриптом во время загруки. Задание выполняется с правами системы (System).
$rootFolder = $service.GetFolder(“”)$TaskDefinition = $service.NewTask(0)$TaskDefinition.RegistrationInfo.Description = “$TaskDescription”$TaskDefinition.Settings.Enabled = $true$TaskDefinition.Settings.AllowDemandStart = $true$triggers = $TaskDefinition.Triggers#http://msdn.microsoft.com/en-us/library/windows/desktop/aa383915(v=vs.85).aspx$trigger = $triggers.Create(8)
Отключение «Планировщика заданий»
Иногда бывает так, что из-за неправильно настроенного «Планировщика» возникают какие-то проблемы в работе ОС, если вы не нашли, в чем именно причина, – можно отключить его совсем (данная функция не поддерживается некоторыми сборками Windows).
- Найдите ярлык «Этот компьютер». Если его нет в Desktop, нажмите «Проводник» (значок в виде желтой папки), и вы увидите его в списке слева.
- Кликните вспомогательной кнопкой мыши (она справа) и выберите «Управление» — «Планировщик заданий» — «Действие» — «Свойства».
- В таблице видно, что в настоящее время приложение функционирует. Нажмите «Стоп» и укажите тип запуска – «Отключено». Таким образом, при очередном включении компьютера эта служба работать не будет.
Перед тем, как отключить «Планировщик заданий» Windows 7, обратите внимание, что в данной версии от этого приложения зависит корректная работа системы. Единственное, что можно предпринять в таком случае: снять некоторые задачи, чтоб приложение их не выполняло.
- Откройте «Панель управления» — «Администрирование» — «Планировщик заданий» — «Библиотека».
- Слева вы увидите тематические папки – открывая каждую, можно выбрать конкретную задачу, исполнение которой легко отменить, щелкнув по ней вспомогательной кнопкой мыши и нажав соответствующую кнопку.
Скрипт
«Планировщик заданий» в Windows XP можно отыскать в разделе «Служебные программы». В восьмой версии утилиту переместили в «Панель управления». В «Виндовс-10» все уже выглядит иначе: ПО располагается в разделе «Управление компьютером» — там же, где находятся другие элементы администрирования. Фактически файлы данного приложения хранятся на системном диске С (Windows – System 32 — Taskschd.msc), и отсюда их тоже можно запускать.

Комментирование
Может случиться так, что созданная в мастере простая задача вам не подходит, а создание новой требует более точных настроек.
Используем пункт раздела «Действия», который создает простую задачу без мастера, но с большим набором различных параметров.
В первом окне создания задачи вам также придется задать ей определенное имя, указать конечную точку, где она будет размещаться, а также сделать конкретное описание.
Выставляем также параметры безопасности.
На вкладке триггеров у вас будет возможность задать не один, а сразу несколько параметров, которые будут способствовать запуску задания.

Установка триггеров для создаваемой задачи
В окне создания триггера имеется список условий, при которых будет происходить запуск.
В нем присутствуют:
- по расписанию;
- при входе в систему;
- при запуске;
- при простое;
- при событии;
- при создании или изменении задачи;
- при подключении к пользовательскому сеансу;
- при отключении от пользовательского сеанса;
- при блокировании рабочей станции;
- при разблокировании рабочей станции.
Также в данном окне вы сможете отложить старт на произвольное время, повторять ее через определенные интервалы в течение указанного срока и осуществить ее остановку спустя указанное время.
Перейдя на вкладку для установки действий, вы сможете дать команду на запуск сразу нескольких программ, а также указать выполнение различных процессов.
В разделе условий вам предстоит установить те из них, которые являются определяющим условием, необходимым для запуска задачи.
Первый пункт — настройка задачи во время простоя компьютера, а ниже — ее настройка относительно питания.

Последняя вкладка, которую нужно настроить для завершения создания простой задачи — это «Параметры».
На ней необходимо указать некоторые дополнительные значения, необходимые для выполнения задания.

Вкладка параметров создаваемой задачи
Выставив необходимые из них — кликаете по кнопке «Ок» для завершения.
Несмотря на то, что данный процесс сопровождается большим количеством опций — затруднений в создании задания вы не испытаете.
Связано это с тем, что каждая из них довольно ясно и доходчиво описывает выполняемую функцию.
Иногда встречается такое, что служба планировщика заданий не запускается. Связано это с возникновением определенных ошибок в операционной системе Windows.
Для того, чтобы это исправить — можно воспользоваться программой Fix. Она предназначена для устранения ошибок в операционных системах.
Получение информации и запуск заданий планировщика из PowerShell
Вы можете вывести список всех активных заданий планировщика в Windows с помощью команды:
Чтобы получить информацию о конкретном задании:
LastRunTime : 4/6/2021 10:00:00 AM
LastTaskResult : 267011
NextRunTime : 4/7/2021 10:00:00 AM
NumberOfMissedRuns : 0
TaskName : CheckServiceState_PS
TaskPath : PSComputerName :

Вы можете отключить это задание:
Чтобы включить задание:
Чтобы запустить задание немедленно (не дожидаясь расписания), выполните:

Чтобы полностью удалить задание из Task Scheduler:
Unregister-ScheduledTask -TaskName CheckServiceState_PS
Если нужно изменить имя пользователя, из-под которого запускается задание и, например, режим совместимости, используйте командлет Set-ScheduledTask:
При появлении ошибки “Set-ScheduledTask : No mapping between account names and security IDs was done” проверьте, что у вас указано правильное имя пользователя.

Управление заданиями Task Scheduler с помощью PowerShell
В Windows 10/Windows Server 2016 для управления задачами в планировщике используется PowerShell модуль ScheduledTasks. Список командлетов в модуле можно вывести так:
Get-Command -Module ScheduledTasks

Совет. Ранее в Windows для создания и управления заданиями планировщика в основном использовались встроенная консольная утилита schtasks.exe.
Экспорт и импорт заданий планировщика в XML файл
С помощью PowerShell можно экспортировать любое задания планировщика в текстовый XML файл для распространения на другие компьютеры. Вы можете экспортировать задание из графического интерфейса Task Scheduler или из консоли PowerShell.
Следующая команда экспортирует задание StartupScript_PS в файл StartupScript_PS.xml:

Командлет Export-ScheduledTask не доступен в PowerShell 2.0. Поэтому в Windows 7 / 2008 R2 для экспорта настроек задания в XML файл лучше воспользоваться встроенной утилитой schtasks, вывод которой нужно перенаправить в текстовый файл:
После того, как настройки задания планировщика экспортированы в XML файл, его можно импортировать на любой другой компьютер с помощи графической консоли, SchTasks.exe или PowerShell.
Воспользуйте командлетом PowerShell Register-ScheduledTask чтобы параметры задания из файла и зарегистрировать его:
Примечание. В PowerShell 2.0 (Windows 7/Server 2008 R2) импорт задания также проще выполнить с помощью утилиты schtasks. Первая команда создаст новое задание. Вторая – сразу запустит его (не дожидаясь срабатывания триггера).
schtasks /create /tn “NewPsTask” /xml “\Server1publicNewPsTask.xml ” /ru corpaaivanov /rp Pa$$w0rdschtasks /Run /TN “NewPsTask”
Обратите внимание, что в этом примере указаны данные учетной записи, из-под которой будет запускаться задание. Если имя и пароль учетной записи не указаны, то т.к. они не хранятся в задании, они будут запрошены при импорте.
Раздел действий
В разделе «Действия» расположен пункт импортирования задачи, который позволяет загрузить какое-нибудь стороннее приложение, скачанное на компьютер.

Окно импортирования задачи
Следующим в списке находится пункт, отображающий все выполняемые задачи.
Для того, чтобы перейти на страницу их отображения — кликните по данному пункту.

Окно выполняемых задач
Затем следует пункт, позволяющий включить либо отключить журнал всех имеющихся заданий.
Имеются и такие пункты, как «Создать папку», «Обновить» и «Справка», которые интуитивно понятны и не нуждаются в описании.
Нижняя часть содержит список действий, которые можно применить к элементу.
Среди них такие, как:
Кроме тех задач, которые будете создавать вы — планировщик содержит и свои, которые делают работу системы стабильной и корректной.
К таким процессам можно отнести дефрагментацию жесткого диска и удаление из него скапливающихся в процессе работы временных файлов.
И таких стандартных процессов в программе достаточно много.
Далее будет рассмотрена последовательность действий, в ходе которых создается простая задача планировщике заданий.
Открываем окно и выбираем в правом разделе списка пункт создания простой задачи.
Вызвав «Мастер простых задач» — приступаете к ее созданию.
Вначале необходимо придумать имя программы и создать ее описание. Вся эта информация вносится в соответствующие поля.

Создание имени и описания
После этого переходите в следующий раздел мастера, отвечающий за триггеры, и указываете — когда будет происходить запуск создаваемой программы.
Есть такие стандартные значения:
- ежедневно;
- еженедельно;
- ежемесячно;
- однократно;
- при запуске компьютера;
- при входе в Windows;
- при занесении в журнал указанного события.

Выбор стандартного триггера
После того, как наиболее подходящий триггер будет выбран — кликаете по кнопке «Далее» и переходите к следующей настройке.
В случае, когда выбран ежедневный запуск создаваемой задачи — откроется окно настроек.
В нем необходимо указать — с какой даты и какого времени произвести первый запуск, а также то, с какой частотой она будет производиться.

Настройки пункта «Ежедневно»
В следующем окне мастера вам предстоит выбрать из списка одно действие, которое будет применено к создаваемой задаче.

Выбор действия для задачи
Дальнейший шаг — выбор программы или сценария для создаваемой задачи, а также добавление аргументов и выбор рабочей папки.

Окно добавления сценария
Завершающим этапом в создании простой задачи будет открытие окна с теми данными, которые были к ней применены.
Здесь, также, вы сможете установить галочку, которая открывает окно свойств задачи после нажатия кнопки «Готово».
После всех этих шагов простая задача будет создана и принята планировщиком к исполнению.
Изменение поведения планировщика
Теперь мы вооружены знаниями о том, как на уровне кодов происходит смена потока в Windows. Но как заставить планировщик работать в соответствии с поставленной задачей? Т.е., во-первых, сделать квант «бесконечным» на время работы заданного потока, а во-вторых, не допустить, чтобы диспетчер баланса поднял приоритет давно ждущих потоков выше приоритета заданного потока.
Для этого требуется внести исправление в само ядро. Это не так уж и сложно. Конечно, потребуется позаботиться о пересчете контрольной суммы с помощью процедуры CheckSumMappedFile и тому подобных мелочах, но это не является серьезным препятствием. Самое главное – организовать удобный интерфейс задачи пользователя с ядром. Напоминаем, что это делается для единственного компьютера.
Была выбрана схема, при которой запущенный поток сам периодически сообщает ядру о своей «избранности». При получении этого сообщения ядро продлевает квант выполнения и ограничивает подъем приоритетов диспетчером баланса не выше заданного. Как только (минут через 20-30) поток завершается, он перестает давать сообщения ядру. Поэтому ОС опять начинает выполнять фрагмент кода по исчерпанию кванта (для других потоков). В этом месте будет срабатывать возврат диспетчера баланса в нормальный режим работы. Таким образом, после завершения нужного потока ядро автоматически возвращается в обычный режим работы.
Сначала нужно найти место для размещения дополнительных команд. Таких мест много, например, команды можно написать вместо вот этого длинного диагностического текста, который вряд ли когда потребуется:
555390 E8 CE DC EA FF C9 C2 04-00 90 2A 2A 2A 2A 2A 2A ..Р******
5553A0 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
5553B0 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
5553C0 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
5553D0 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
5553E0 2A 2A 2A 2A 2A 2A 2A 2A-2A 0A 2A 0A 2A 20 54 68 *********.*.* Th
5553F0 69 73 20 69 73 20 74 68-65 20 73 74 72 69 6E 67 is is the string
555400 20 79 6F 75 20 61 64 64-20 74 6F 20 79 6F 75 72 you add to your
555410 20 63 68 65 63 6B 69 6E-20 64 65 73 63 72 69 70 checkin descrip
555420 74 69 6F 6E 0A 2A 20 44-72 69 76 65 72 20 56 65 tion.* Driver Ve
555430 72 69 66 69 65 72 3A 20-45 6E 61 62 6C 65 64 20 rifier: Enabled
555440 66 6F 72 20 25 5A 20 6F-6E 20 42 75 69 6C 64 20 for %Z on Build
555450 25 6C 64 20 25 77 5A 0A-2A 0A 2A 2A 2A 2A 2A 2A %ld %wZ.*.******
555460 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
555470 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
555480 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
555490 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
5554A0 2A 2A 2A 2A 2A 2A 2A 2A-2A 0A 00 CC CC CC CC CC *********..
Передача сообщения ядру происходит с помощью выполнения привилегированной команды, на которую сработает исключение INT 0D «нарушение общей защиты». При этом предварительно в одном из регистров пишется специальное значение, которое и позволит ядру отличить этот случай от всех остальных. Кстати, само ядро тоже пользуется похожим приемом, например, в интерфейсе запроса времени INT 2A в регистре EBP можно записать специальные значения F0F0F0F0 или F0F0F0F1, которые заставят ядро реагировать на INT 2A по-разному.
Для начала команды обработчика исключения INT 0D в ядре по адресу 409150 можно немного «уплотнить» и добавить вызов новой подпрограммы (размещенной по адресу 5553A0 на месте текста), не двигая остальной код обработчика:
Как видите, при необходимости даже оптимизированный код можно «ужать» и вставить дополнительные команды.
А на место диагностического текста помещаются основные команды исправления ядра:
Дополнительный обработчик исключения проверяет сигнатуру ESI=55554444 и выполняет следующие действия:
– устанавливает максимальное значение счетчика 127 для текущего потока;
– достает приоритет текущего потока и вставляет его как константу прямо внутрь команды, через которую проходит управление в диспетчере баланса. Чтобы найти относительный адрес исправляемой команды, выполняется фиктивный вызов процедуры;
– пропускает команду, которая вызвала это исключение, выбрасывает из стека адрес возврата и код ошибки и возвращается прямо в задачу пользователя.
По сути, Windows вообще не «чувствует» такое исключение, поскольку управление сразу же возвращается в задачу, минуя обычные пути обработки исключений. В программе достаточно хотя бы раз в 2-3 секунды давать исключение с таким значением в ESI и тогда внутренний счетчик потока по адресу 6F никогда не достигнет нуля. А значит, переменная 9AC продолжает оставаться нулевой и Windows не ищет замену текущему потоку.
Остается поправить диспетчер баланса. В него добавляются команды, проверяющие приоритет ждущего потока. Если приоритет ниже, диспетчер действует так, как будто поток еще не «старый»:
Первоначально приоритет сравнивается с константой 16, которой у проверяемых потоков не может быть, и поэтому проверка никак не влияет на обычную работу диспетчера. Но когда начинают приходить сообщения от «избранного» потока, константа 16 прямо в команде проверки заменяется значением приоритета заданного потока. Теперь всем более низкоприоритетным потокам диспетчер уже не пытается поставить приоритет 15.
Требуется лишь вернуть константу 16 на место после того, как заданный поток закончился. В этом случае ОС опять начинает выполнять поиск потоков по исчерпанию кванта, в это место и можно добавить команды восстановления:
Все перечисленные вставки кодов записаны непрерывно на месте диагностического текста и разделены здесь лишь для более наглядного пояснения их работы.
Создание обычного задания
Для создания обычного задания откройте планировщик и выберете в меню справа Create Task.

На вкладке General заполните поле Name именем задания. Также можно указать дополнительные параметры безопасности, такие как пользователь и группа пользователей, от имени которых выполняется задача, запуск задачи от имени суперпользователя.

На закладке Triggers необходимо создать расписание работы задачи с помощью кнопки New.

Здесь можно выбрать условие запуска задачи, например по расписанию, при входе в систему, при блокировке или разблокировке системы.

Например можно задать следующее расписание: начиная с 1 марта 2018 года еженедельно во во вторник, пятницу и воскресенье в 10:30 утра выполнять указанную задачу. Интерфейс настроек прост и интуитивно понятен.

На закладке Actions необходимо указать действия, которые будут выполняться по расписанию, с помощью кнопки New.

Укажите путь до исполняемого файла, при необходимости введите дополнительные аргументы. Нажмите OK.

Ниже приведены скриншоты расширенных настроек и условий, при необходимости их можно использовать.


Как открыть «Планировщик заданий»
Теперь мы расскажем, как запустить «Планировщик заданий» разными способами.
Меню пуск
- В Windows ХР и 7 следуем пути: «Пуск» — «Все программы» — «Стандартные» — «Служебные».
- В Windows 10 – «Пуск» — «Средства администрирования»
- В Windows 8 через «Пуск» открыть приложение не выйдет.

Панель управления
Открываем планировщик заданий в Windows 10 и 8 следующим образом:
- Разворачиваем строку поиска и пишем «Панель управления».
- Открываем раздел и обращаем внимание на надпись «Просмотр» справа вверху. «Категории» нужно сменить на «Крупные значки».
- Теперь мы видим ярлык «Администрирование» — при нажатии на него откроется список служб, среди которых будет и «Планировщик».
В Windows 7 и ХР, как мы помним, он вынесен в служебные программы.
Поле поиска
Самый легкий способ найти приложение – набрать его название в строке поиска Windows. Сразу, как только вы начнете записывать словосочетание, система автоматически найдет ПО, и его можно сразу же включить.
Окно «Выполнить»
- Нажимаем комбинацию Win+R.
- Появляется окно «Выполнить» с пустой строкой, куда мы вписываем «taskschd.msc» (игнорируем кавычки).
- Жмем «Интер» и ждем, пока откроется приложение.

Командная строка
- Снова вызываем окно «Выполнить» и вписываем «cmd» (без кавычек)
- Нажимаем Enter и ждем появления «Командной строки».
- Вписываем туда «C:/Windows/System32/taskschd.msc» и жмем ОК.
Можно также конкретизировать команду, добавив к ней без пробелов:
- /Create – для формирования новой задачи;
- /Delete – для снятия задачи;
- /Query – для просмотра созданных задач;
- /Change – для корректировки задачи.

Прямой запуск
Как уже упоминалось выше, «Планировщик заданий» можно запустить прямо из корневой папки, где хранятся все его файлы. Для этого достаточно перейти по пути: диск С — Windows – System 32 — Taskschd.msc и дважды кликнуть его.
Анализ кода
По условиям задачи анализировать потребовалось ядро Windows-XP SP3 сборки 0421 от 4 июля 2013 года. При этом в очень большом тексте (примерно 570 000 ассемблерных строк) нужно было по возможности быстро найти элементы планировщика, отвечающие за переключение потоков.
Далее идет обновление числа «тиков» и проверки таймеров, а затем самый важный для анализа фрагмент:
Т.е. при каждом окончании времени кванта запускается подпрограмма с вполне соответствующим случаю названием KeUpdateRunTime.
Она расположена по тексту рядом:
Откуда следует, что это достаются именно текущий поток и процесс?
Это легко выясняется, например, из процедуры KeGetCurrentThread:
И из процедуры IoGetCurrentProcess:
Самое интересное место расположено в конце KeUpdateRunTime:
Здесь из некоторого поля внутренней структуры текущего потока со смещением 6F вычитается 3 и, если этот счетчик становится не положительным, в некоторую переменную с относительным адресом 9AC заносится зачем-то значение ESP. А где используется такая переменная? Оказывается, контекстный поиск смещения 9AC находит одно единственное место внутри KiDispatchInterrupt:
Если значение переменной 9AC не равно нулю, оно сбрасывается, затем идет обращение к некоторой процедуре по адресу 411ABF. И если процедура возвращает ненулевой EAX, то управление попадает на адрес 4058D1. А здесь это значение (командой по адресу 4058F1) пишется как новый текущий поток. Вот нужное место и найдено!
Теперь понятна вся цепочка действий ядра: на каждый «тик» встроенных часов запускается KeUpdateSystemTime, где текущий квант уменьшается на число прошедших «тиков». Если квант истек, запускается KeUpdateRunTime, которая уменьшает внутренний счетчик в структуре текущего потока. Как только этот счетчик истекает, данное событие отмечается в переменной с относительным адресом 9AC. При ближайшем прерывании запускается KiDispatchInterrupt, которая проверяет переменную 9AC. Если переменная не нулевая (именно для этого в нее занесли ESP) – значит время данного потока исчерпано.
С помощью подпрограммы по адресу 411ABF ОС ищет новый поток для работы. Если конкурента текущему потоку не находится, он продолжает выполнение. Иначе текущий поток переводится в режим ожидания с помощью процедуры по адресу 405667, и запускается (т.е. становится текущим) другой поток.
Интересно, что внутри процедуры с адресом 411ABF проверяется, равно ли нулю поле 69 структуры текущего потока. Если нет – новый поток не ищется. Это поле описано в документации как DisableQuantum. Т.е. квант работы можно сделать бесконечным!
Увы, установить это поле из режима пользователя нельзя. Сама ОС может установить любое значение этого поля с помощью внутренней процедуры по адресу 43CA4B. Однако когда она использует эту подпрограмму, всегда данное поле устанавливается в ноль. Жаль, было бы удобно с помощью какого-нибудь недокументированного сервиса задать себе таким способом «бесконечный» квант работы.
Обратите внимание, что не только переменная 9AC может вызвать смену потока. Точно так же поток меняется, если значение поля с относительным адресом 128 не нулевое. По адресу 4058D1 начинается общая для двух этих случаев часть действий ОС по смене потока. Не вызывает сомнения, что проверка переменной со смещением 128 – это как раз случай появления потока с более высоким приоритетом.
А есть ли еще места смены текущего потока? Да, есть, и они по тексту рядом.
Это подпрограмма вызывается, например, внутри KeWaitForMultipleObjects. Очевидно, что это случай «добровольной» смены потока при ожиданиях, задержках, окончании задачи и т.п.
Наконец, еще одно место изменения поля со смещением 124 находится контекстным поиском чуть выше:
Здесь уже не проверяется переменная 9AC, но опять проверяется наличие потока с более высоким приоритетом. Очевидно, что это обработка прерывания, случившегося внутри самой ОС, где квант не может истечь по определению, но на появление готового потока с более высоким приоритетом нужно реагировать немедленно.
И это весь анализ по части смены потока. Контекстным поиском больше не найдено мест, где бы менялся текущий поток (по смещению 124). А значит, анализировать остальные сотни тысяч строк ассемблерного кода уже нет никакой необходимости. ОС именно так как описано в документации меняет текущий поток или по исчерпанию заданного числа квантов (что определяется счетчиком в поле 6F структуры текущего потока) или при появлении более высокоприоритетного или если поток сам уступает время выполнения. Других «секретных» способов не обнаружено. Для решения поставленной задачи осталось лишь понять работу диспетчера баланса. Кстати, где он?
Если это и есть диспетчер баланса, тогда вот в нем сама проверка степени «старения» потока по времени его ожидания в поле со смещением 68:
А вот и нашлось поднимание текущего приоритета до 15, а также указанное в документации удвоение времени работы в кванте в этом случае:
Теперь, наконец, анализ кода можно считать оконченным. В более чем полумиллионе ассемблерных строк с помощью контекстного поиска и общих соображений достаточно легко нашлось несколько десятков команд полностью и в строгом соответствии с документацией объясняющих поведение ОС при переключении потоков.
Удаление или отключение?
Консольная команда schtasks имеет полный набор аргументов для управления Планировщиком заданий Windows. В ходе поиска информации по отдельным задачам в сети Интернет мне попадались скрипты других авторов, где ненужные задачи отключались (подаргумент /disable аргумента /Change). Я использую более радикальный подход — просто удаляю (аргумент /Delete) ненужные мне задачи. Ведь вариант «отключение» подразумевает что мне когда-нибудь понадобится включить некоторую задачу. Не представляю себе ситуацию, когда мне понадобится снова включить, например, уведомление об окончании срока поддержки или телеметрию. Что скажете?
Планирование потоков
Как известно, переключение на другой поток в Windows происходит в трех случаях:
- истек выделенный квант времени работы и есть потоки с таким же приоритетом;
- поток добровольно уступает время работы (например, начинает ждать события);
- появился готовый к работе поток с более высоким приоритетом. Он немедленно (на самом деле в момент ближайшего прерывания) получает управление.
Кроме этого, в составе планировщика Windows имеется так называемый диспетчер баланса, который поднимает приоритет до значения 15 у давно ждущих выполнения потоков. Поскольку значения приоритетов класса «реального времени» начинаются с 16, то потоки «реального времени» диспетчер баланса прервать не может, а вот остальные потоки рано или поздно уступят квант потокам с более низким приоритетом. Скорее всего, это и является источником редких непредсказуемых задержек – иногда целый квант выполняется какой-то низкоприоритетный поток.
Проведем несложный эксперимент. Запустим одновременно две копии простейшей программы, которые просто выводят на экран постоянно увеличивающееся на единицу число. Чтобы не влияла многоядерность, назначим этим задачам одно и то же ядро процессора или вообще запустим компьютер в одноядерном режиме. Две программы, как и положено, работают «одновременно» (т.е. попеременно) и примерно с одинаковой скоростью. Теперь, используя диспетчер процессов, установим одной задаче приоритет «реального времени». Эта задача продолжает работать, а вторая задача останавливается. Все ожидаемо. Однако иногда и во второй задаче выдаваемое число увеличивается!
Объясните (как говорят в Одессе, «с указочкой»), почему задача с низким приоритетом вообще получает управление, когда по условиям эксперимента есть непрерывно работающая программа с заведомо очень большим приоритетом? Ответ на этот вопрос приведен в конце статьи и, честно говоря, он имеет мало отношения к теме.
С другой стороны, тот же Руссинович сообщает, что Windows создавали 5000 программистов. Вряд ли одному человеку под силу разобраться во всех тонкостях такой большой и сложной системы. К счастью, разобраться требуется только в одной из многочисленных сторон ОС. А это вполне возможно и одному человеку и за сравнительно небольшое время.
Отключение автоматического обслуживания
Планировщик задач тесно связан с автоматическим обслуживанием Windows, так как последнее представляет собой достаточно большой набор заданий, запуск которых проходит по установленному расписанию.
Обычно автоматическое обслуживание запускается, когда компьютер находится в состоянии бездействия, и проходит в фоновом режиме — не тревожа пользователя.
Но как только вы выводите компьютер из состояния сна для того, чтобы начать работать — автоматическое обслуживание прекращает свое действие и переносит его на другое время.
В большинстве случаев не рекомендуется отключать данную функцию, однако, бывают моменты, когда это сделать нужно.
Одним из таких случаев является зависание системы во время простоя компьютера или невозможность вывести его из состояния сна. Причиной проблемы является ошибка одного из процессов, входящих в обслуживающий пакет.
На примере Windows 8 будет показано, как остановить автоматическое обслуживание, задействовав для этих целей планировщик.
Для этого откройте его окно.
Один такой способ был рассмотрен в самом начале статьи.
Другой способ позволяет вызвать окно планировщика с помощью комбинаций клавиш.
Зажимаете одновременно на клавиатуре кнопки Win + R. Откроется окно «Выполнить».

Окно команды «Выполнить»
В его поисковой строке нужно вписать
и кликнуть по кнопке «Ок».
Эта команда вызывает «Планировщика задач». В левом разделе окна планировщика следует открыть каталог его библиотеки и перейти по следующей цепочке: Microsoft-Windows-TaskScheduler.

После этого в среднем разделе находите строку Regular Maintenance и кликнув по ней выбираете пункт «Отключить».
https://youtube.com/watch?v=_6T_ufHh7G4%3Frel%3D0%26enablejsapi%3D1
Планировщик задач Windows 8
В операционной системе Windows 8 присутствует возможность настраивать запуск различных приложений по расписанию, в строго определенное время дня или конкретного числа по календарю.
Планировщик заданий в предыдущих версиях этой операционной системы не являлся важной службой, поэтому его можно было отключать. Но в Windows 7 с помощью планировщика выполняется обширный ряд системных процессов, прекращение работы которых может привести к сбоям в функционировании PC.
(1 голос, в среднем: 5 из 5)
Если же вы захотите отключить выполнение тех или иных несистемных заданий, то это можно сделать, а иногда и крайне необходимо.
Через интерфейс Windows 7 данная процедура производится следующим образом:





Что именно можно отключить в планировщике заданий Windows 7? Только задачи, оставшиеся после удаления различных несистемных программ.
Использование
Запуск под учётной записью администратора приводит к выполнению последовательности команд schtasks с аргументом /Delete (удалить) последующее имя задачи за аргументом /tn. Ключ /f подавляет вывод уведомлений о подтверждении. Достаточно одного выполнения скрипта, а повторные запуски лишь отобразят список ошибок из-за невозможности удалить то, чего уже нет. Скрипт не наделён «интерактивностью», так как используется в процессе автоматической установки Windows.
Применимость
Список задач, подлежащих удалению данным скриптом, составлен для следующих версий ОС: Windows 7 Professional VL SP1 (updated Jan 2020 — End of Support), Windows 8.1 Professional VL Update3 (updated Jan 2023 — End of Support), Windows 10 v1607 Enterprise LTSB (updated Jan 2023). Изначально хотел написать отдельные скрипты для каждой версии Windows, но увидел, что список задач значительно повторяется и поэтому объединил в один. В планах добавить в список ненужные задачи из следующих версий ОС: Windows 10 v1809 Enterprise LTSC, Windows 10 v21H2 Professional BE (business editions) — на базе которых также делаю свои сборки.
Вердикт на удаление
Какие задачи в Планировщике заданий принимать к рассмотрению? Рассмотрим какие задачи бывают, в каком состоянии и насколько открыты. На начальном этапе были мысли написать простой скрипт, который бы удалял вообще все задачи (без разбора), но данный подход опасен тем, что может привести к снижению производительности и надёжности системы, так что пришлось разбираться. Итак:
- Бесполезное обслуживание
Это пример задач которые запускают ежедневное/еженедельное выполнение различных служб в назначенное время, как правило ночью. Как итог, эти задачи не выполняются так как ночью мой компьютер («рядового» пользователя) отключён. Также мне не надо чтобы днём отвлекались ресурсы моего компьютера. - Телеметрия
Это страшное слово знакомо многим системным администраторам и не только. Значительная часть удаляемых по моему списку задач относится к средствам телеметрии и слежения за пользователем со стороны компании Майкрософт. Мой компьютер — это МОЙ КОМПЬЮТЕР! - «Тёмные лошадки»
Самая сложная категория задач. Как правило, много их появилось в версии Windows 10. Отличительные особенности: описание размыто или отсутствует, параметры запуска скрыты, триггеры срабатывания отсутствуют, но при этом задача каким-то чудом регулярно запускается, о чём указано в поле «Время прошлого запуска».
Создание простого задания
Для создания простого задания откройте планировщик и выберете в меню справа Create Basic Task.

В поле Name введите удобное для вас название задачи, в поле Description при необходимости описание задачи.

На следующем шаге выберете частоту запуска: ежедневно, еженедельно,ежемесячно, один раз, при запуске компьютера, при входе в систему, при специфическом событии.

Укажите дату и время начала работы задания, а также периодичность, например запуск команды раз в 2 дня.

Далее выберете запуск программы в качестве действия.


Проверьте введенные ранее настройки и нажмите Finish.

Выполнение задания
Результат выполнения задания можно посмотреть в планировщике в центре рабочей области.


Настройка планировщика для Windows
Доработка прикладного ПО
Анализ и исправление ядра ОС занял примерно неделю, зато все прикладное ПО осталось без изменения, за исключением добавления в одном месте в главный цикл основного модуля подпрограммы выдачи сообщения ядру.
На языке PL/1 подпрограмма выдачи сообщения ядру выглядит так:
Продление_Кванта:proc;
dcl ?ESI bit(32);
?ESI=’55554444’b4; // в регистр ESI помещаем сигнатуру
unspec(‘0F08’b4); // код любой «запрещенной» команды из 2-х байт
end Продление_Кванта;
Достаточно хотя бы раз в 2-3 секунды (т.е. пока не истечет внутренний счетчик, нужно опять успеть присвоить ему максимальное значение) обращаться из задачи пользователя к этой процедуре, как данный поток будет работать, не прерываясь на целые кванты для менее приоритетных потоков.




