diff --git a/README.md b/README.md
index 54fba9a..3f50559 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,319 @@
-# AutoRun_Task_Test
+# 创建计划任务实现开机自启动
-创建计划任务实现开机自启动
\ No newline at end of file
+# 背景
+
+想必实现程序开机自启动,是很常见的功能了。无论是恶意程序,还是正常的应用软件,都会提供这个功能,方便用户的使用。程序开机自启动,顾名思义,就是计算机开机后,不用人为地去运行程序,程序就可以自己运行起来。对于这个功能的,一直都是杀软重点监测的地方。因为,对于病毒来说,重要的不是如何被破坏,而是如何启动。
+
+在过去写的大大小小的程序中,我也实现过程序自启动的功能。现在,我把这些自启动功能的实现方式进行下总结。常见的方式有:修改开机自启动注册表、开机自启动目录、创建开机自启计划任务、创建开机自启系统服务等方式。现在对这些技术一一进行分析,并形成文档分享给大家。本文介绍的是创建自启动任务计划实现开机自启动的方式,其它的实现方式可以搜索我写的相关系列的文档。
+
+# 实现原理
+
+我是使用Windows Shell编程实现创建任务计划,所以会涉及COM组件相关知识。
+
+现在,为方便大家的理解,我把整个程序的逻辑概括为 3 各部分,分别是:初始化操作、创建任务计划以及删除任务计划。现在,我们一一对每一个部分进行解析。
+
+## 初始化操作
+
+初始化操作的目的就是获取 ITaskService 对象以及 ITaskFolder 对象,我们创建任务计划,主要是对这两个指针进行操作。具体流程是:
+
+- 首先初始化COM接口环境,因为我们接下来会使用到COM组件
+
+- 然后,创建 ITaskService 对象,并连接到任务服务上
+
+- 接着,从 ITaskService 对象中获取 ITaskFolder 对象
+
+这样,初始化操作就完成了,接下来就是直接使用 ITaskService 对象以及 ITaskFolder 对象进行操作了。
+
+## 创建任务计划
+
+现在,解析下任务计划的具体创建过程:
+
+- 首先,从 ITaskService 对象中创建一个任务定义对象 ITaskDefinition,用来来创建任务
+
+- 接着,就是开始对任务定义对象 ITaskDefinition进行设置:
+
+ - 设置注册信息,包括设置作者的信息
+
+ - 设置主体信息,包括登陆类型、运行权限
+
+ - 设置设置信息,包括设置在使用电池运行时是否停止、在使用电池是是否允许运行、是否允许手动运行、是否设置多个实例
+
+ - 设置操作信息,包括启动程序,并设置运行程序的路径和参数
+
+ - 设置触发器信息,包括用户登录时触发
+
+- 最后,使用 ITaskFolder 对象根据任务定义对象 ITaskDefinition的设置,注册任务计划
+
+这样,任务计划创建的操作就完成了,只要满足设置的触发条件,那么就会启动指定程序。
+
+## 删除任务计划
+
+ ITaskFolder 对象存储着已经注册成功的任务计划的信息,我们只需要将任务计划的名称传入其中,调用DeleteTask接口函数,就可以删除指定的任务计划了。
+
+# 编码实现
+
+## 创建任务计划的初始化
+
+```c++
+CMyTaskSchedule::CMyTaskSchedule(void)
+{
+ m_lpITS = NULL;
+ m_lpRootFolder = NULL;
+ // 初始化COM
+ HRESULT hr = ::CoInitialize(NULL);
+ if(FAILED(hr))
+ {
+ ShowError("CoInitialize", hr);
+ }
+ // 创建一个任务服务(Task Service)实例
+ hr = ::CoCreateInstance(CLSID_TaskScheduler,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_ITaskService,
+ (LPVOID *)(&m_lpITS));
+ if(FAILED(hr))
+ {
+ ShowError("CoCreateInstance", hr);
+ }
+ // 连接到任务服务(Task Service)
+ hr = m_lpITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::Connect", hr);
+ }
+ // 获取Root Task Folder的指针,这个指针指向的是新注册的任务
+ hr = m_lpITS->GetFolder(_bstr_t("\\"), &m_lpRootFolder);
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::GetFolder", hr);
+ }
+}
+```
+
+## 创建任务计划
+
+```c++
+BOOL CMyTaskSchedule::NewTask(char *lpszTaskName, char *lpszProgramPath, char *lpszParameters, char *lpszAuthor)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ // 如果存在相同的计划任务,则删除
+ Delete(lpszTaskName);
+ // 创建任务定义对象来创建任务
+ ITaskDefinition *pTaskDefinition = NULL;
+ HRESULT hr = m_lpITS->NewTask(0, &pTaskDefinition);
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::NewTask", hr);
+ return FALSE;
+ }
+
+ /* 设置注册信息 */
+ IRegistrationInfo *pRegInfo = NULL;
+ CComVariant variantAuthor(NULL);
+ variantAuthor = lpszAuthor;
+ hr = pTaskDefinition->get_RegistrationInfo(&pRegInfo);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_RegistrationInfo", hr);
+ return FALSE;
+ }
+ // 设置作者信息
+ hr = pRegInfo->put_Author(variantAuthor.bstrVal);
+ pRegInfo->Release();
+
+ /* 设置登录类型和运行权限 */
+ IPrincipal *pPrincipal = NULL;
+ hr = pTaskDefinition->get_Principal(&pPrincipal);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Principal", hr);
+ return FALSE;
+ }
+ // 设置登录类型
+ hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
+ // 设置运行权限
+ // 最高权限
+ hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
+ pPrincipal->Release();
+
+ /* 设置其他信息 */
+ ITaskSettings *pSettting = NULL;
+ hr = pTaskDefinition->get_Settings(&pSettting);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Settings", hr);
+ return FALSE;
+ }
+ // 设置其他信息
+ hr = pSettting->put_StopIfGoingOnBatteries(VARIANT_FALSE);
+ hr = pSettting->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
+ hr = pSettting->put_AllowDemandStart(VARIANT_TRUE);
+ hr = pSettting->put_StartWhenAvailable(VARIANT_FALSE);
+ hr = pSettting->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
+ pSettting->Release();
+
+ /* 创建执行动作 */
+ IActionCollection *pActionCollect = NULL;
+ hr = pTaskDefinition->get_Actions(&pActionCollect);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Actions", hr);
+ return FALSE;
+ }
+ IAction *pAction = NULL;
+ // 创建执行操作
+ hr = pActionCollect->Create(TASK_ACTION_EXEC, &pAction);
+ pActionCollect->Release();
+
+ /* 设置执行程序路径和参数 */
+ CComVariant variantProgramPath(NULL);
+ CComVariant variantParameters(NULL);
+ IExecAction *pExecAction = NULL;
+ hr = pAction->QueryInterface(IID_IExecAction, (PVOID *)(&pExecAction));
+ if(FAILED(hr))
+ {
+ pAction->Release();
+ ShowError("IAction::QueryInterface", hr);
+ return FALSE;
+ }
+ pAction->Release();
+ // 设置程序路径和参数
+ variantProgramPath = lpszProgramPath;
+ variantParameters = lpszParameters;
+ pExecAction->put_Path(variantProgramPath.bstrVal);
+ pExecAction->put_Arguments(variantParameters.bstrVal);
+ pExecAction->Release();
+
+ /* 创建触发器,实现用户登陆自启动 */
+ ITriggerCollection *pTriggers = NULL;
+ hr = pTaskDefinition->get_Triggers(&pTriggers);
+ if (FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Triggers", hr);
+ return FALSE;
+ }
+ // 创建触发器
+ ITrigger *pTrigger = NULL;
+ hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger);
+ if (FAILED(hr))
+ {
+ ShowError("ITriggerCollection::Create", hr);
+ return FALSE;
+ }
+
+ /* 注册任务计划 */
+ IRegisteredTask *pRegisteredTask = NULL;
+ CComVariant variantTaskName(NULL);
+ variantTaskName = lpszTaskName;
+ hr = m_lpRootFolder->RegisterTaskDefinition(variantTaskName.bstrVal,
+ pTaskDefinition,
+ TASK_CREATE_OR_UPDATE,
+ _variant_t(),
+ _variant_t(),
+ TASK_LOGON_INTERACTIVE_TOKEN,
+ _variant_t(""),
+ &pRegisteredTask);
+ if(FAILED(hr))
+ {
+ pTaskDefinition->Release();
+ ShowError("ITaskFolder::RegisterTaskDefinition", hr);
+ return FALSE;
+ }
+ pTaskDefinition->Release();
+ pRegisteredTask->Release();
+
+ return TRUE;
+}
+```
+
+## 删除任务计划
+
+```c++
+BOOL CMyTaskSchedule::Delete(char *lpszTaskName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ CComVariant variantTaskName(NULL);
+ variantTaskName = lpszTaskName;
+ HRESULT hr = m_lpRootFolder->DeleteTask(variantTaskName.bstrVal, 0);
+ if(FAILED(hr))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+```
+
+# 程序测试
+
+在 main 函数中调用上述封装好的函数,进行测试。main 函数为:
+
+```c++
+int _tmain(int argc, _TCHAR* argv[])
+{
+ CMyTaskSchedule task;
+ BOOL bRet = FALSE;
+
+ // 创建 任务计划
+ bRet = task.NewTask("520", "C:\\Users\\DemonGan\\Desktop\\520.exe", "", "");
+ if (FALSE == bRet)
+ {
+ printf("Create Task Schedule Error!\n");
+ }
+
+ // 暂停
+ printf("Create Task Schedule OK!\n");
+ system("pause");
+
+ // 卸载 任务计划
+ bRet = task.Delete("520");
+ if (FALSE == bRet)
+ {
+ printf("Delete Task Schedule Error!\n");
+ }
+
+ printf("Delete Task Schedule OK!\n");
+ system("pause");
+ return 0;
+}
+```
+
+测试结果:
+
+“以管理员身份运行程序”方式打开程序,提示任务计划创建成功。
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/e542bb6eec0f93c6ec02b4f50973d741.writebug)
+
+打开任务计划列表进行查看,发现“520”任务计划成功创建。
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/c7953c56b969f3394458c4d097bddfc9.writebug)
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/3566ef40f42abe9ab4365af312e51011.writebug)
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/9beb1edb6785e012fc6ef0d9888e06fe.writebug)
+
+然后,删除创建的任务计划,程序提示删除成功。
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/5b95c68abce032a5e9452dc216b8ec0c.writebug)
+
+查看任务计划列表,发现“520”任务计划已经成功删除。
+
+![](http://www.write-bug.com/myres/static/uploads/2021/10/19/e34a1e9c0c35d5ef284e8b235d1b3a7b.writebug)
+
+所以,测试成功。
+
+# 总结
+
+这个功能的实现涉及到COM组件的相关知识,所以初学者对此可能感到陌生,这是很正常的。其实,对于这方面的理解我也没有什么好的建议,只有多动手练几遍,加深程序逻辑和印象吧。
+
+注意的地方就是,创建任务计划,要求程序必须要有管机员权限才行。所以,测试的时候,不要忘记以管理员身份运行程序。
+
+# 参考
+
+参考自《[Windows黑客编程技术详解](https://www.write-bug.com/article/1811.html "Windows黑客编程技术详解")》一书
\ No newline at end of file
diff --git a/src/AutoRun_Task_Test.sln b/src/AutoRun_Task_Test.sln
new file mode 100644
index 0000000..924d00f
--- /dev/null
+++ b/src/AutoRun_Task_Test.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AutoRun_Task_Test", "AutoRun_Task_Test\AutoRun_Task_Test.vcxproj", "{72D26442-FF39-438F-A920-FFD8CBB9282A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {72D26442-FF39-438F-A920-FFD8CBB9282A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {72D26442-FF39-438F-A920-FFD8CBB9282A}.Debug|Win32.Build.0 = Debug|Win32
+ {72D26442-FF39-438F-A920-FFD8CBB9282A}.Release|Win32.ActiveCfg = Release|Win32
+ {72D26442-FF39-438F-A920-FFD8CBB9282A}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/AutoRun_Task_Test.v12.suo b/src/AutoRun_Task_Test.v12.suo
new file mode 100644
index 0000000..0e5a6d1
Binary files /dev/null and b/src/AutoRun_Task_Test.v12.suo differ
diff --git a/src/AutoRun_Task_Test/AutoRun_Task_Test.cpp b/src/AutoRun_Task_Test/AutoRun_Task_Test.cpp
new file mode 100644
index 0000000..af46835
--- /dev/null
+++ b/src/AutoRun_Task_Test/AutoRun_Task_Test.cpp
@@ -0,0 +1,35 @@
+// AutoRun_Task_Test.cpp : ̨Ӧóڵ㡣
+//
+
+#include "stdafx.h"
+#include "MyTaskSchedule.h"
+
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ CMyTaskSchedule task;
+ BOOL bRet = FALSE;
+
+ // ƻ
+ bRet = task.NewTask("520", "C:\\Users\\DemonGan\\Desktop\\520.exe", "", "");
+ if (FALSE == bRet)
+ {
+ printf("Create Task Schedule Error!\n");
+ }
+
+ // ͣ
+ printf("Create Task Schedule OK!\n");
+ system("pause");
+
+ // ж ƻ
+ bRet = task.Delete("520");
+ if (FALSE == bRet)
+ {
+ printf("Delete Task Schedule Error!\n");
+ }
+
+ printf("Delete Task Schedule OK!\n");
+ system("pause");
+ return 0;
+}
+
diff --git a/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj b/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj
new file mode 100644
index 0000000..48431b4
--- /dev/null
+++ b/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj
@@ -0,0 +1,99 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {72D26442-FF39-438F-A920-FFD8CBB9282A}
+ Win32Proj
+ AutoRun_Task_Test
+
+
+
+ Application
+ true
+ v120_xp
+ MultiByte
+
+
+ Application
+ false
+ v120_xp
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj.filters b/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj.filters
new file mode 100644
index 0000000..8d70140
--- /dev/null
+++ b/src/AutoRun_Task_Test/AutoRun_Task_Test.vcxproj.filters
@@ -0,0 +1,42 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ 头文件
+
+
+ 头文件
+
+
+ 头文件
+
+
+
+
+ 源文件
+
+
+ 源文件
+
+
+ 源文件
+
+
+
\ No newline at end of file
diff --git a/src/AutoRun_Task_Test/MyTaskSchedule.cpp b/src/AutoRun_Task_Test/MyTaskSchedule.cpp
new file mode 100644
index 0000000..eab5d6d
--- /dev/null
+++ b/src/AutoRun_Task_Test/MyTaskSchedule.cpp
@@ -0,0 +1,379 @@
+#include "stdafx.h"
+#include "MyTaskSchedule.h"
+
+
+void ShowError(char *lpszText, DWORD dwErrCode)
+{
+ char szErr[MAX_PATH] = {0};
+ ::wsprintf(szErr, "%s Error!\nError Code Is:0x%08x\n", lpszText, dwErrCode);
+ ::MessageBox(NULL, szErr, "ERROR", MB_OK | MB_ICONERROR);
+}
+
+
+CMyTaskSchedule::CMyTaskSchedule(void)
+{
+ m_lpITS = NULL;
+ m_lpRootFolder = NULL;
+ // ʼCOM
+ HRESULT hr = ::CoInitialize(NULL);
+ if(FAILED(hr))
+ {
+ ShowError("CoInitialize", hr);
+ }
+ // һTask Serviceʵ
+ hr = ::CoCreateInstance(CLSID_TaskScheduler,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_ITaskService,
+ (LPVOID *)(&m_lpITS));
+ if(FAILED(hr))
+ {
+ ShowError("CoCreateInstance", hr);
+ }
+ // ӵTask Service
+ hr = m_lpITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::Connect", hr);
+ }
+ // ȡRoot Task Folderָ룬ָָע
+ hr = m_lpITS->GetFolder(_bstr_t("\\"), &m_lpRootFolder);
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::GetFolder", hr);
+ }
+}
+
+
+CMyTaskSchedule::~CMyTaskSchedule(void)
+{
+ if(m_lpITS)
+ {
+ m_lpITS->Release();
+ }
+ if(m_lpRootFolder)
+ {
+ m_lpRootFolder->Release();
+ }
+ // жCOM
+ ::CoUninitialize();
+}
+
+
+BOOL CMyTaskSchedule::Delete(char *lpszTaskName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ CComVariant variantTaskName(NULL);
+ variantTaskName = lpszTaskName;
+ HRESULT hr = m_lpRootFolder->DeleteTask(variantTaskName.bstrVal, 0);
+ if(FAILED(hr))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::DeleteFolder(char *lpszFolderName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ CComVariant variantFolderName(NULL);
+ variantFolderName = lpszFolderName;
+ HRESULT hr = m_lpRootFolder->DeleteFolder(variantFolderName.bstrVal, 0);
+ if(FAILED(hr))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::NewTask(char *lpszTaskName, char *lpszProgramPath, char *lpszParameters, char *lpszAuthor)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ // ͬļƻɾ
+ Delete(lpszTaskName);
+ //
+ ITaskDefinition *pTaskDefinition = NULL;
+ HRESULT hr = m_lpITS->NewTask(0, &pTaskDefinition);
+ if(FAILED(hr))
+ {
+ ShowError("ITaskService::NewTask", hr);
+ return FALSE;
+ }
+
+ /* עϢ */
+ IRegistrationInfo *pRegInfo = NULL;
+ CComVariant variantAuthor(NULL);
+ variantAuthor = lpszAuthor;
+ hr = pTaskDefinition->get_RegistrationInfo(&pRegInfo);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_RegistrationInfo", hr);
+ return FALSE;
+ }
+ // Ϣ
+ hr = pRegInfo->put_Author(variantAuthor.bstrVal);
+ pRegInfo->Release();
+
+ /* õ¼ͺȨ */
+ IPrincipal *pPrincipal = NULL;
+ hr = pTaskDefinition->get_Principal(&pPrincipal);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Principal", hr);
+ return FALSE;
+ }
+ // õ¼
+ hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
+ // Ȩ
+ // Ȩ
+ hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
+ pPrincipal->Release();
+
+ /* Ϣ */
+ ITaskSettings *pSettting = NULL;
+ hr = pTaskDefinition->get_Settings(&pSettting);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Settings", hr);
+ return FALSE;
+ }
+ // Ϣ
+ hr = pSettting->put_StopIfGoingOnBatteries(VARIANT_FALSE);
+ hr = pSettting->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
+ hr = pSettting->put_AllowDemandStart(VARIANT_TRUE);
+ hr = pSettting->put_StartWhenAvailable(VARIANT_FALSE);
+ hr = pSettting->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
+ pSettting->Release();
+
+ /* ִж */
+ IActionCollection *pActionCollect = NULL;
+ hr = pTaskDefinition->get_Actions(&pActionCollect);
+ if(FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Actions", hr);
+ return FALSE;
+ }
+ IAction *pAction = NULL;
+ // ִв
+ hr = pActionCollect->Create(TASK_ACTION_EXEC, &pAction);
+ pActionCollect->Release();
+
+ /* ִг·Ͳ */
+ CComVariant variantProgramPath(NULL);
+ CComVariant variantParameters(NULL);
+ IExecAction *pExecAction = NULL;
+ hr = pAction->QueryInterface(IID_IExecAction, (PVOID *)(&pExecAction));
+ if(FAILED(hr))
+ {
+ pAction->Release();
+ ShowError("IAction::QueryInterface", hr);
+ return FALSE;
+ }
+ pAction->Release();
+ // ó·Ͳ
+ variantProgramPath = lpszProgramPath;
+ variantParameters = lpszParameters;
+ pExecAction->put_Path(variantProgramPath.bstrVal);
+ pExecAction->put_Arguments(variantParameters.bstrVal);
+ pExecAction->Release();
+
+ /* ʵû½ */
+ ITriggerCollection *pTriggers = NULL;
+ hr = pTaskDefinition->get_Triggers(&pTriggers);
+ if (FAILED(hr))
+ {
+ ShowError("pTaskDefinition::get_Triggers", hr);
+ return FALSE;
+ }
+ //
+ ITrigger *pTrigger = NULL;
+ hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger);
+ if (FAILED(hr))
+ {
+ ShowError("ITriggerCollection::Create", hr);
+ return FALSE;
+ }
+
+ /* עƻ */
+ IRegisteredTask *pRegisteredTask = NULL;
+ CComVariant variantTaskName(NULL);
+ variantTaskName = lpszTaskName;
+ hr = m_lpRootFolder->RegisterTaskDefinition(variantTaskName.bstrVal,
+ pTaskDefinition,
+ TASK_CREATE_OR_UPDATE,
+ _variant_t(),
+ _variant_t(),
+ TASK_LOGON_INTERACTIVE_TOKEN,
+ _variant_t(""),
+ &pRegisteredTask);
+ if(FAILED(hr))
+ {
+ pTaskDefinition->Release();
+ ShowError("ITaskFolder::RegisterTaskDefinition", hr);
+ return FALSE;
+ }
+ pTaskDefinition->Release();
+ pRegisteredTask->Release();
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::IsExist(char *lpszTaskName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ HRESULT hr = S_OK;
+ CComVariant variantTaskName(NULL);
+ CComVariant variantEnable(NULL);
+ variantTaskName = lpszTaskName; // ƻ
+ IRegisteredTask *pRegisteredTask = NULL;
+ // ȡƻ
+ hr = m_lpRootFolder->GetTask(variantTaskName.bstrVal, &pRegisteredTask);
+ if(FAILED(hr) || (NULL == pRegisteredTask))
+ {
+ return FALSE;
+ }
+ pRegisteredTask->Release();
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::IsTaskValid(char *lpszTaskName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ HRESULT hr = S_OK;
+ CComVariant variantTaskName(NULL);
+ CComVariant variantEnable(NULL);
+ variantTaskName = lpszTaskName; // ƻ
+ IRegisteredTask *pRegisteredTask = NULL;
+ // ȡƻ
+ hr = m_lpRootFolder->GetTask(variantTaskName.bstrVal, &pRegisteredTask);
+ if(FAILED(hr) || (NULL == pRegisteredTask))
+ {
+ return FALSE;
+ }
+ // ȡ״̬
+ TASK_STATE taskState;
+ hr = pRegisteredTask->get_State(&taskState);
+ if(FAILED(hr))
+ {
+ pRegisteredTask->Release();
+ return FALSE;
+ }
+ pRegisteredTask->Release();
+ // Ч
+ if(TASK_STATE_DISABLED == taskState)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::Run(char *lpszTaskName, char *lpszParam)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ HRESULT hr = S_OK;
+ CComVariant variantTaskName(NULL);
+ CComVariant variantParameters(NULL);
+ variantTaskName = lpszTaskName;
+ variantParameters = lpszParam;
+
+ // ȡƻ
+ IRegisteredTask *pRegisteredTask = NULL;
+ hr = m_lpRootFolder->GetTask(variantTaskName.bstrVal, &pRegisteredTask);
+ if(FAILED(hr) || (NULL == pRegisteredTask))
+ {
+ return FALSE;
+ }
+ //
+ hr = pRegisteredTask->Run(variantParameters, NULL);
+ if(FAILED(hr))
+ {
+ pRegisteredTask->Release();
+ return FALSE;
+ }
+ pRegisteredTask->Release();
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::IsEnable(char *lpszTaskName)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ HRESULT hr = S_OK;
+ CComVariant variantTaskName(NULL);
+ CComVariant variantEnable(NULL);
+ variantTaskName = lpszTaskName; // ƻ
+ IRegisteredTask *pRegisteredTask = NULL;
+ // ȡƻ
+ hr = m_lpRootFolder->GetTask(variantTaskName.bstrVal, &pRegisteredTask);
+ if(FAILED(hr) || (NULL == pRegisteredTask))
+ {
+ return FALSE;
+ }
+ // ȡǷѾ
+ pRegisteredTask->get_Enabled(&variantEnable.boolVal);
+ pRegisteredTask->Release();
+ if(ATL_VARIANT_FALSE == variantEnable.boolVal)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL CMyTaskSchedule::SetEnable(char *lpszTaskName, BOOL bEnable)
+{
+ if(NULL == m_lpRootFolder)
+ {
+ return FALSE;
+ }
+ HRESULT hr = S_OK;
+ CComVariant variantTaskName(NULL);
+ CComVariant variantEnable(NULL);
+ variantTaskName = lpszTaskName; // ƻ
+ variantEnable = bEnable; // Ƿ
+ IRegisteredTask *pRegisteredTask = NULL;
+ // ȡƻ
+ hr = m_lpRootFolder->GetTask(variantTaskName.bstrVal, &pRegisteredTask);
+ if(FAILED(hr) || (NULL == pRegisteredTask))
+ {
+ return FALSE;
+ }
+ // Ƿ
+ pRegisteredTask->put_Enabled(variantEnable.boolVal);
+ pRegisteredTask->Release();
+
+ return TRUE;
+}
+
diff --git a/src/AutoRun_Task_Test/MyTaskSchedule.h b/src/AutoRun_Task_Test/MyTaskSchedule.h
new file mode 100644
index 0000000..a95b239
--- /dev/null
+++ b/src/AutoRun_Task_Test/MyTaskSchedule.h
@@ -0,0 +1,50 @@
+#ifndef _MY_TASK_SCHEDULT_H_
+#define _MY_TASK_SCHEDULT_H_
+
+
+#include
+#include
+#include
+#pragma comment(lib, "taskschd.lib")
+
+
+class CMyTaskSchedule
+{
+private:
+
+ ITaskService *m_lpITS;
+ ITaskFolder *m_lpRootFolder;
+
+public:
+
+ CMyTaskSchedule(void);
+ ~CMyTaskSchedule(void);
+
+public:
+
+ // ɾָƻ
+ BOOL Delete(char *lpszTaskName);
+ BOOL DeleteFolder(char *lpszFolderName);
+
+ // ƻ
+ BOOL NewTask(char *lpszTaskName, char *lpszProgramPath, char *lpszParameters, char *lpszAuthor = "");
+
+ // жָƻǷ
+ BOOL IsExist(char *lpszTaskName);
+
+ // жָƻ״̬ǷЧ
+ BOOL IsTaskValid(char *lpszTaskName);
+
+ // ָƻ
+ BOOL Run(char *lpszTaskName, char *lpszParam);
+
+ // жָƻǷ
+ BOOL IsEnable(char *lpszTaskName);
+
+ // ָƻǷǽ
+ BOOL SetEnable(char *lpszTaskName, BOOL bEnable);
+
+};
+
+
+#endif
\ No newline at end of file
diff --git a/src/AutoRun_Task_Test/ReadMe.txt b/src/AutoRun_Task_Test/ReadMe.txt
new file mode 100644
index 0000000..c51450f
--- /dev/null
+++ b/src/AutoRun_Task_Test/ReadMe.txt
@@ -0,0 +1,30 @@
+========================================================================
+ 控制台应用程序:AutoRun_Task_Test 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 AutoRun_Task_Test 应用程序。
+
+本文件概要介绍组成 AutoRun_Task_Test 应用程序的每个文件的内容。
+
+
+AutoRun_Task_Test.vcxproj
+ 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+AutoRun_Task_Test.vcxproj.filters
+ 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
+
+AutoRun_Task_Test.cpp
+ 这是主应用程序源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+ 这些文件用于生成名为 AutoRun_Task_Test.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/AutoRun_Task_Test/stdafx.cpp b/src/AutoRun_Task_Test/stdafx.cpp
new file mode 100644
index 0000000..b9a1c1a
--- /dev/null
+++ b/src/AutoRun_Task_Test/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : ֻļԴļ
+// AutoRun_Task_Test.pch ΪԤͷ
+// stdafx.obj ԤϢ
+
+#include "stdafx.h"
+
+// TODO: STDAFX.H
+// κĸͷļڴļ
diff --git a/src/AutoRun_Task_Test/stdafx.h b/src/AutoRun_Task_Test/stdafx.h
new file mode 100644
index 0000000..baa4bbc
--- /dev/null
+++ b/src/AutoRun_Task_Test/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : ϵͳļİļ
+// Ǿʹõĵ
+// ضĿİļ
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include
+#include
+
+
+
+// TODO: ڴ˴óҪͷļ
diff --git a/src/AutoRun_Task_Test/targetver.h b/src/AutoRun_Task_Test/targetver.h
new file mode 100644
index 0000000..7a7d2c8
--- /dev/null
+++ b/src/AutoRun_Task_Test/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// SDKDDKVer.h õ߰汾 Windows ƽ̨
+
+// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h
+// WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h
+
+#include
diff --git a/src/Debug/AutoRun_Task_Test.exe b/src/Debug/AutoRun_Task_Test.exe
new file mode 100644
index 0000000..a083dab
Binary files /dev/null and b/src/Debug/AutoRun_Task_Test.exe differ