Windows提供了API函數:NetScheduleJobEnum可以用於枚舉Windows計劃任務(Schedule Job)。其C++原形為:
NET_API_STATUS NetScheduleJobEnum(<br /> __in_opt LPCWSTR Servername,<br /> __out LPBYTE *PointerToBuffer,<br /> __in DWORD PreferredMaximumLength,<br /> __out LPDWORD EntriesRead,<br /> __out LPDWORD TotalEntries,<br /> __inout LPDWORD ResumeHandle<br />);
(參數說明詳見:http://msdn.microsoft.com/en-us/library/aa370616(VS.85).aspx)
該函數執行成功的話,最後一個參數ResumeHandle包含指向了AT_ENUM結構數組指標,可枚舉的個數儲存在參數EntriesRead中。
在MASM32內建的 Windows.inc 中,AT_ENUM結構的定義如下:
AT_ENUM struct
JobId dd ?
JobTime dd ?
DaysOfMonth dd ?
DaysOfWeek UCHAR ?
Flags UCHAR ?
Command dd ?
AT_ENUM ends
這與MSDN網站上的是一致的:
typedef struct _AT_ENUM {<br /> DWORD JobId;<br /> DWORD_PTR JobTime;<br /> DWORD DaysOfMonth;<br /> UCHAR DaysOfWeek;<br /> UCHAR Flags;<br /> LPWSTR Command;<br />}AT_ENUM, *PAT_ENUM, *LPAT_ENUM;
(詳見:http://msdn.microsoft.com/en-us/library/aa370247(VS.85).aspx)
但程式輸出的枚舉結果不正確:第1個任務的JobId等資訊是正確的,但Command不正確。從2個任務開始,所有資訊都不正確。
經過測試發現,AT_ENUM實際長度位元組數要比上面定義的多2個位元組。
之所以會多出來2個位元組,是因為DaysOfWeek、Flags兩個成員的類型是UCHAR,也就是一個位元組的長度,為了對齊,Flags後面加了兩個位元組,AT_ENUM結構的實際定義如下:
_AT_ENUM struct
JobId dd ?
JobTime dd ?
DaysOfMonth dd ?
DaysOfWeek UCHAR ?
Flags UCHAR ?
align1 db ?
align2 db ?
Command dd ?
_AT_ENUM ends
這樣程式輸出的結果就正常了。完整的代碼如下:
(原始碼+EXE下載:
1、http://download.csdn.net/source/1795004
2、http://purpleendurer.ys168.com)
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 文 件 名:EnumTask.asm (控制台程式)
; 功 能: 枚舉通過At命令建立的計劃任務
; 開發環境:Win XP PRO SP3 + MASM32 v8
; 作 者:PurpleEndurer, 廣西河池
; log
; --------------------------------------------------
; 2009-11-05 將AT_ENUM 修改為 _AT_ENUM, OK!
; 2009-10-30
; 將
; add edi, sizeof AT_ENUM
; 改為
; add edi, sizeof AT_ENUM + 2
; 輸出的JobId, JobTime值正確,但Command值不對 :-(
; 2009-10-27 開始編寫
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.586
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE
INCLUDE /masm32/include/windows.inc
INCLUDE /masm32/include/kernel32.inc
INCLUDELIB /masm32/lib/kernel32.lib
INCLUDE /masm32/include/Netapi32.inc
INCLUDELIB /masm32/lib/Netapi32.lib
INCLUDE /masm32/include/user32.inc
INCLUDELIB /masm32/lib/user32.lib
INCLUDE /masm32/include/masm32.inc
INCLUDELIB /masm32/lib/masm32.lib
WriteJobList proto
FormatJobInfo proto :LPSTR
_AT_ENUM struct
JobId dd ?
JobTime dd ?
DaysOfMonth dd ?
DaysOfWeek UCHAR ?
Flags UCHAR ?
align1 db ?
align2 db ?
Command dd ?
_AT_ENUM ends
;ssssssssssssssssssssssss
.CODE
;ssssssssssssssssssssssss
g_szAppInfo db "Enum Schedule Task by PurpleEndurer with MASM32", 0dh, 0ah, 0
start:
invoke StdOut, addr g_szAppInfo
invoke WriteJobList
invoke ExitProcess, 0
g_szFail db "失敗資訊:", 0
;g_szFmtEAX db "(%d)", 0dh, 0ah, 0
g_szNoTask db "無計劃任務!", 0
WriteJobList proc
LOCAL pBuf: LPBYTE ;DWORD; ponter to _AT_ENUM
LOCAL dwRead, dwLeftBeforeCall, dwJobCount: DWORD
LOCAL buf512[512]: byte
mov dwLeftBeforeCall, 0
.repeat
invoke NetScheduleJobEnum, NULL, addr pBuf, MAX_PREFERRED_LENGTH/
, addr dwRead, addr dwJobCount, addr dwLeftBeforeCall
push eax
.if (eax != NERR_Success && eax != ERROR_MORE_DATA)
;push eax
;invoke wsprintf, addr buf512, addr g_szFmtEAX, eax
;invoke StdOut, addr buf512
;pop eax
invoke GetLastError
mov edi, eax
invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or/
FORMAT_MESSAGE_FROM_SYSTEM, NULL, edi, 0, addr pBuf, 0, NULL
test eax, eax
.IF !ZERO?
invoke StdOut, addr g_szFail
invoke StdOut, pBuf
invoke LocalFree, pBuf
.ENDIF
.else
mov edi, pBuf
test edi, edi
.if ZERO?
invoke StdOut, addr g_szNoTask
.break
.endif
.while (dwRead > 0)
push edi
invoke FormatJobInfo, addr buf512
invoke StdOut, addr buf512
pop edi
add edi, sizeof _AT_ENUM
dec dwRead
.endw
.IF (pBuf != NULL)
invoke NetApiBufferFree, pBuf
.ENDIF
.endif
pop eax
.until (eax != ERROR_MORE_DATA)
ret
WriteJobList endp
;////////////////////////////////////////////////////////
; 功能:格式化任務資訊
; 輸入:edi - 指向 _AT_ENUM 結構的指標
; lpszBuf - 指向儲存格式化任務資訊的緩衝區地址的指標
; 輸出:無
;////////////////////////////////////////////////////////
g_szFmt db 0dh, 0ah, "%08lu %02d:%02d %S", 0dh, 0ah, 0
FormatJobInfo proc lpszBuf: LPSTR
;-- 計算小時
mov eax, (_AT_ENUM ptr [edi]).JobTime
xor edx, edx
mov ecx, 3600000
div ecx
mov ebx, eax ;將小時值存入ebx
;-- 計算分鐘,存於eax
mov eax, edx
xor edx, edx
mov ecx, 60000
div ecx
invoke wsprintf, lpszBuf, addr g_szFmt, (_AT_ENUM ptr [edi]).JobId/
, ebx, eax, (_AT_ENUM ptr [edi]).Command
ret
FormatJobInfo endp
END start
可惜的是,NetScheduleJobEnum只能枚舉AT命令建立的計劃任務,不能枚舉“任務計劃”嚮導建立的任務。