У нас есть серьезная проблема с тихим завершением приложения C # в случайные и редкие моменты времени при установке 32-разрядной версии Windows 10. Например, это может быть месяц между событиями. Или иногда просто день.

Основные технические характеристики системы:

Microsoft Windows 10 Enterprise 2016 LTSB
Version 10.0.14393 Build 14393
32-bit

Используя https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-and-clearing-flags-for-silent-process-exit, мы настроили бесшумный мониторинг выхода из процесса. И у нас наконец есть несколько образцов этого:

The process 'APPLICATIONPATH\APPLICATIONNAME.exe' was terminated by 
the process 'C:\Windows\System32\svchost.exe' with termination code 1067. 
The creation time for the exiting process was 0x01d43bd8689073eb.

Рассматривая дампы для этого, который был настроен для мониторинга, мы получили идентификатор процесса для svchost. Эта служба все еще работала в системе, и она показывает следующий список служб:

Сервисы

Который, кажется, список "netsvcs" для Windows. Открыв дамп из svchost.exe и посмотрев на него, был найден единственный поток с интересным стеком вызовов:

ntdll.dll!_KiFastSystemCallRet@0 ()
ntdll.dll!_NtWaitForSingleObject@12 ()
ntdll.dll!RtlReportSilentProcessExit()
KERNELBASE.dll!TerminateProcess()
ubpm.dll!_UbpmpTerminateProcessCallback@12 ()
ubpm.dll!UbpmUtilsTimerCallback()
ntdll.dll!TppTimerpExecuteCallback()
ntdll.dll!TppWorkerThread()
kernel32.dll!@BaseThreadInitThunk@12 ()
ntdll.dll!__RtlUserThreadStart()
ntdll.dll!__RtlUserThreadStart@8 ()

UBPM - это унифицированный диспетчер фоновых процессов. Но как это может прекратить наше приложение? И почему? А что говорит нам код завершения 1067 ?

Ниже приведена запись в журнале от Silent Process Monitoring:

Log Name:      Application
Source:        Microsoft-Windows-ProcessExitMonitor
Date:          2018-08-31 15:26:09
Event ID:      3001
Task Category: None
Level:         Information
Keywords:      Classic
User:          SYSTEM
Computer:      PC
Description:
The process 'APPLICATIONPATH\APPLICATIONNAME.exe' was terminated by the process 'C:\Windows\System32\svchost.exe' with termination code 1067. The creation time for the exiting process was 0x01d43ed2aee892ab.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-ProcessExitMonitor" Guid="{FD771D53-8492-4057-8E35-8C02813AF49B}" EventSourceName="Process Exit Monitor" />
    <EventID Qualifiers="16384">3001</EventID>
    <Version>0</Version>
    <Level>4</Level>
    <Task>0</Task>
    <Opcode>0</Opcode>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2018-08-31T13:26:09.988216500Z" />
    <EventRecordID>4853</EventRecordID>
    <Correlation />
    <Execution ProcessID="0" ThreadID="0" />
    <Channel>Application</Channel>
    <Computer>PC</Computer>
    <Security UserID="S-1-5-18" />
  </System>
  <EventData Name="EVENT_PROCESSTERMINATION_CROSSPROCESS">
    <Data Name="param1">APPLICATIONPATH\APPLICATIONNAME.exe</Data>
    <Data Name="param2">C:\Windows\System32\svchost.exe</Data>
    <Data Name="param3">1067</Data>
    <Data Name="param4">01d43ed2aee892ab</Data>
  </EventData>
</Event>

ЗАМЕЧАНИЯ: ПК не выключается в момент завершения работы приложения, и в журналах событий отсутствуют какие-либо другие указания относительно того, почему процесс был остановлен.

ОБНОВЛЕНИЕ 1: Здесь несколько дополнительных деталей (пытаясь ответить столько же, сколько в комментариях):

  • Процесс (иногда) запускается через TaskScheduler, когда Windows запускается да. В другое время пользователем. Не совсем уверен, что проблема возникает только при запуске через TaskScheduler. Но интересный момент? Может ли Windows по какой-то причине убить задачу? Обратите внимание, что время между выходом из процесса может составлять до месяца.
  • У нас есть исходный код для основной программы, но могут возникнуть проблемы с его запуском в отладчике, так как он выполняется на клиенте, но, возможно,. Мы не можем запустить его скомпилировано для отладки. Вовсе нет, из-за производительности. Это живое производство.
  • Приложение - это обычное приложение WPF без каких-либо дочерних процессов или какого-либо другого межпроцессного взаимодействия. Он использует несколько сторонних устройств, например, библиотеки и драйверы.
  • У нас есть настроенная обработка событий исключений приложений, доменов приложений и т.д. Ничего из этого не происходит. Процесс завершается без каких-либо признаков возникновения исключения. Это сложный процесс выхода.
  • Мы подозревали, что источником может быть сторонний драйвер, но как? И как мы могли определить, было ли это так?

ОБНОВЛЕНИЕ 2: Мы используем пакет TaskScheduler для настройки задачи с помощью кода. Обратите внимание, что мы не устанавливаем ExecutionTimeLimit, который, следовательно, должен быть Nothing и, следовательно, бесконечным.

using (TaskService m_service = new TaskService())
 {
     var task = m_service.NewTask();

     task.Principal.UserId = userId;
     task.Principal.LogonType = TaskLogonType.InteractiveToken;
     task.Principal.RunLevel = TaskRunLevel.Highest;

     task.Settings.Enabled = true;
     task.Settings.MultipleInstances = TaskInstancesPolicy.IgnoreNew;
     task.Settings.Hidden = false;

     // NOTICE: A subset of the following 4 settings will cause app to hang on Win10
     //task.Settings.AllowHardTerminate = true;
     //task.Settings.DisallowStartOnRemoteAppSession = false;
     //task.Settings.RunOnlyIfLoggedOn = true;

     var trigger = (LogonTrigger)task.Triggers.Add(new LogonTrigger());
     trigger.Enabled = true;
     trigger.UserId = userId;

     task.Actions.Add(new ExecAction(executableFilePath, arguments: null,
         workingDirectory: m_installDirectoryPath));

     if (!IsAdministrator())
     {
         var message = "Cannot register task with your current identity's permissions level.";
         m_logger.Error(message);
     }
     m_service.RootFolder.RegisterTaskDefinition(taskName, task, TaskCreation.Create,
         userId, password: null, logonType: TaskLogonType.InteractiveToken);
 }

ОБНОВЛЕНИЕ 3: Возможно, вышеупомянутое утверждение было неверным, по умолчанию в библиотеке TaskScheduler кажется, 3 дня или 72 часа.

//
// Summary:
//     Gets or sets the amount of time that is allowed to complete the task. By default,
//     a task will be stopped 72 hours after it starts to run.
//
// Remarks:
//     If a task is started on demand, the ExecutionTimeLimit setting is bypassed. Therefore,
//     a task that is started on demand will not be terminated if it exceeds the ExecutionTimeLimit.
[DefaultValue(typeof(TimeSpan), "3")]
public TimeSpan ExecutionTimeLimit { get; set; }

ОБНОВЛЕНИЕ 4: Единственное, что мы наблюдаем, - тихий процесс завершается после того, как процесс запущен гораздо дольше, чем 3 дня, например, 30 дней, поэтому не уверен, что это так.

ОБНОВЛЕНИЕ 5: более 3 дней не было правильно соблюдено, поэтому после всего, что теперь стало ясно, это было связано с неправильными настройками для задачи планировщика задач. Неправильные настройки показаны ниже:

Неправильные настройки планировщика заданий

Правильные настройки:

Настройки планировщика заданий правильные

2 ответа2

0

Я думаю, что информация, которую вы предоставляете в своем посте, основана на фактах.

Например, код завершения 1067 означает «ERROR_PROCESS_ABORTED - процесс неожиданно завершен».

С другой стороны, трассировка стека, которую вы дали, по моему мнению, является просто обработкой события завершения вашей программы, то есть потока, который сделал автоматическое создание отчетов, поэтому не имеет никакой информации для добавления.

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

По моему опыту, самый простой и надежный способ найти проблему, требующий полного контроля над источниками продукта, - это скомпилировать продукт для отладки и запустить его в отладчике, установив точки останова на всех процедурах завершения работы системы. Для C это _exit и _abort , но могут быть и другие.

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

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

РЕДАКТИРОВАТЬ

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

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

Для лучшего анализа сбоев вы можете настроить параметры пользовательских дампов в Панели управления> Система> Дополнительные параметры системы> вкладка "Дополнительно"> "Запуск и восстановление"> "Настройки"> "Запись отладочной информации", установите для нее "Полный дамп памяти" и OK.

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

  • Файл дампа и символов должен быть сгенерирован одной и той же исполняемой версией
  • Дамп должен быть расположен при анализе в той же папке, что и при создании (C:\some-path\ etc.)
0

Это просто теория, но, может быть, поскольку она запущена с запланированной задачей, то каким-то образом планировщик задач все еще имеет "родительский" контроль над процессом после его запуска? Мне может показаться, что может быть какое-то условие, которое достигнуто или проблема, когда планировщик задач Windows останавливает задачу. Возможно, вам следует попробовать запустить его с помощью команды запуска, чтобы приложение запускалось, но "запланированное задание" было разрешено завершить, и, следовательно, управление приложением освобождается из планировщика задач Windows.

EG C:\Windows\System32\cmd.exe /c запускает "заголовок" C:\Windows\System32\notepad.exe

(или любая другая программа, которую вы запускаете)

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .