PC 를 끄려는데 화면이 파랗게 바뀌며 "taskhostw 가 종료를 막고 있습니다" 같은 문구가 뜰 때가 있다. 작업 관리자를 열어 보면 같은 이름이 "Windows 작업을 위한 호스트 프로세스"라는 설명을 달고 늘 떠 있다. 이름만으로는 무슨 작업인지 전혀 알 수 없다. 이번 편은 이 taskhostw.exe 와, 가끔 나타났다 금방 사라지는 backgroundTaskHost.exe 를 열어 본다.
두 개의 taskhostw, 부모는 작업 스케줄러
확인한 시점에 taskhostw.exe 는 두 개였다.
Get-CimInstance Win32_Process -Filter "Name='taskhostw.exe'" |
Select-Object ProcessId, ParentProcessId, CommandLine, CreationDate
두 개 모두 부모가 svchost.exe 였고, 그 svchost 안의 서비스는 Schedule(작업 스케줄러) 하나였다. 파일은 C:\Windows\System32\taskhostw.exe, 117,216바이트, 버전 10.0.26100.9949 이고 Microsoft Windows 서명이 유효했다.
하나는 로그온한 바로 그 순간에 떴다. 명령줄은 taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E} 처럼 중괄호 ID 하나였다. 이 ID 를 레지스트리 HKCR\CLSID 와 이 PC 의 예약 작업 215개 동작에서 모두 찾아봤지만 일치하는 것이 없었다. 특정 작업을 가리키는 번호라기보다 그 taskhostw 인스턴스를 구별하는 식별자로 보인다. 다른 하나는 로그온 다음 날 새벽 2시 1분 2초에 떴고, 일반 권한으로는 경로와 명령줄이 비어 보였다.
메모리는 첫 번째가 작업 집합 5.6MB, 개인 메모리 9.7MB, 두 번째가 2.5MB, 9.1MB 였다. 두 개를 합쳐도 20MB 가 안 된다.
예약 작업의 두 종류와 taskhostw
작업 스케줄러에서 아무 작업이나 열어 "동작" 탭을 보면 대부분 "프로그램 시작"이다. 지정한 실행 파일을 그대로 띄우는 방식이라 taskhostw 가 필요 없다. 그런데 Windows 자체 작업 중 상당수는 실행 파일이 아니라 COM 처리기, 즉 DLL 안의 코드를 부르는 방식이다. DLL 은 혼자 돌 수 없으니 담아 줄 프로세스가 필요하고, 그 그릇이 taskhostw.exe 다.
$t = Get-ScheduledTask
$t | ForEach-Object { $_.Actions.CimClass.CimClassName } | Group-Object | Select-Object Count, Name
이 PC 의 예약 작업은 215개였고, \Microsoft\ 아래 Windows 작업이 194개, 나머지 21개가 설치한 프로그램이 등록한 것이었다. 동작 종류로 나누면 COM 처리기가 115개, 프로그램 시작이 100개였다. 상태는 준비 175개, 실행 중 6개, 사용 안 함 34개였다.
실행 중 6개 가운데 COM 처리기는 셋이었다. 멀티미디어의 SystemSoundsService, Wininet 의 CacheTask, WDI 의 ResolutionHost 다. 레지스트리에서 각 작업의 CLSID 를 찾으면 담당 DLL 이 나온다. 순서대로 PlaySndSrv.dll(PlaySound 서비스), wininet.dll(인터넷 캐시 작업), wdi.dll(진단 인프라)이었다.
어떤 작업을 담고 있는지 찾는 법
taskhostw 의 명령줄은 답을 주지 않으니 다른 단서 두 가지를 썼다.
첫째는 시작 시각이다. 작업마다 마지막 실행 시각이 남는다.
Get-ScheduledTask | Where-Object State -eq 'Running' |
ForEach-Object { $_ | Get-ScheduledTaskInfo } | Select-Object TaskName, LastRunTime
SystemSoundsService 와 CacheTask, 그리고 CTF 로더 편에서 본 MsCtfMonitor 는 마지막 실행 시각이 첫 번째 taskhostw 의 시작 시각과 초 단위까지 같았다. 셋 다 트리거가 로그온이고 Users 그룹 일반 권한으로 도는 작업이다. ResolutionHost 는 새벽 2시 1분 2초로, 두 번째 taskhostw 와 정확히 같았다. 이 작업은 실행 수준이 "가장 높은 권한"이라서 일반 권한에서 경로가 안 보였던 것과도 맞는다. 작업 스케줄러는 같은 계정·같은 권한으로 도는 COM 처리기 작업을 한 taskhostw 에 묶는 것으로 보인다.
둘째는 올라온 DLL 이다. 같은 사용자 권한으로 도는 첫 번째 taskhostw 는 모듈 목록을 읽을 수 있었다.
(Get-Process -Id <PID>).Modules | Select-Object ModuleName, @{n='설명'; e={$_.FileVersionInfo.FileDescription}}
49개 모듈 가운데 MsCtfMonitor.dll, PlaySndSrv.dll, wininet.dll 이 그대로 있었다. 시작 시각으로 짐작한 세 작업과 일치한다. MsCtfMonitor 는 작업 상태가 "준비"로 나와 있었는데도 DLL 은 여전히 메모리에 남아 있었다.
작업 스케줄러의 "기록" 탭을 쓰면 더 쉬울 것 같지만, 이 PC 에서는 기록 로그(Microsoft-Windows-TaskScheduler/Operational)가 꺼져 있었다. Windows 기본값이 꺼짐이고, 켜려면 관리자 권한으로 작업 스케줄러 오른쪽 창의 "모든 작업 기록 사용"을 눌러야 한다. 켜 두면 작업이 어느 프로세스 번호로 실행됐는지까지 남는다.
taskhostw 의 CPU 가 계속 높다면 이 방법으로 담긴 작업을 찾고, 그 작업의 트리거와 마지막 실행 결과를 본다. 설치한 프로그램의 작업은 대개 "프로그램 시작" 방식이라 자기 실행 파일 이름으로 보이고, taskhostw 쪽은 거의 Windows 작업이다.
backgroundTaskHost.exe 와 종료를 막는다는 메시지
backgroundTaskHost.exe 는 Store 앱의 백그라운드 작업용 그릇이다. 앱이 "알림을 갱신해 둬", "라이선스를 확인해 둬" 같은 작업을 등록해 두면 Windows 가 조건이 맞을 때 이 프로세스를 잠깐 띄워 그 코드를 돌린다. 평소에는 안 보이는 경우가 많아서, 두 번에 걸쳐 3분 남짓 1~2초 간격으로 지켜봤더니 딱 한 번 잡혔다. 부모는 Runtime Broker 를 띄우는 그 DcomLaunch svchost 였고, 명령줄은 -ServerName:App.AppX...mca 형태였다. 다음 확인 때는 이미 사라지고 없었다. 파일은 C:\Windows\System32\backgroundTaskHost.exe, 설명 "Background Task Host", 서명 유효였다.
지나간 기록은 이벤트 로그 Microsoft-Windows-BackgroundTaskInfrastructure/Operational 에 남는다. 이 PC 에는 4월부터 11월까지 56건이 있었는데, 47건이 "취소 알림에 따라 완료되지 못함", 9건이 "활성화 실패"였다. 패키지별로는 Dolby Access 앱의 작업이 35건으로 가장 많았고, 피드백 허브, Microsoft Store, 위젯 보드가 몇 건씩 뒤를 이었다. 특정 앱의 backgroundTaskHost 가 자꾸 CPU 를 쓴다면 이 로그에서 패키지 이름을 찾고, 설정 → 앱 → 설치된 앱 → 해당 앱의 고급 옵션에서 백그라운드 실행 권한을 보는 것이 맞다.
종료할 때 taskhostw 가 끝내지 못하게 막고 있다는 화면은 오류라기보다 기다려 달라는 신호에 가깝다. 이때 목록에는 "작업 호스트 창"과 "백그라운드 작업을 중지하는 중" 같은 설명이 함께 뜨는 것으로 알려져 있다. Windows 는 끄기 전에 실행 중인 프로세스에 정리할 시간을 주는데, taskhostw 안의 작업이 아직 끝나지 않았으면 그 이름이 화면에 남는다. 대개 몇 초 안에 스스로 사라지고, 업데이트 직후처럼 정리할 작업이 많을 때 더 자주 보이는 것으로 알려져 있다. "그래도 종료"를 누르면 그 작업은 중간에 끊긴다. 검색에 나오는 종료 대기 시간을 줄이는 레지스트리 수정은 다른 프로그램의 저장까지 끊을 수 있어서 권하지 않는다. 매번 같은 화면이 오래 간다면 위 방법으로 어떤 작업이 걸려 있는지 먼저 본다.
가짜 구별은 앞 편들과 같다.
Get-Process taskhostw | Select-Object Id, Path
Get-AuthenticodeSignature C:\Windows\System32\taskhostw.exe | Select-Object Status
경로가 System32 가 아니거나 부모가 Schedule 서비스의 svchost 가 아니라면 의심해 볼 만하다.
다음 편은 소리를 낼 때 CPU 를 먹는다는 audiodg.exe 다. 오디오 향상 효과와 제조사 오디오 서비스가 어디에 끼어드는지 레지스트리로 확인해 본다.