Windows计划任务开机启动程序

前言

Windows下需要管理员权限的开机程序启动时,如果Windows UAC等级设置的比较高,那么总是会提示是否启动某某程序的对话框,这对于用户来说体验非常不好,但是通过计划任务来设置程序以管理员身份启动就可以完全避免。

下面是C++和C#的实现代码,直接拿来用即可。

C++代码

   此代码是参考MSDN的里面,稍微进行了一点修改。MSDN例子

#define _CRT_SECURE_NO_WARNINGS
#define _WIN32_DCOM
#include 
#include 
#include 
#include 
//  Include the task header file.
#include 
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")
using namespace std;
//是否存在指定名字的计划任务
bool IsExistScheduler(wchar_t *taskName)
{
	//  ------------------------------------------------------
//  Initialize COM.
	HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
	if (FAILED(hr))
	{
		return false;
	}
	//  Set general COM security levels.
	hr = CoInitializeSecurity(
		NULL,
		-1,
		NULL,
		NULL,
		RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
		RPC_C_IMP_LEVEL_IMPERSONATE,
		NULL,
		0,
		NULL);

	if (FAILED(hr))
	{
		CoUninitialize();
		return false;
	}

	//  ------------------------------------------------------
	//  Create a name for the task.
	LPCWSTR wszTaskName = taskName;

	//  ------------------------------------------------------
	//  Create an instance of the Task Service. 
	ITaskService *pService = NULL;
	hr = CoCreateInstance(CLSID_TaskScheduler,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_ITaskService,
		(void**)&pService);
	if (FAILED(hr))
	{
		printf("Failed to create an instance of ITaskService: %x", hr);
		CoUninitialize();
		return false;
	}

	//  Connect to the task service.
	hr = pService->Connect(_variant_t(), _variant_t(),
		_variant_t(), _variant_t());
	if (FAILED(hr))
	{
		printf("ITaskService::Connect failed: %x", hr);
		pService->Release();
		CoUninitialize();
		return false;
	}

	//  ------------------------------------------------------
	//  Get the pointer to the root task folder.  This folder will hold the
	//  new task that is registered.
	ITaskFolder *pRootFolder = NULL;
	hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
	if (FAILED(hr))
	{
		printf("Cannot get Root Folder pointer: %x", hr);
		pService->Release();
		CoUninitialize();
		return false;
	}
	//查看计划任务是否存在
	IRegisteredTask *ttt;
	auto ret=pRootFolder->GetTask(_bstr_t(wszTaskName),&ttt);
	if (ret != S_OK)
	{
		pRootFolder->Release();
		pService->Release();
		CoUninitialize();
		return false;
	}
	ttt->Release();
	pRootFolder->Release();
	pService->Release();
	CoUninitialize();
	return true;
}
//创建用户登录启动软件的任务
//taskName 任务名字
//executablePath 可执行文件路径
//creater 创建者
HRESULT LogonStartScheduler(wchar_t *taskName,wchar_t*executablePath,wchar_t *creater=NULL)
{
		//  ------------------------------------------------------
		//  Initialize COM.
		HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
		if (FAILED(hr))
		{
			return hr;
		}
		//  Set general COM security levels.
		hr = CoInitializeSecurity(
			NULL,
			-1,
			NULL,
			NULL,
			RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
			RPC_C_IMP_LEVEL_IMPERSONATE,
			NULL,
			0,
			NULL);

		if (FAILED(hr))
		{
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Create a name for the task.
		LPCWSTR wszTaskName = taskName;

		//  Get the windows directory and set the path to notepad.exe.
		wstring wstrExecutablePath = executablePath;


		//  ------------------------------------------------------
		//  Create an instance of the Task Service. 
		ITaskService *pService = NULL;
		hr = CoCreateInstance(CLSID_TaskScheduler,
			NULL,
			CLSCTX_INPROC_SERVER,
			IID_ITaskService,
			(void**)&pService);
		if (FAILED(hr))
		{
			printf("Failed to create an instance of ITaskService: %x", hr);
			CoUninitialize();
			return hr;
		}

		//  Connect to the task service.
		hr = pService->Connect(_variant_t(), _variant_t(),
			_variant_t(), _variant_t());
		if (FAILED(hr))
		{
			printf("ITaskService::Connect failed: %x", hr);
			pService->Release();
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Get the pointer to the root task folder.  This folder will hold the
		//  new task that is registered.
		ITaskFolder *pRootFolder = NULL;
		hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
		if (FAILED(hr))
		{
			printf("Cannot get Root Folder pointer: %x", hr);
			pService->Release();
			CoUninitialize();
			return hr;
		}
		//查看计划任务是否存在
		//IRegisteredTask *ttt;
		//auto ret=pRootFolder->GetTask(_bstr_t(L"OnebotStartScheduler"),&ttt);
		//if (ret == S_OK)
		//{
		//	ttt->Release();
		//	pRootFolder->Release();
		//	pService->Release();
		//	CoUninitialize();
		//	return 1;
		//}
		//  If the same task exists, remove it.
		pRootFolder->DeleteTask(_bstr_t(wszTaskName), 0);
		//  Create the task builder object to create the task.
		ITaskDefinition *pTask = NULL;
		hr = pService->NewTask(0, &pTask);

		pService->Release();  // COM clean up.  Pointer is no longer used.
		if (FAILED(hr))
		{
			printf("Failed to create a task definition: %x", hr);
			pRootFolder->Release();
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Get the registration info for setting the identification.
		IRegistrationInfo *pRegInfo = NULL;
		hr = pTask->get_RegistrationInfo(&pRegInfo);
		if (FAILED(hr))
		{
			printf("\nCannot get identification pointer: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}
		if (creater != NULL)
		{
			WCHAR *AuthorName = creater;
			hr = pRegInfo->put_Author(AuthorName);
			if (FAILED(hr))
			{
			pRegInfo->Release();
				printf("\nCannot put identification info: %x", hr);
				pRootFolder->Release();
				pTask->Release();
				CoUninitialize();
				return hr;
			}
		}
			pRegInfo->Release();
		//  ------------------------------------------------------
		//  Create the settings for the task
		ITaskSettings *pSettings = NULL;
		hr = pTask->get_Settings(&pSettings);
		if (FAILED(hr))
		{
			printf("\nCannot get settings pointer: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  Set setting values for the task. 
		hr= pSettings->put_StartWhenAvailable(VARIANT_TRUE);
		if (FAILED(hr))
		{
			pSettings->Release();
			printf("\nCannot put setting info: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return 1;
		}
		hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
		pSettings->Release();
		if (FAILED(hr))
		{
			printf("\nCannot put setting info: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Get the trigger collection to insert the logon trigger.
		ITriggerCollection *pTriggerCollection = NULL;
		hr = pTask->get_Triggers(&pTriggerCollection);
		if (FAILED(hr))
		{
			printf("\nCannot get trigger collection: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  Add the logon trigger to the task.
		ITrigger *pTrigger = NULL;
		hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
		pTriggerCollection->Release();
		if (FAILED(hr))
		{
			printf("\nCannot create the trigger: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		ILogonTrigger *pLogonTrigger = NULL;
		hr = pTrigger->QueryInterface(
			IID_ILogonTrigger, (void**)&pLogonTrigger);
		pTrigger->Release();
		if (FAILED(hr))
		{
			printf("\nQueryInterface call failed for ILogonTrigger: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}
	
		hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
		if (FAILED(hr))
			printf("\nCannot put the trigger ID: %x", hr);

		wchar_t computerName[256] = { 0 };
		wchar_t userName[256] = { 0 };
		DWORD dwSize = 256;
		if (!GetComputerNameW(computerName, &dwSize)|| !GetUserNameW(userName, &dwSize))
		{		
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return S_FALSE;
		}
		lstrcatW(computerName, (wchar_t*)L"\\");
		lstrcatW(computerName, userName);
		std::wcout << "当前用户名:" << computerName << endl;

		//  Define the user.  The task will execute when the user logs on.
		//  The specified user must be a user on this computer.  
		hr = pLogonTrigger->put_UserId(computerName);
		pLogonTrigger->Release();
		if (FAILED(hr))
		{
			printf("\nCannot add user ID to logon trigger: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Add an Action to the task. This task will execute notepad.exe.     
		IActionCollection *pActionCollection = NULL;

		//  Get the task action collection pointer.
		hr = pTask->get_Actions(&pActionCollection);
		if (FAILED(hr))
		{
			printf("\nCannot get Task collection pointer: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  Create the action, specifying that it is an executable action.
		IAction *pAction = NULL;
		hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
		pActionCollection->Release();
		if (FAILED(hr))
		{
			printf("\nCannot create the action: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		IExecAction *pExecAction = NULL;
		//  QI for the executable task pointer.
		hr = pAction->QueryInterface(
			IID_IExecAction, (void**)&pExecAction);
		pAction->Release();
		if (FAILED(hr))
		{
			printf("\nQueryInterface call failed for IExecAction: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  Set the path of the executable to notepad.exe.
		hr = pExecAction->put_Path(_bstr_t(wstrExecutablePath.c_str()));
		pExecAction->Release();
		if (FAILED(hr))
		{
			printf("\nCannot set path of executable: %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		//  ------------------------------------------------------
		//  Save the task in the root folder.
		IRegisteredTask *pRegisteredTask = NULL;

		hr = pRootFolder->RegisterTaskDefinition(
			_bstr_t(wszTaskName),
			pTask,
			TASK_CREATE_OR_UPDATE,
			_variant_t(computerName),
			_variant_t(),
			TASK_LOGON_INTERACTIVE_TOKEN,
			_variant_t(L""),
			&pRegisteredTask);
		if (FAILED(hr))
		{
			printf("\nError saving the Task : %x", hr);
			pRootFolder->Release();
			pTask->Release();
			CoUninitialize();
			return hr;
		}

		printf("\n Success! Task successfully registered. ");

		// Clean up
		pRootFolder->Release();
		pTask->Release();
		pRegisteredTask->Release();
		CoUninitialize();
		return 0;
	
}

C#代码

注意需要安装nuget包TaskScheduler

        /// 
        /// 开机自启
        /// 
        /// 任务名字
        /// 可执行文件路径(如果路径存在空格,最好将路径用双引号包起来,"C:\\Program Files (x86)\\123.exe")
        /// 任务藐视
        public static void AutoStart(string taskName,string fileName,string description)
        {
            if (string.IsNullOrEmpty(taskName) || string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException();
            }
            string TaskName = taskName;
            var logonUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            string taskDescription = description;
            string deamonFileName = fileName;

            using (var taskService = new TaskService())
            {
                var tasks = taskService.RootFolder.GetTasks(new System.Text.RegularExpressions.Regex(TaskName));
                foreach (var t in tasks)
                {
                    taskService.RootFolder.DeleteTask(t.Name);
                }

                var task = taskService.NewTask();
                task.RegistrationInfo.Description = taskDescription;
                task.Settings.DisallowStartIfOnBatteries = false;//当使用电源时,也运行此计划任务
                task.Triggers.Add(new LogonTrigger { UserId = logonUser });
                task.Principal.RunLevel = TaskRunLevel.Highest;
                task.Actions.Add(new ExecAction(deamonFileName));

                taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
            }
        }

 

你可能感兴趣的:(学习过程)