go语言编写的windows应用程序如何申请提权

程序功能需要管理员权限,程序运行过程中如何做到每3秒钟判断当前运行权限,如果普通权限申请提权,管理员权限就不申请提权
还有windows应用程序申请提权的时候是不是停止运行直到用户选择

我解决了


```go
package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func main() {
    for i := 1; i < 3; i++ {
        check()
    }

}
func check() {
    if os.Geteuid() == 0 {
        fmt.Println("Already running as root")
        return
    }

    // 获取程序的路径
    path, err := os.Executable()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取当前进程的句柄
    handle, err := syscall.LoadLibrary("shell32.dll")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer syscall.FreeLibrary(handle)

    // 获取ShellExecuteW函数的地址
    proc, err := syscall.GetProcAddress(handle, "ShellExecuteW")
    if err != nil {
        fmt.Println(err)
        return
    }

    // 调用ShellExecuteW函数以请求管理员权限
    args := []uintptr{
        0,
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("runas"))),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
        0,
        0,
        0,
    }
    ret, _, err := syscall.Syscall6(uintptr(proc), 6, args[0], args[1], args[2], args[3], args[4], args[5])
    if ret != 0 {
        fmt.Println("Successfully requested admin privileges")
        return
    } else {
        fmt.Println("Failed to request admin privileges")
        fmt.Println(err)
    }
}


```

在Windows操作系统中,如果你的Go程序需要管理员权限,你可以通过在程序的manifest文件中声明需要的权限来实现。这个manifest文件应该与你的程序在同一个目录下,并且名字应该和你的程序相同,但是扩展名是.manifest。例如,如果你的程序叫做myprogram.exe,那么manifest文件应该叫做myprogram.exe.manifest

在manifest文件中,你可以添加以下内容来声明你的程序需要管理员权限:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86"
     name="myprogram"
     type="win32"/>
  <description>My Program</description>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

当你的程序启动时,Windows会检查这个manifest文件,如果发现你的程序需要管理员权限,它会弹出一个UAC(用户账户控制)对话框,询问用户是否允许你的程序以管理员权限运行。如果用户同意,你的程序就会以管理员权限运行,否则就会以普通用户权限运行。

至于你的需求,即每3秒钟检查一次程序的运行权限,如果是普通权限就申请提权,这在Windows中是不可能的。因为一旦程序启动,它的权限级别就已经确定了,不能在运行时改变。如果你的程序需要管理员权限,你应该在程序开始运行时就申请,而不是在运行过程中。

另外,当程序申请提权时,程序不会停止运行,但是会弹出UAC对话框,等待用户的响应。在用户做出选择之前,程序会被挂起,等待用户的选择。如果用户选择允许,程序会以管理员权限继续运行;如果用户选择拒绝,程序会以普通用户权限继续运行,或者根据你的代码处理,可能会退出。

以上是基于Windows的权限管理机制,和你使用的编程语言无关。无论你使用Go、C++、Python还是其他任何语言,都需要遵循这个机制。

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/252818
  • 你也可以参考下这篇文章:登录系统以后,在Windows服务进程中启动需管理员权限(带盾牌图标)的应用程序
  • 除此之外, 这篇博客: 无损windows系统迁移中的 同时准备好一块系统将要迁移到的目标硬盘,并且使得硬盘稳定正常连接到将要迁移系统的计算机上 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 如果目标硬盘是nvme固态,如果笔记本或者台式机主板支持第二个nvme插口,可以直接拆机插入,没有则可以选择移动固态硬盘盒子。同理支持ngff协议的固态或者sata接口的机械硬盘也可以直接装入机子或者使用外置移动盒子的方案使得能被将要迁移的系统读取到,r三种硬盘迁移过程相同,欢迎往后观看

    关于区分ngff和nvme固态的博客:NVMe和NGFF区别


  • 您还可以看一下 夏曹俊老师的Windows程序设计应用开发课程中的 线程-线程概念与函数、线程关系理解windows应用程序设计小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    问题解答:

    要让go语言编写的Windows应用程序在运行过程中实现动态申请管理员权限并判断,可以通过以下步骤实现:

    1.引入相关的Windows API包。在go语言中,可以通过“syscall”和“golang.org/x/sys/windows”这两个包引入相关的Windows API函数,具体可以根据实际需要进行选择。

    2.创建相关函数并进行调用。可以通过以下三个函数实现:OpenProcessToken、GetTokenInformation和CreateProcessAsUser。其中,OpenProcessToken用于打开当前进程的访问令牌,并返回令牌句柄;GetTokenInformation可以获取当前令牌的信息,包括用户SID等;CreateProcessAsUser则可以创建一个以指定用户身份运行的新进程,在创建过程中可以通过指定参数来设置进程的访问令牌等相关信息。

    3.实现循环检测和动态请求管理员权限。可以在应用程序运行过程中设置一个循环,每隔3秒钟检测一次当前的运行权限,如果权限为普通权限,则使用上述函数动态请求管理员权限。

    以下是一段示例代码,具体用法可根据实际需要进行调整和扩展:

    package main
    
    import (
        "fmt"
        "syscall"
        "time"
        "unsafe"
    
        "golang.org/x/sys/windows"
    )
    
    const (
        TokenElevation = 20
        TokenElevated  = 2
    )
    
    func main() {
        // 循环检测权限和请求管理员权限
        for {
            // 获取当前进程的访问令牌
            hToken := windows.Token(0)
            err := windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_QUERY, &hToken)
            if err != nil {
                fmt.Println("OpenProcessToken failed:", err)
                break
            }
    
            // 获取当前令牌的信息
            tokenElevation := windows.TokenElevation{}
    
            var dwReturnLength uint32
            err = windows.GetTokenInformation(hToken, TokenElevation, unsafe.Pointer(&tokenElevation), uint32(unsafe.Sizeof(tokenElevation)), &dwReturnLength)
            if err != nil {
                fmt.Println("GetTokenInformation failed:", err)
                break
            }
    
            // 判断是否具有管理员权限
            if tokenElevation.TokenIsElevated != TokenElevated {
                fmt.Println("Current user is not administrator, requesting elevated privileges...")
    
                // 创建新进程并请求管理员权限
                startupInfo := windows.StartupInfo{}
                processInformation := windows.ProcessInformation{}
    
                err = windows.CreateProcessAsUser(hToken, nil, "cmd /k",
                    nil, nil, false, windows.CREATE_NEW_CONSOLE|windows.CREATE_NEW_PROCESS_GROUP|windows.CREATE_DEFAULT_ERROR_MODE,
                    nil, ".", &startupInfo, &processInformation)
                if err != nil {
                    fmt.Println("CreateProcessAsUser failed:", err)
                    break
                }
    
                // 等待新进程结束
                windows.WaitForSingleObject(processInformation.Process, windows.INFINITE)
            } else {
                fmt.Println("Current user already has administrator privileges.")
            }
    
            // 等待一段时间后进行下一次检测
            time.Sleep(3 * time.Second)
        }
    }
    

    需要注意的是,在请求管理员权限时,应用程序可能会停止运行并等待用户选择。为了弹出相应的提示,可以使用Windows API中的MessageBox函数或Win32的窗口控件等来实现。

    总之,实现动态申请与判断Windows管理员权限的功能需要调用相关的Windows API函数,并结合循环检测和动态请求管理员权限的策略,使应用程序在运行过程中能够实时获取并调整运行权限。