Автоматическое обслуживание

Платформы

Клиенты — Windows 8
Серверы — Windows Server 2012

Описание

Windows зависит от выполнения операций обслуживания папки "Входящие" и стороннего производителя для большей части ее дополнительных компонентов, включая клиентский компонент Центра обновления Windows, автоматическую дефрагментацию диска, а также обновления и проверки антивирусной программы. Кроме того, предприятия часто используют действия по обслуживанию, такие как проверка защиты доступа к сети (NAP), для обеспечения соблюдения стандартов безопасности на всех корпоративных рабочих станциях.

Обслуживание в Windows предназначено для выполнения в фоновом режиме с ограниченным взаимодействием с пользователем и минимальным влиянием на производительность и энергоэффективность. Тем не менее, в Windows 7 и более ранних версиях производительность и энергоэффективность по-прежнему влияют из-за недетерминированного и широкого разнообразия графика нескольких мероприятий по обслуживанию в Windows. Скорость реагирования пользователей снижается при выполнении действий по обслуживанию, когда пользователи активно используют компьютер. Приложения также часто просят пользователя обновить свое программное обеспечение и выполнить фоновое обслуживание, а также направляют пользователей к нескольким интерфейсам, включая центр уведомлений, панель управления, клиентский компонент Центра обновления Windows, оснастку MMC планировщика задач и сторонние элементы управления.

Цель автоматического обслуживания — объединить все фоновые действия по обслуживанию в Windows и помочь сторонним разработчикам добавить свои действия по обслуживанию в Windows без негативного влияния на производительность и энергоэффективность. Кроме того, автоматическое обслуживание позволяет пользователям, а также предприятиям контролировать планирование и настройку действий по обслуживанию.

Ключевые проблемы

Автоматическое обслуживание предназначено для решения следующих проблем с действиями обслуживания в Windows:

  • Планирование крайних сроков
  • Конфликты использования ресурсов
  • Энергоэффективности
  • Прозрачность для пользователя

Функциональность

Автоматическое обслуживание повышает эффективность простоя и позволяет выполнять все действия своевременно и приоритетным образом. Это также помогает обеспечить унифицированную видимость и контроль над действиями по обслуживанию, а также позволяет сторонним разработчикам добавлять свои действия по обслуживанию в Windows, не влияя на производительность и энергоэффективность. Для этого он предоставляет полностью автоматический режим, режим, инициированный пользователем, автоматическую остановку, крайние сроки и уведомления, а также корпоративный контроль. Каждый из них описан ниже.

Полностью автоматический режим

Этот режим по умолчанию включает интеллектуальное планирование во время простоя компьютера и в запланированное время— выполнение и автоматическую приостановку действий по обслуживанию без вмешательства пользователя. Пользователь может задать еженедельное или ежедневное расписание. Все действия по обслуживанию являются неинтерактивными и выполняются автоматически.

Компьютер автоматически возобновляется из спящего режима, когда система, скорее всего, не будет использоваться, в соответствии с политикой управления питанием, которая в случае ноутбуков по умолчанию разрешает пробуждение только в том случае, если он подключен к сети переменного тока. Полные системные ресурсы с высокой мощностью используются для максимально быстрого завершения обслуживания. Если система была восстановлена из спящего режима для автоматического обслуживания, она будет запрошена для возврата в спящий режим.

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

Режим, инициированный пользователем

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

Автоматическая остановка

Автоматическое обслуживание автоматически останавливает текущие действия по обслуживанию, если пользователь начинает взаимодействовать с компьютером. Обслуживание возобновится, когда система вернется в состояние простоя.

Примечание

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

 

Крайние сроки и уведомления

Критические действия по обслуживанию должны выполняться в течение предварительно определенного периода времени. Если критические задачи не удалось выполнить в течение указанного времени, автоматическое обслуживание автоматически начнет выполняться при следующей доступной возможности простоя системы. Однако если состояние задачи остается за крайним сроком, автоматическое обслуживание уведомит пользователя о действии и предоставит возможность запуска автоматического обслуживания вручную. Все задачи, запланированные на обслуживание, будут выполняться, хотя большинство из них имеют приоритет. Это действие может повлиять на скорость отклика и производительность системы; Поэтому автоматическое обслуживание уведомит пользователя о выполнении критически важного действия по обслуживанию.

Корпоративный элемент управления

Корпоративные ИТ-специалисты должны иметь возможность определять, когда выполняется автоматическое обслуживание в своих системах Windows, применять это расписание через стандартизированные интерфейсы управления и получать данные о событиях о состоянии попыток автоматического обслуживания. Кроме того, ИТ-специалисты должны иметь возможность удаленно вызывать определенные действия автоматического обслуживания с помощью стандартных интерфейсов управления. При каждом выполнении автоматического обслуживания выполняется отчет о состоянии, включая уведомления о том, что автоматическое обслуживание не удалось выполнить, так как пользователь приостановил действие вручную. ИТ-специалистам следует рассмотреть возможность переноса сценариев входа в автоматическое обслуживание, чтобы упростить процесс входа пользователя.

Создание задачи автоматического обслуживания

В этом разделе описано, как разработчики могут создать задачу с помощью определения задачи на языке XML или C. Имейте в виду, что при выполнении обслуживания не следует запускать какой-либо пользовательский интерфейс, требующий взаимодействия с пользователем, так как автоматическое обслуживание полностью неактивно и выполняется, когда пользователь отсутствует. Действительно, если пользователь взаимодействует с компьютером во время автоматического обслуживания, все выполняемые задачи будут завершены до следующего периода простоя.

Использование XML

Планировщик задач включает встроенное средство командной строки schtasks.exe, которое может импортировать определение задачи в формате XML. Схема определения задачи задокументирована в https://msdn.microsoft.com/library/aa383609(v=VS.85).aspx. Ниже приведен пример задачи автоматического обслуживания, определенной в XML.

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2011-07-01T11:34:31</Date>
    <Author>IT Deptartment</Author>
  </RegistrationInfo>
  <Principals>
    <Principal id="Author">
      <RunLevel>LeastPrivilege</RunLevel>
      <GroupId>NT AUTHORITY\SYSTEM</GroupId>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <MaintenanceSettings>
      <Period>P2D</Period>
      <Deadline>P14D</Deadline>
    </MaintenanceSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>cmd</Command>
      <Arguments>/c timeout -t 60</Arguments>
    </Exec>
  </Actions>
</Task> 

Чтобы сохранить задачу на компьютере Windows, сохраните приведенный выше XML-файл в виде текстового файла и используйте следующую командную строку:

Schtasks.exe /create /tn <task name> /xml <text file name>

Использование C

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

/********************************************************************
This sample creates a maintenance task to start cmd window during maintenance opportunities with periodicity of 2 days and deadline 0f 14 days.
********************************************************************/

#define _WIN32_DCOM

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <comdef.h>
#include <wincred.h>
//  Include the task header file.
#include <taskschd.h>
//#pragma comment(lib, "taskschd.lib")
//#pragma comment(lib, "comsupp.lib")

int __cdecl 
MainteanceTask( )
{
    //  ------------------------------------------------------
    //  Initialize COM.
    HRESULT hr;

    //  ------------------------------------------------------
    //  Create a name for the task.
    LPCWSTR wszTaskName = L"MaintenanceTask";

    ITaskService *pService = NULL;
    ITaskFolder *pRootFolder = NULL;
    ITaskDefinition *pTask = NULL;
    ITaskSettings *pSettings = NULL;
    IRegistrationInfo *pRegInfo= NULL;
    IPrincipal *pPrincipal = NULL;
    ITaskSettings3 *pSettings3 = NULL;
    IMaintenanceSettings* pMaintenanceSettings = NULL;
    IActionCollection *pActionCollection = NULL;
    IAction *pAction = NULL;
    IExecAction *pExecAction = NULL;
    IRegisteredTask *pRegisteredTask = NULL;

    wprintf(L"\nCreate Maintenance Task %ws", wszTaskName );

    hr = CoInitializeEx( NULL, COINIT_MULTITHREADED);
    if( FAILED(hr) )
    {
        wprintf(L"\nCoInitializeEx failed: %x", hr );
        return 1;
    }

    //  Set general COM security levels.
    hr = CoInitializeSecurity( NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);

    if( FAILED(hr) )
    {
        wprintf(L"\nCoInitializeSecurity failed: %x", hr );
        goto CleanUp;
    }

    //  ------------------------------------------------------
    //  Create an instance of the Task Service. 
    hr = CoCreateInstance( CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskService,
                           (void**)&pService );  
    if (FAILED(hr))
    {
        wprintf(L"\nFailed to create an instance of ITaskService: %x", hr);
        goto CleanUp;
    }
        
    //  Connect to the task service.
    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if( FAILED(hr) )
    {
        wprintf(L"\nITaskService::Connect failed: %x", hr );
        goto CleanUp;
    }

    //  ------------------------------------------------------
    //  Get the pointer to the root task folder.  This folder will hold the
    //  new task that is registered.
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot get Root folder pointer: %x", hr );
        goto CleanUp;
    }
    
    //  If the same task exists, remove it.
    ( void ) pRootFolder->DeleteTask( _bstr_t(wszTaskName), 0  );
    
    //  Create the task definition object to create the task.
    hr = pService->NewTask( 0, &pTask );
    if (FAILED(hr))
    {
        wprintf(L"\nFailed to CoCreate an instance of the TaskService class: %x", hr);
        goto CleanUp;
    }
        
    //  ------------------------------------------------------
    //  Get the registration info for setting the identification.
    hr = pTask->get_RegistrationInfo( &pRegInfo );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot get identification pointer: %x", hr );
        goto CleanUp;
    }
    
    hr = pRegInfo->put_Author( _bstr_t(L"Author Name") );    
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put identification info: %x", hr );
        goto CleanUp;
    }

    // The task needs to grant explicit FRFX to LOCAL SERVICE (A;;FRFX;;;LS)
    hr = pRegInfo->put_SecurityDescriptor( _variant_t(L"D:P(A;;FA;;;BA)(A;;FA;;;SY)(A;;FRFX;;;LS)") );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put security descriptor: %x", hr );
        goto CleanUp;
    }

    //  ------------------------------------------------------
    //  Create the principal for the task - these credentials
    //  are overwritten with the credentials passed to RegisterTaskDefinition
    hr = pTask->get_Principal( &pPrincipal );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot get principal pointer: %x", hr );
        goto CleanUp;
    }
    
    //  Set up principal logon type to interactive logon
    hr = pPrincipal->put_LogonType( TASK_LOGON_INTERACTIVE_TOKEN );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put principal info: %x", hr );
        goto CleanUp;
    }  

    //  ------------------------------------------------------
    //  Create the settings for the task
    hr = pTask->get_Settings( &pSettings );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot get settings pointer: %x", hr );
        goto CleanUp;
    }

    hr = pSettings->QueryInterface( __uuidof(ITaskSettings3), (void**) &pSettings3 );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot query ITaskSettings3 interface: %x", hr );
        goto CleanUp;
    }

    hr = pSettings3->put_UseUnifiedSchedulingEngine( VARIANT_TRUE );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put_UseUnifiedSchedulingEngine: %x", hr );
        goto CleanUp;
    }

    hr = pSettings3->CreateMaintenanceSettings( &pMaintenanceSettings );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot CreateMaintenanceSettings: %x", hr );
        goto CleanUp;
    }

    hr = pMaintenanceSettings->put_Period ( _bstr_t(L"P2D") );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put_Period: %x", hr );
        goto CleanUp;
    }

    hr = pMaintenanceSettings->put_Deadline ( _bstr_t(L"P14D") );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put_Period: %x", hr );
        goto CleanUp;
    }

    //  ------------------------------------------------------
    //  Add an action to the task. This task will execute cmd.exe.     
    //  Get the task action collection pointer.
    hr = pTask->get_Actions( &pActionCollection );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot get Task collection pointer: %x", hr );
        goto CleanUp;
    }
    
    //  Create the action, specifying that it is an executable action.
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot create the action: %x", hr );
        goto CleanUp;
    }

    //  QI for the executable task pointer.
    hr = pAction->QueryInterface( IID_IExecAction, (void**) &pExecAction );
    if( FAILED(hr) )
    {
        wprintf(L"\nQueryInterface call failed for IExecAction: %x", hr );
        goto CleanUp;
    }

    //  Set the path of the executable to cmd.exe.
    hr = pExecAction->put_Path( _bstr_t(L"cmd") );
    if( FAILED(hr) )
    {
        wprintf(L"\nCannot put action path: %x", hr );
        goto CleanUp;
    }  
    
    //  ------------------------------------------------------
    //  Save the task in the root folder.
    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t(wszTaskName),
            pTask,
            TASK_CREATE_OR_UPDATE, 
            _variant_t(), 
            _variant_t(), 
            TASK_LOGON_INTERACTIVE_TOKEN,
            _variant_t(L""),
            &pRegisteredTask);
    if( FAILED(hr) )
    {
        wprintf(L"\nError saving the Task : %x", hr );
        goto CleanUp;
    }
    
    wprintf(L"\nSuccess!\n----------------------------------" );

CleanUp:

    if ( pService != NULL ) pService->Release();
    if ( pRootFolder != NULL ) pRootFolder->Release();
    if ( pTask != NULL ) pTask->Release();
    if ( pSettings != NULL ) pSettings->Release();
    if ( pRegInfo != NULL ) pRegInfo->Release();
    if ( pPrincipal != NULL ) pPrincipal->Release();
    if ( pSettings3 != NULL ) pSettings3->Release();
    if ( pMaintenanceSettings != NULL ) pMaintenanceSettings->Release();
    if ( pActionCollection != NULL ) pActionCollection->Release();
    if ( pAction != NULL ) pAction->Release();
    if ( pExecAction != NULL ) pExecAction->Release();
    if ( pRegisteredTask != NULL ) pRegisteredTask->Release();

    CoUninitialize();
    return SUCCEEDED ( hr ) ? 0 : 1;
}

Проверка задач

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

Проверка создания задачи

Используйте эту командную строку для экспорта определения задачи в файл и обеспечения правильности определения задачи:

Schtasks.exe /Query /tn<task name> /xml <text file name>

Проверка выполнения задачи

Выполните эту командную строку, чтобы запустить задачу и убедиться, что в пользовательском интерфейсе планировщика задач (taskschd.msc) указано, что задача выполнена:

Schtasks.exe /Run /tn<task name>

Ресурсы