• .net 创建计划任务开机后自动以管理员身份启动运行 win7 ~ win10


    假如要启动 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(0)
    
            Dim objPrincipal As Object
            objPrincipal = objTaskDef.principal
            With objPrincipal
                .LogonType = 1
                .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 = 0
            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, 0)
            Catch ex As Exception
                Return Err.Number
            End Try
    
            objService = Nothing
            objTaskFolder = Nothing
            DeleteTask = 0
        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(0)
    
            Dim numberOfTasks
            numberOfTasks = taskCollection.Count
    
            If numberOfTasks = 0 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 "0"
                            taskState = "Unknown"
                        Case "1"
                            taskState = "Disabled"
                            If (name = taskName) Then
                                TaskAvailable = False
                                Exit Function
                            End If
                        Case "2"
                            taskState = "Queued"
                        Case "3"
                            taskState = "Ready"
                        Case "4"
                            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
  • 相关阅读:
    《GDB常用基本》
    《Linux守护进程》
    <C语言知识点 —— 数组赋值字符串>
    《Linux知识点》
    玩转----select模块操作下拉框-selenium
    玩转----selenium--下拉框select
    玩转----selenium-滚动条的几种方式
    玩转----python-装饰器
    玩转----解决selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid 'expiry'
    玩转----iframe框架怎样来定位,并说明iframe框架中不变和可变的属性分别是什么?多个iframe框架怎么处理?iframe和frame区别:
  • 原文地址:https://www.cnblogs.com/nanfei/p/6100412.html
Copyright © 2020-2023  润新知