자동 유지 관리

플랫폼

클라이언트 – Windows 8
서버 – Windows Server 2012

Description

Windows는 Windows 업데이트, 자동 디스크 조각 모음, 바이러스 백신 업데이트 및 검사를 포함하여 대부분의 부가가치에 대한 받은 편지함 및 타사 유지 관리 작업의 실행에 따라 달라집니다. 또한 엔터프라이즈는 NAP(네트워크 액세스 보호) 검사와 같은 유지 관리 작업을 자주 사용하여 모든 엔터프라이즈 워크스테이션에 보안 표준을 적용합니다.

Windows의 유지 관리 활동은 제한된 사용자 상호 작용과 성능 및 에너지 효율성에 미치는 영향을 최소화하여 백그라운드에서 실행되도록 설계되었습니다. 그러나 Windows 7 및 이전 버전에서는 Windows의 여러 유지 관리 활동의 비결정적이고 널리 다양한 일정으로 인해 성능 및 에너지 효율성이 여전히 영향을 받고 있습니다. 사용자가 컴퓨터를 적극적으로 사용하는 동안 유지 관리 작업이 실행되면 사용자에 대한 응답성이 줄어듭니다. 또한 앱은 사용자에게 소프트웨어를 업데이트하고 백그라운드 유지 관리를 실행하도록 요청하고 사용자를 알림 센터, 제어판, Windows 업데이트, 작업 스케줄러 MMC 스냅인 및 타사 컨트롤을 비롯한 여러 환경으로 안내합니다.

자동 유지 관리의 목표는 Windows의 모든 백그라운드 유지 관리 활동을 결합하고 타사 개발자가 성능 및 에너지 효율성에 부정적인 영향을 주지 않고 Windows에 유지 관리 활동을 추가할 수 있도록 돕는 것입니다. 또한 자동 유지 관리를 사용하면 사용자와 기업이 유지 관리 활동 일정 및 구성을 제어할 수 있습니다.

주요 문제

자동 유지 관리는 Windows의 유지 관리 작업에서 이러한 문제를 해결하도록 설계되었습니다.

  • 최종 기한 예약
  • 리소스 사용률 충돌
  • 에너지 효율성
  • 사용자에게 투명도

기능

자동 유지 관리는 유휴 효율성을 용이하게 하며 모든 활동을 적시에 우선 순위가 지정된 방식으로 실행할 수 있도록 합니다. 또한 유지 관리 활동에 대한 통합 가시성 및 제어를 가능하게 하고 타사 개발자가 성능 및 에너지 효율성에 부정적인 영향을 주지 않고도 유지 관리 활동을 Windows에 추가할 수 있습니다. 이를 위해 완전 자동 모드, 사용자 시작 모드, 자동 중지, 최종 기한 및 알림 및 엔터프라이즈 제어를 제공합니다. 이들은 각각 아래에 설명되어 있습니다.

완전 자동 모드

이 기본 모드를 사용하면 PC 유휴 시간 동안 및 예약된 시간에 지능형 일정 예약을 사용할 수 있습니다. 사용자 개입 없이 유지 관리 작업의 실행 및 자동 일시 중지가 가능합니다. 사용자는 매주 또는 일별 일정을 설정할 수 있습니다. 모든 유지 관리 작업은 비대화형이며 자동으로 실행됩니다.

컴퓨터는 시스템이 사용 중일 가능성이 없을 때 자동으로 절전 모드에서 다시 시작되며, 노트북의 경우 AC 전원에 있는 경우에만 절전 모드 해제를 허용하는 기본값인 전원 관리 정책을 따릅니다. 높은 전력의 전체 시스템 리소스는 가능한 한 빨리 유지 관리 작업을 완료하는 데 사용됩니다. 자동 유지 관리를 위해 시스템이 절전 모드에서 다시 시작된 경우 절전 모드로 돌아가도록 요청됩니다.

구성과 같은 활동과 관련된 모든 필수 사용자 상호 작용은 자동 유지 관리 실행 외부에서 수행됩니다.

사용자가 시작한 모드

사용자가 여행을 준비해야 하거나, 장기간 배터리 전원을 켜야 하거나, 성능 및 응답성을 최적화하려는 경우 주문형 자동 유지 관리를 시작할 수 있습니다. 사용자는 자동 실행 일정을 포함하여 자동 유지 관리 특성을 구성할 수 있습니다. 자동 유지 관리 실행의 현재 상태 볼 수 있으며 필요한 경우 자동 유지 관리를 중지할 수 있습니다.

자동 중지

자동 유지 관리는 사용자가 컴퓨터와 상호 작용을 시작하는 경우 현재 실행 중인 유지 관리 작업을 자동으로 중지합니다. 시스템이 유휴 상태 돌아오면 유지 관리 작업이 다시 시작됩니다.

참고

자동 유지 관리의 모든 활동은 2초 이내에 중지를 지원해야 합니다. 사용자에게 활동이 중지되었다는 알림을 받아야 합니다.

 

마감일 및 알림

중요한 유지 관리 작업은 미리 정의된 기간 내에 실행되어야 합니다. 중요한 작업을 지정된 시간 내에 실행할 수 없는 경우 자동 유지 관리는 사용 가능한 다음 시스템 유휴 기회에 자동으로 실행을 시작합니다. 그러나 작업 상태가 최종 기한 뒤에 남아 있는 경우 자동 유지 관리는 사용자에게 활동에 대해 알리고 자동 유지 관리 수동 실행에 대한 옵션을 제공합니다. 유지 관리로 예약된 모든 작업이 실행되지만 가장 부족한 작업이 우선합니다. 이 활동은 시스템 응답성 및 성능에 영향을 미칠 수 있습니다. 따라서 자동 유지 관리는 사용자에게 중요한 유지 관리 작업이 실행 중임을 알립니다.

엔터프라이즈 제어

엔터프라이즈 IT 전문가는 Windows 시스템에서 자동 유지 관리가 실행되는 시기를 확인하고, 표준화된 관리 인터페이스를 통해 해당 일정을 적용하고, 자동 유지 관리 실행 시도의 상태 대한 이벤트 데이터를 검색할 수 있어야 합니다. 또한 IT 전문가는 표준 관리 인터페이스를 통해 특정 자동 유지 관리 작업을 원격으로 호출할 수 있어야 합니다. 자동 유지 관리가 실행될 때마다 사용자가 작업을 수동으로 일시 중지했기 때문에 자동 유지 관리를 실행할 수 없는 경우 알림을 포함하여 상태 보고가 실행됩니다. IT 전문가는 사용자의 로그온 환경을 더 빠르게 만들 수 있도록 로그온 스크립트를 자동 유지 관리로 이동하는 것을 고려해야 합니다.

자동 유지 관리 작업 만들기

이 섹션에서는 개발자가 XML 또는 C 언어로 작업 정의를 사용하여 작업을 만드는 방법을 자세히 설명합니다. 자동 유지 관리는 완전히 침묵하며 사용자가 없을 때 실행되므로 유지 관리 작업은 사용자 상호 작용이 필요한 사용자 인터페이스를 시작해서는 안 됩니다. 실제로 사용자가 자동 유지 관리 중에 컴퓨터와 상호 작용하는 경우 프로세스의 모든 작업은 다음 유휴 기간까지 종료됩니다.

XML 사용

작업 스케줄러에는 XML 형식으로 작업 정의를 가져올 수 있는 기본 제공 명령줄 도구 schtasks.exe 포함되어 있습니다. 작업 정의에 대한 스키마는 에 설명되어 있습니다 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>

작업 실행 유효성 검사

이 명령줄을 실행하여 작업을 시작하고 작업 스케줄러 UI(taskschd.msc)에 태스크가 실행되었는지 확인합니다.

Schtasks.exe /Run /tn<task name>

리소스