尝试使用 C++ 创建计划任务运行一次,在 win7 上使用 Task Scheduler 1.0 [英] Trying to create a scheduled task to run once using C++ , Task Scheduler 1.0 on win7

查看:302
本文介绍了尝试使用 C++ 创建计划任务运行一次,在 win7 上使用 Task Scheduler 1.0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个非常简单的程序,该程序将在两分钟后运行记事本(这些都经过简化以提出更清晰的问题).我试图合并一些 MSDN示例 令我惊讶的是,所有内容都编译成功,运行程序时,在 C:\Windows\Tasks 中创建了一个 .job 任务.我在任务计划程序"GUI 程序中没有看到新任务,我认为这是因为任务计划程序"只显示任务计划程序 2.0 任务,但我不确定.问题是任务没有被执行.我附上了代码,它有点长但有据可查.

有人可以帮忙解决这个问题吗?如果任务在运行时出错,它记录在哪里?

注意 1:我知道我计算开始时间的方式并不理想(并且会在分钟为 >57 的时间给出错误的结果).正如我之前所说,下面的代码是一个简化版本.

注意 2:我在 win7 上运行它,我认为它与 Task Scheduler 1.0 API 兼容.这段代码应该可以在 XP 和 win7 机器上运行(希望将来可以在 win 8 上运行)

注意 3:对于任何有勇气尝试的人,如果您收到错误 0x80070050,则表示该名称的任务已存在,请删除 .job 文件或更改名称.

#include #include #include 

#include #include #include #include #include int main(int argc, char **argv){HRESULT hr = S_OK;ITaskScheduler *pITS;//////////////////////////////////////////////////////////////////调用 CoInitialize 初始化 COM 库,然后//调用 CoCreateInstance 来获取 Task Scheduler 对象.////////////////////////////////////////////////////////////////hr = CoInitialize(NULL);如果(成功(小时)){hr = CoCreateInstance(CLSID_CTaskScheduler,空值,CLSCTX_INPROC_SERVER,IID_ITaskScheduler,(无效**) &pITS);如果(失败(小时)){CoUninitialize();返回 1;}}别的{返回 1;}//////////////////////////////////////////////////////////////////调用 ITaskScheduler::NewWorkItem 创建新任务.////////////////////////////////////////////////////////////////LPCWSTR pwszTaskName;ITask *pITask;IPersistFile *pIPersistFile;pwszTaskName = L"测试任务";hr = pITS->NewWorkItem(pwszTaskName,//任务名称CLSID_CTask,//类标识符IID_ITask,//接口标识符(IUnknown**)&pITask);//任务地址// 界面坑->释放();//释放对象如果(失败(小时)){CoUninitialize();fprintf(stderr, "调用 NewWorkItem 失败,错误 = 0x%x\n",hr);返回 1;}//////////////////////////////////////////////////////////////////设置注释、名称、工作目录、参数////////////////////////////////////////////////////////////////pITask->SetComment(L"这是一条评论");pITask->SetApplicationName(L"C:\\Windows\\System32\\notepad.exe");pITask->SetWorkingDirectory(L"C:\\Windows\\System32");pITask->SetParameters(L"");////////////////////////////////////////////////////////////////////调用 ITask::CreateTrigger 来创建新的触发器.//////////////////////////////////////////////////////////////////ITaskTrigger *pITaskTrigger;字 piNewTrigger;hr = pITask->CreateTrigger(&piNewTrigger,&pITaskTrigger);如果(失败(小时)){wprintf(L"调用 ITask::CreatTrigger 失败:");wprintf(L"error = 0x%x\n",hr);pITask->Release();CoUninitialize();返回 1;}///////////////////////////////////////////////////////定义 TASK_TRIGGER 结构.请注意,wBeginDay,//wBeginMonth 和 wBeginYear 必须设置为一个有效的//分别为日、月和年./////////////////////////////////////////////////////TASK_TRIGGER pTrigger;ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));LPSYSTEMTIME lpSystemTime;获取本地时间(lpSystemTime);//添加设置触发器结构的代码?pTrigger.wBeginDay = lpSystemTime->wDay;//必需的pTrigger.wBeginMonth = lpSystemTime->wMonth;//必需的pTrigger.wBeginYear =lpSystemTime->wYear;//必需的pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);pTrigger.wStartHour = lpSystemTime->wHour;pTrigger.wStartMinute = lpSystemTime->wMinute + 2;pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;pTrigger.Type.Daily.DaysInterval = 1;////////////////////////////////////////////////////////////////////调用 ITaskTrigger::SetTrigger 来设置触发条件.//////////////////////////////////////////////////////////////////hr = pITaskTrigger->SetTrigger(&pTrigger);如果(失败(小时)){wprintf(L"调用 ITaskTrigger::SetTrigger 失败:");wprintf(L"error = 0x%x\n",hr);pITask->Release();pITaskTrigger->Release();CoUninitialize();返回 1;}//////////////////////////////////////////////////////////////////调用 IUnknown::QueryInterface 以获取指向//IPersistFile 和 IPersistFile::Save 保存//将新任务写入磁盘.////////////////////////////////////////////////////////////////hr = pITask->QueryInterface(IID_IPersistFile,(void **)&pIPersistFile);pITask->Release();如果(失败(小时)){CoUninitialize();fprintf(stderr, "调用查询接口失败,错误 = 0x%x\n",hr);返回 1;}hr = pIPersistFile->Save(NULL,真的);pIPersistFile->Release();如果(失败(小时)){CoUninitialize();fprintf(stderr, "调用保存失败,错误 = 0x%x\n",hr);返回 1;}CoUninitialize();printf("已创建任务.\n");返回0;}

我添加了以下内容:

/////////////////////////////////////////////////////////////////设置标志////////////////////////////////////////////////////////////////pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);

和:

///////////////////////////////////////////////////////////////////调用 ITask::SetAccountInformation 指定账户名//和测试任务的帐户密码.//////////////////////////////////////////////////////////////////hr = pITask->SetAccountInformation(L"",空值);如果(失败(小时)){wprintf(L"调用 ITask::SetAccountInformation 失败:");wprintf(L"error = 0x%x\n",hr);pITask->Release();CoUninitialize();返回 1;}

现在任务显示在任务计划程序中,并在 SYSTEM 帐户下执行(Notepad.exe 不显示,因为 SYSTEM 帐户不与桌面或其他东西交互).如果我将其更改为 hr = pITask->SetAccountInformation(L"MyUserName", NULL); 则显示记事本.问题解决了:)

解决方案

设置标志:

pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);

设置账户信息:

hr = pITask->SetAccountInformation(L"用户名",空值);

鲍勃是你的叔叔

I'm trying to create a very simple program which will run Notepad after two minutes (these are all simplified to make a clearer question). I tried to merge some of MSDN's examples and to my surprise everything compiled successfully, when running the program a .job task is created in C:\Windows\Tasks. I don't see the new task in the "Task Scheduler" GUI program and I assume this is because "Task Scheduler" shows only Task Scheduler 2.0 tasks, but I'm not sure. The problem is that the task is not being executed. I'm attaching the code, it is a bit long but well documented.

Can someone help figuring this out? If a task got an error when running where is it logged?

Note 1: I know the way I'm calculating the start time is not ideal (and will give faulty results on times where minutes is >57). As I said before the code below is a simplified version.

Note 2: I'm running it on win7 and I assume it is compatible with Task Scheduler 1.0 API. This code should run on both XP and win7 machines (and hopefully on win 8 in the future)

Note 3: To anyone who's brave enough to try it, if you get error 0x80070050 it means that a task with that name already exists, delete the .job file or change the name.

#include <windows.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <objidl.h>
#include <wchar.h>
#include <stdio.h>


int main(int argc, char **argv)
{
  HRESULT hr = S_OK;
  ITaskScheduler *pITS;


  /////////////////////////////////////////////////////////////////
  // Call CoInitialize to initialize the COM library and then 
  // call CoCreateInstance to get the Task Scheduler object. 
  /////////////////////////////////////////////////////////////////
  hr = CoInitialize(NULL);
  if (SUCCEEDED(hr))
  {
     hr = CoCreateInstance(CLSID_CTaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskScheduler,
                           (void **) &pITS);
     if (FAILED(hr))
     {
        CoUninitialize();
        return 1;
     }
  }
  else
  {
     return 1;
  }


  /////////////////////////////////////////////////////////////////
  // Call ITaskScheduler::NewWorkItem to create new task.
  /////////////////////////////////////////////////////////////////
  LPCWSTR pwszTaskName;
  ITask *pITask;
  IPersistFile *pIPersistFile;
  pwszTaskName = L"Test Task";

  hr = pITS->NewWorkItem(pwszTaskName,         // Name of task
                         CLSID_CTask,          // Class identifier 
                         IID_ITask,            // Interface identifier
                         (IUnknown**)&pITask); // Address of task 
                                                                                                                                                                                            //  interface


  pITS->Release();                               // Release object
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling NewWorkItem, error = 0x%x\n",hr);
     return 1;
  }

  /////////////////////////////////////////////////////////////////
  //Set Comment, Name, Working dir, Params
  /////////////////////////////////////////////////////////////////
  pITask->SetComment(L"This is a comment");
  pITask->SetApplicationName(L"C:\\Windows\\System32\\notepad.exe");
  pITask->SetWorkingDirectory(L"C:\\Windows\\System32");
  pITask->SetParameters(L"");

  ///////////////////////////////////////////////////////////////////
  // Call ITask::CreateTrigger to create new trigger.
  ///////////////////////////////////////////////////////////////////

  ITaskTrigger *pITaskTrigger;
  WORD piNewTrigger;
  hr = pITask->CreateTrigger(&piNewTrigger,
                             &pITaskTrigger);
  if (FAILED(hr))
  {
    wprintf(L"Failed calling ITask::CreatTrigger: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    CoUninitialize();
    return 1;
  }

//////////////////////////////////////////////////////
  // Define TASK_TRIGGER structure. Note that wBeginDay,
  // wBeginMonth, and wBeginYear must be set to a valid 
  // day, month, and year respectively.
  //////////////////////////////////////////////////////

  TASK_TRIGGER pTrigger;
  ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));

  LPSYSTEMTIME lpSystemTime;
  GetLocalTime(lpSystemTime);


  // Add code to set trigger structure?
  pTrigger.wBeginDay = lpSystemTime->wDay;                  // Required
  pTrigger.wBeginMonth = lpSystemTime->wMonth;                // Required
  pTrigger.wBeginYear =lpSystemTime->wYear;              // Required
  pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER); 
  pTrigger.wStartHour = lpSystemTime->wHour;
  pTrigger.wStartMinute = lpSystemTime->wMinute + 2;
  pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
  pTrigger.Type.Daily.DaysInterval = 1;


  ///////////////////////////////////////////////////////////////////
  // Call ITaskTrigger::SetTrigger to set trigger criteria.
  ///////////////////////////////////////////////////////////////////

  hr = pITaskTrigger->SetTrigger (&pTrigger);
  if (FAILED(hr))
  {
    wprintf(L"Failed calling ITaskTrigger::SetTrigger: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    pITaskTrigger->Release();
    CoUninitialize();
    return 1;
  }




  /////////////////////////////////////////////////////////////////
  // Call IUnknown::QueryInterface to get a pointer to 
  // IPersistFile and IPersistFile::Save to save 
  // the new task to disk.
  /////////////////////////////////////////////////////////////////

  hr = pITask->QueryInterface(IID_IPersistFile,
                              (void **)&pIPersistFile);

  pITask->Release();
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling QueryInterface, error = 0x%x\n",hr);
     return 1;
  }


  hr = pIPersistFile->Save(NULL,
                           TRUE);
  pIPersistFile->Release();
  if (FAILED(hr))
  {
     CoUninitialize();
     fprintf(stderr, "Failed calling Save, error = 0x%x\n",hr);
     return 1;
  }


  CoUninitialize();
  printf("Created task.\n");
  return 0;
}

EDIT:

I added the following:

  /////////////////////////////////////////////////////////////////
  //Set Flags
  /////////////////////////////////////////////////////////////////

  pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);

and:

///////////////////////////////////////////////////////////////////
  // Call ITask::SetAccountInformation to specify the account name
  // and the account password for Test Task.
  ///////////////////////////////////////////////////////////////////
  hr = pITask->SetAccountInformation(L"", 
            NULL);


  if (FAILED(hr))
  {
    wprintf(L"Failed calling ITask::SetAccountInformation: ");
    wprintf(L"error = 0x%x\n",hr);
    pITask->Release();
    CoUninitialize();
    return 1;
  }

Now the task is getting displayed in the task scheduler and is being executed under SYSTEM account (Notepad.exe is not displayed since SYSTEM account is not interactive with desktop or something). If I change it to hr = pITask->SetAccountInformation(L"MyUserName", NULL); then Notepad is being displayed. Problem solved :).

解决方案

Set Flags:

pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);

Set account information:

hr = pITask->SetAccountInformation(L"Username", 
            NULL);

And Bob's your uncle

这篇关于尝试使用 C++ 创建计划任务运行一次,在 win7 上使用 Task Scheduler 1.0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆