假如要启动 this.exe。以下逻辑中会启动先后关联启动三个实例分别是ABC。先启动第一个实例A,A启动实例B,B启动实例C.

要求:

1.如果没有以管理员权限运行,则请求管理员权限运行,即使没有请求成功或请求成功之前,也要先以非管理员权限运行,因为它定时要执行一些任务,不能因阻塞而错过。

2.如果没有以管理员权限运行,也要可以动态申请以管理员权限来注册开机启动,然后托盘显示右键菜单指示是否已经设置开机启动。

3.支持Windows XP 到 Windows 10.

4.自启过程无需人工干预,全自动无阻塞。

5.不能关闭UAC,如果这个都关了,我们就不用讨论了。

要实现以上3点,其实并不容易,XP容易实现自不必说,从Vista开始就不那么容易了。

有两个难点:

1. 以管理员身份开机自启。注册表实现不了,启动菜单目录也实现不了。因为即使设置了程序的兼容性以管理员身份运行,但弹出的那个UAC确认框谁来点呢?据我所知,用计划任务是目前唯一可以实现以管理员身份启动并且不需要UAC确认的。

2. 当以非管理员身份运行时,动态申请管理员权限,当然这个是需要UAC确认的。

用来做一些人工设置的时候,这时候人是在电脑旁边的。比如设置开机自启,取消开机自启。

这个解决方案比较简单,实例A用RunAs方式申请管理员权限启动一个新实例B,传入命令行参数,B执行完自动结束。即使申请启动失败,A也可以继续存活,想要申请过程无阻塞就新开一个线程来做。

但有一个问题,B有没有启动成功?用户有没有在UAC确认时允许?即使是用户确认了,B成功在计划任务创建了开机以管理员身份启动。但是A依然无法判断是否成功设置了开机自启,托盘无法正确的为用户指示开机自启状态。有人会说查询一下计划任务里有没有我们创建的任务就行了,很可惜,因为A没有管理员权限,所以无法查询。

我其实也搞不懂,微软为什么查询计划任务都需要管理员权限。

既然B都有管理员权限了,它返回一个ExitCode不就行了。当然这样可以,但是开机自启是敏感操作,很可能被杀软干掉,这样我们的开机自启状态指示就变得不可靠。

有一个办法,B既然已经有了管理员权限,让它启动一个C,C就是一个完全有管理员权限的实例,B自我关闭,返回一个ExitCode给A,A收到通知也关闭,一切不就解决了嘛。这就是我的方案。

当然也可以不启动C,B关闭A,B继续以管理员权限运行,但是如何返回状态给A让A自我结束,或者B干掉A,就不是一个ExitCode可以解决的了,通讯或查找程序可能变得复杂。

下面附上创建、查询、删除计划任务的VB.NET代码:

Public Class Form1
Private Const TASK_TRIGGER_LOGON = &H9
Private Const TASK_ACTION_EXEC = &H0
Private Const TASK_CREATE = &H2
Private Const TASK_CREATE_OR_UPDATE = &H6
Private Const TASK_RUNLEVEL_HIGHEST = &H1
Private Const TASK_LOGON_GROUP = &H4
Private Const TASK_LOGON_NONE = &H0 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub Public Function CreateOrUpdateTask(ByVal strTaskName As String, ByVal strAuthor As String, ByVal strTaskDescription As String, ByVal strPath As String, ByVal strWorkingDir As String, Optional ByVal strArguments As String = "", Optional ByVal bUseHighestSecLevel As Boolean = True) As Long
Dim objService As Object
objService = CreateObject("Schedule.Service")
objService.Connect() Dim objTaskFolder As Object
objTaskFolder = objService.GetFolder("\") Dim objTaskDef As Object
objTaskDef = objService.NewTask() Dim objPrincipal As Object
objPrincipal = objTaskDef.principal
With objPrincipal
.LogonType =
.RunLevel = TASK_RUNLEVEL_HIGHEST
End With Dim colTriggers As Object
Dim objTrigger As Object
Dim colActions As Object
Dim objAction As Object
Dim objInfo As Object
Dim objSettings As Object
colTriggers = objTaskDef.Triggers
objTrigger = colTriggers.Create(TASK_TRIGGER_LOGON)
objTrigger.Enabled = True
colActions = objTaskDef.Actions
objAction = colActions.Create(TASK_ACTION_EXEC)
objAction.Path = strPath
objAction.WorkingDirectory = strWorkingDir
objAction.Arguments = strArguments
objInfo = objTaskDef.RegistrationInfo
objInfo.Author = strAuthor
objInfo.Description = strTaskDescription
objSettings = objTaskDef.Settings
With objSettings
.Enabled = True
.Hidden = False
.StartWhenAvailable = True
.DisallowStartIfOnBatteries = False
.StopIfGoingOnBatteries = False
.AllowHardTerminate = False
End With Try
If bUseHighestSecLevel Then
objTaskFolder.RegisterTaskDefinition(strTaskName, objTaskDef, TASK_CREATE_OR_UPDATE, "Administrators", , TASK_LOGON_GROUP)
Else
objTaskFolder.RegisterTaskDefinition(strTaskName, objTaskDef, TASK_CREATE_OR_UPDATE, , , TASK_LOGON_NONE)
End If
Catch ex As Exception
Return Err.Number
End Try CreateOrUpdateTask =
objService = Nothing
objInfo = Nothing
objTaskFolder = Nothing
objTaskDef = Nothing
objPrincipal = Nothing
End Function Public Function DeleteTask(ByVal strTaskName As String) As Long
Dim objService As Object
Dim objTaskFolder As Object Try
objService = CreateObject("Schedule.Service")
objService.Connect()
objTaskFolder = objService.GetFolder("\")
objTaskFolder.DeleteTask(strTaskName, )
Catch ex As Exception
Return Err.Number
End Try objService = Nothing
objTaskFolder = Nothing
DeleteTask =
End Function Public Function TaskAvailable(taskName) As Boolean
Dim service = CreateObject("Schedule.Service")
Call service.Connect() ' Get the task folder that contains the tasks.
Dim rootFolder
rootFolder = service.GetFolder("\") Dim taskCollection
taskCollection = rootFolder.GetTasks() Dim numberOfTasks
numberOfTasks = taskCollection.Count If numberOfTasks = Then
Debug.Print("No tasks are registered.")
Else
Debug.Print("Number of tasks registered: " & numberOfTasks) Dim registeredTask
For Each registeredTask In taskCollection
Dim name As String = registeredTask.Name
Debug.Print("Task Name: " & name)
Dim taskState
Select Case registeredTask.State
Case ""
taskState = "Unknown"
Case ""
taskState = "Disabled"
If (name = taskName) Then
TaskAvailable = False
Exit Function
End If
Case ""
taskState = "Queued"
Case ""
taskState = "Ready"
Case ""
taskState = "Running"
Case Else
taskState = "Unknown"
End Select
If (name = taskName) Then
TaskAvailable = True
Exit Function
End If
Debug.Print(" Task State: " & taskState)
Next
End If
TaskAvailable = False
End Function Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
MsgBox(CreateOrUpdateTask("Test", Interaction.Environ("USERDOMAIN") & "\" & Interaction.Environ("USERNAME"), "a Test Task", Application.ExecutablePath, Application.StartupPath, "", True))
End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
MsgBox(DeleteTask("Test"))
End Sub
End Class

.net 创建计划任务开机后自动以管理员身份启动运行 win7 ~ win10的更多相关文章

  1. 让一个Activity在开机后自动显示

    Activity本身不会在手机开机后自动运行的.但想让手机开机后就立刻做一些动作,需要使用广播接收器拦截手机开启广播,并在onReceive方法中完成相应的动作,如打开一个Activity. 广播接收 ...

  2. 让bat文件自动以管理员身份运行

    · 让bat文件自动以管理员身份运行 如何让bat文件自动以管理员身份运行,将这段写在bat文件的前头即可 : %1 mshta vbscript:CreateObject("Shell.A ...

  3. CMD批处理(5)——自动以管理员身份运行批处理脚本

    在日常运维工作中,为方便对windows用户进行系统安装或配置等,使用Windows自带的批处理(bat文件)是一种最为简单快速的方法. 批处理脚本不会默认已管理员身份运行,一般情况下,我会将脚本命名 ...

  4. 如何自动以管理员身份运行.NET程序?

    原文:如何自动以管理员身份运行.NET程序? windows 7和vista提高的系统的安全性,同时需要明确指定“以管理员身份运行”才可赋予被运行软件比较高级的权限,比如访问注册表等.否则,当以普通身 ...

  5. 教你在树莓派使用上RTC实时时钟,不用再担心断电后时间归零的问题,开机后自动同步RTC时钟!!!

    准备工作:1.系统建议使用官方最新的镜像文件 2.RTC时钟模块板(I2C接口)建议使用DS1307时钟模块,或者RTC时钟模块RTC时钟模块: 大家知道arduino的电平是5V,树莓派是3.3V, ...

  6. 如何使Linux系统上的程序开机后自动运行 (转)

    Linux有自己一套完整的启动体系,抓住了Linux启动的脉络,Linux的启动过程将不再神秘. 阅读之前建议先看一下附图. 本文中假设inittab中设置的init tree为: /etc/rc.d ...

  7. 【转载】CentOS 7自动以root身份登录gnome桌面 操作系统开机后自动登录到桌面 跳过GDM

    CentOS 7自动以root身份登录gnome桌面 ################### #cd /etc/gdm ]# cat custom.conf# GDM configuration st ...

  8. 设置Qt程序在Windows开机后自动运行

    (转自:http://blog.csdn.net/weiren2006/article/details/7443362) 主要原理是修改Windows的注册表来实现的,Qt的QSettings提供了访 ...

  9. 电脑开机后多了OneKey Ghost启动选项怎么解决

    原文地址:http://www.xitongcheng.com/jiaocheng/dnrj_article_18745.html 大多数用户在使用OneKey Ghost安装电脑系统后,会在开机启动 ...

随机推荐

  1. 线程的Abort方法有感

    今天看CSDN上一个很老的帖子,有个人说Thread.Abort()方法调用之后一定会抛出异常,我对这个有点疑问. 于是自己做了一个测试demo,来研究Abort抛出异常的时机.废话少说,直接上代码: ...

  2. 关于JavaEE 开发中web.xml的主要配置及其使用

    web.xml 中的listener. filter.servlet 加载顺序及其详解 在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人 ...

  3. python基础之模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合. 而对于一个复杂的功能来,可能需要多个函数 ...

  4. Python中文问题(转)

    在本文中,以'哈'来解释作示例解释所有的问题,“哈”的各种编码如下: 1. UNICODE (UTF8-16),C854: 2. UTF-8,E59388: 3. GBK,B9FE. 一.python ...

  5. Cannot forward after response has been committed

    项目:蒙文词语检索 日期:2016-05-01 提示:Cannot forward after response has been committed 出处:request.getRequestDis ...

  6. liunx中字符驱动编写的简单模板

    下面是关于字符驱动两个程序,主要是说明驱动编写的思想,理解驱动是怎么一步一步被实现的. 驱动的第一个实现程序,是相对于裸机编程的,主要是体会一下驱动编程思想: cdev.h: 所包含的头文件 #ifn ...

  7. Newtonsoft.Json 处理多态类型的反序列化

    Newtonsoft.Json的序列化和反序列化很成熟也很好用, 最近在处理多态类型的反序列化中遇到了问题, 反序列化后只能到基类,而得不到也不能转换到子类.从网上查询了一番后,需要写一个创建类型的C ...

  8. DotNetBar 第2课,窗口设置 Ribbon Form 样式

    1. 新增 windows 窗体时,选 Ribbon Form 2. 窗体继承 Office2007RibbonForm 3. 设计窗口下面,删除 删除styleManager1  组件 窗口效果如下 ...

  9. track by

    ng-repeat指令中使用track by子语句解决重复数据遍历的错误 <li ng-repat="x in [2, 2]" ng-bind="x"&g ...

  10. jQuery获取带点的id元素

    一般jQuery获取某个id为elem元素,只需用$('#elem')就行了,但是如果id中不小心包括了'.' ,那么我吗就会发现这时候jQuery就不能获取到这个元素了.但是使用dom原生的getE ...