Системное программирование в среде Windows
Шрифт:
{
HANDLE hJobData, hProcess;
JM_JOB JobRecord;
DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;
TCHAR JobMgtFileName[MAX_PATH];
OVERLAPPED RegionStart;
if (!GetJobMgtFileName(JobMgtFileName)) return –1;
/* Предоставление результата в виде строки "\tmp\UserName.JobMgt" */
hJobData = CreateFile(JobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hJobData == INVALID_HANDLE_VALUE) return –1;
/*
Блокировать весь файл плюс одну возможную запись для получения исключительного доступа. */
RegionStart.Offset = 0;
RegionStart.OffsetHigh = 0;
RegionStart.hEvent = (HANDLE)0;
FsLow = GetFileSize(hJobData, &FsHigh);
LockFileEx(hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, FsLow + SJM_JOB, 0, &RegionStart);
__try {
/* Чтение записи для нахождения пустого сегмента. */
while(ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) {
if (JobRecord.ProcessId == 0) break;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, JobRecord.ProcessId);
if (hProcess == NULL) break;
if (GetExitCodeProcess(hProcess, &ExitCode) && (ExitCode != STILL_ACTIVE)) break;
JobNumber++;
}
/* Либо найден пустой сегмент, либо мы находимся в конце файла и должны создать новый сегмент. */
if (nXfer != 0) /* Не конец файла. Резервировать. */
SetFilePointer(hJobData, –(LONG)SJM_JOB, NULL, FILE_CURRENT);
JobRecord.ProcessId = pProcessInfo->dwProcessId;
_tcsnccpy(JobRecord.CommandLine, Command, MAX_PATH);
WriteFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);
} /* Конец try-блока. */
__finally {
UnlockFileEx(hJobData, 0, FsLow + SJM_JOB, 0, &RegionStart);
CloseHandle(hJobData);
}
return JobNumber + 1;
}
Вывод списка фоновых задач
Программа 6.5 реализует функцию управления задачами DisplayJobs.
Программа 6.5. JobMgt: отображение списка активных задач
BOOL DisplayJobs(void)
/* Просмотреть файл базы данных, сообщить статус задачи. */
{
HANDLE hJobData, hProcess;
JM_JOB JobRecord;
DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;
TCHAR JobMgtFileName[MAX_PATH];
OVERLAPPED RegionStart;
GetJobMgtFileName(JobMgtFileName);
hJobData = CreateFile(JobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
RegionStart.Offset = 0;
RegionStart.OffsetHigh = 0;
RegionStart.hEvent = (HANDLE)0;
FsLow = GetFileSize(hJobData, &FsHigh);
LockFileEx(hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, FsLow, FsHigh, &RegionStart);
__try {
while(ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) {
JobNumber++;
if (JobRecord.ProcessId == 0) continue;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, JobRecord.ProcessId);
if (hProcess != NULL) GetExitCodeProcess(hProcess, &ExitCode);
_tprintf(_T(" [%d] "), JobNumber);
if (hProcess == NULL) _tprintf(_T("
Готово"));
else if (ExitCode != STILL_ACTIVE) _tprintf(_T("+ Готово"));
else _tprintf(_T(" "));
_tprintf(_T(" %s\n"), JobRecord.CommandLine);
/* Удалить процессы, которые в системе уже не присутствуют. */
if (hProcess == NULL) {
/* Зарезервировать одну запись. */
SetFilePointer(hJobData, –(LONG)nXfer, NULL, FILE_CURRENT);
JobRecord.ProcessId = 0;
WriteFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);
}
} /* Конец цикла while. */
} /* Конец __try-блока. */
__finally {
UnlockFileEx(hJobData, 0, FsLow, FsHigh, &RegionStart);
CloseHandle(hJobData);
}
return TRUE;
}
Поиск задачи в файле списка задач
Программа 6.6 представляет последнюю функцию управления задачами, FindProcessID, которая получает идентификатор процесса, соответствующего задаче с указанным номером. В свою очередь, идентификатор процесса может использоваться вызывающей программой для получения дескриптора и другой информации о состоянии процесса.
Программа 6.6. JobMgt: получение идентификатора процесса по номеру задачи
DWORD FindProcessId(DWORD JobNumber)
/* Получить ID процесса для задачи с указанным номером. */
{
HANDLE hJobData;
JM_JOB JobRecord;
DWORD nXfer;
TCHAR JobMgtFileName[MAX_PATH];
OVERLAPPED RegionStart;
/* Открыть файл управления задачами. */
Поделиться с друзьями: