找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
楼主: 小白龙

[问题求助] 批处理中使用powershell执行管理员权限

[复制链接]
 楼主| 发表于 2024-9-29 11:38:19 | 显示全部楼层
回复 15# WHY


    下面是gpt的解析, 正确吗?

这个批处理脚本的作用是将自身的一部分内容保存为一个 PowerShell 脚本,然后以管理员权限执行该 PowerShell 脚本。具体步骤如下:

1. `@echo off`:关闭批处理文件的命令回显,以免在命令行窗口显示每个执行的命令。

2. `more +4 "%~f0" > "%~dpn0.ps1"`:
   - `"%~f0"`:代表当前批处理文件的完整路径。
   - `more +4 "%~f0"`:从当前批处理文件的第5行开始读取(跳过前4行)。
   - `"%~dpn0.ps1"`:代表批处理文件的目录路径和文件名,扩展名改为 `.ps1`。这将会创建一个新的 PowerShell 脚本文件(`.ps1`)。
   - 这一行的意思是,将当前批处理文件从第5行开始的内容保存到同名的 `.ps1` 文件中。

3. `PowerShell "Start-Process PowerShell -Args ('-exec Bypass -file ' + [char]34 + '%~dpn0.ps1' + [char]34) -Verb RunAs" & exit/b`:
   - `Start-Process PowerShell`:启动一个新的 PowerShell 进程。
   - `-Args ('-exec Bypass -file ' + [char]34 + '%~dpn0.ps1' + [char]34)`:指定启动参数,绕过执行策略限制,并运行生成的 PowerShell 脚本文件。
     - `-exec Bypass`:绕过执行策略(`ExecutionPolicy Bypass`)。
     - `[char]34`:代表双引号字符(`"`),用于确保文件路径被正确引用。
     - `'%~dpn0.ps1'`:代表生成的 `.ps1` 文件路径。
   - `-Verb RunAs`:以管理员权限运行 PowerShell。
   - `& exit/b`:执行 PowerShell 命令后,退出批处理文件。

4. `echo Done`:输出 "Done",但由于前面已经执行 `exit/b`,所以这行代码实际上不会被执行。

5. `[Console]::ReadLine()`:这是一个 C# 语法的代码,它无法在批处理文件中直接执行。这行代码可能是放在生成的 PowerShell 脚本中,而不是直接在批处理文件中执行。

总结:这个批处理文件生成并运行一个 PowerShell 脚本,以管理员权限执行 PowerShell 脚本内容。
发表于 2024-10-7 20:58:17 | 显示全部楼层
回复 16# 小白龙


4.  echo Done`:输出 "Done",echo 是 Write-Output 的别名;

5. `[Console]::ReadLine()`:调用 C# 静态类的方法,"暂停"的意思。
发表于 2024-10-7 21:00:47 | 显示全部楼层
不用临时文件的办法:
  1. <# :
  2. @echo off
  3. PowerShell "Start-Process PowerShell -Args 'gc -Literal ''%~f0''|Out-String|iex' -Verb RunAS" & exit/b
  4. #>

  5. echo Done
  6. [Console]::ReadLine()
复制代码

评分

参与人数 1技术 +1 收起 理由
小白龙 + 1 乐于助人

查看全部评分

发表于 2024-10-7 21:08:51 | 显示全部楼层
本帖最后由 WHY 于 2024-10-7 21:10 编辑

1.
  1. <# :
复制代码
在批处理中,"<"和">"是重定向符,重定向可以前置(比如:>1.txt echo;1),经过预处理之后会变成这样子:
: 0<#
0--标准输入,<--重定向,#--文件名,:--标签标识符。就是说,这一行其实是一个无关紧要的标签行。

2.
  1. PowerShell "Start-Process PowerShell -Args 'gc -Literal ''%~f0''|Out-String|iex' -Verb RunAS" & exit/b
复制代码
Start-Process PowerShell 启动一个新的PowerShell进程;
'gc -Literal ''%~f0''|Out-String|iex' 传递给PowerShell新进程的启动参数,
这里 %~f0 代表批处理脚本自身,''%~f0'' 红色单引号对蓝色单引号进行转义。
启动参数的含义:读取批处理文本内容,转换成字符串,执行这个字符串的内容(iex为Invoke-Expression的别名)
这里的''%~f0''不可以用"%~f0"代替,否则,%~f0会暴露在双引号对之外。
-Verb RunAS 以管理员身份运行新进程。
exit/b 执行完这条命令后退出批处理。

3.
总之,这是一个批处理混编脚本,首先通过CMD运行这个批处理,执行完第3行后会退出批处理自身;
而批处理执行第3行的时候,会以管理员身份启动一个PowerShell新进程,新进程也是执行这个批处理文本的内容;
不过因为第1-4行是PowerShell多行注释(<#...#>),PowerShell实际只执行第5行之后的内容。
 楼主| 发表于 2026-3-22 18:43:41 | 显示全部楼层
本帖最后由 小白龙 于 2026-3-22 18:48 编辑
WHY 发表于 2024-10-7 21:08
1.在批处理中,""是重定向符,重定向可以前置(比如:>1.txt echo;1),经过预处理之后会变成这样子:
: 0 ...


多谢大佬解析,
以前没看懂, 也没怎么用, 今天我又需要这个功能了, 然后就搜索过来了,
现在差不多能看懂了, 这应该是在bat中执行powershell代码并用管理员身份运行最简洁的代码了吧?

不知道是不是穿越了, 还是论坛的问题, 大佬又改下面这个楼层的代码了? 我看修改时间是昨天, 这个代码真是难懂. 为啥又改它?
https://www.bathome.net/forum.ph ... 9839&pid=284559

真是过的太快了, 转眼快两年了.
 楼主| 发表于 2026-3-22 18:52:19 | 显示全部楼层
WHY 发表于 2024-10-7 21:08
1.在批处理中,""是重定向符,重定向可以前置(比如:>1.txt echo;1),经过预处理之后会变成这样子:
: 0 ...

下面是deepseek的分析:


这个方案的思路很巧妙,利用 PowerShell 注释语法和 `Start-Process -Verb RunAs` 实现了“一键提权”,但它有一个**致命缺陷**:缺少管理员权限检测,会导致无限循环。

### 代码运行过程分析
1. **首次运行**(普通用户权限)  
   - 批处理执行 `PowerShell "Start-Process ... -Verb RunAs"`,弹出 UAC 窗口,请求管理员权限。  
   - 用户确认后,新 PowerShell 窗口以管理员身份运行,并执行 `gc -Literal ''%~f0'' ... | iex`,即再次加载整个脚本内容。  
   - 原批处理窗口执行 `exit/b` 退出。  

2. **第二次运行**(管理员权限)  
   - 新打开的 PowerShell 窗口读取脚本,遇到 `Start-Process ... -Verb RunAs` 这一行(因为它是批处理部分,但在 PowerShell 中它是注释,不会被执行?这里有个关键点:在混合脚本中,`<# : ... #>` 内的内容在 PowerShell 中被视为注释,所以当脚本以 PowerShell 运行时,`Start-Process ...` 这一行**不会执行**!  
   - 但实际上,当脚本被 `iex` 执行时,PowerShell 解析的是**整个文件内容**,而不仅仅是注释内的部分。因为 `<# : ... #>` 是 PowerShell 的注释语法,所以位于其中的 `Start-Process ...` 确实被注释掉了,不会执行。  
   - 因此,第二次运行时,PowerShell 会跳过批处理部分,直接执行注释后的 PowerShell 代码(`echo "Done你好"` 和 `pause`),不会再次启动新的进程。  

所以**并不会无限循环**,因为第一次启动的 PowerShell 以管理员身份运行时,脚本中的提权命令在 PowerShell 语境下是注释,不会被执行。  
这个方案巧妙地利用了注释来实现“仅在第一次(批处理执行)时提权,之后(PowerShell 执行)不再提权”。

### 但为什么说它不是“非常好的”方案?
1. **依赖注释的隐蔽性**:对于不熟悉混合脚本的人来说,这种写法不够直观,维护者可能误以为它会导致无限循环。  
2. **没有显式权限检测**:即使已经是管理员,脚本也会先执行一次批处理部分(提权命令),导致**每次都弹出 UAC 窗口**(虽然实际上并不会重复启动,但用户会看到一闪而过的命令窗口和 UAC 提示,体验不好)。  
3. **在非管理员环境下的行为**:如果用户拒绝 UAC 提权,第一次的批处理窗口会退出,脚本不会继续执行。  
4. **兼容性问题**:某些系统环境(如 PowerShell 执行策略限制)可能阻止 `iex` 执行脚本内容。  

### 更好的做法
应该先检测当前是否已有管理员权限,只在**没有**权限时才提权。例如:

```batch
net session >nul 2>&1 || (
    echo 请求管理员权限...
    PowerShell "Start-Process -Verb RunAs -FilePath '%~f0'"
    exit /b
)
```

这样:
- 如果已经是管理员,直接执行后续代码(不会弹出 UAC 窗口)。
- 如果不是管理员,才请求提权,且提权后原进程退出,新进程再次检测到已是管理员,继续执行。

### 结论
你提供的方案虽然巧妙,但**并不是一个优秀的提权方案**,因为它缺少权限检测,在已管理员权限下也会多一次不必要的提权尝试,且代码可读性较差。建议采用显式检测 + 条件提权的方式。
 楼主| 发表于 2026-3-22 18:56:23 | 显示全部楼层
WHY 发表于 2024-10-7 21:00
不用临时文件的办法:

下面这两个参数加在哪里呢?

  1. -nop -ep Bypass
复制代码
 楼主| 发表于 2026-3-22 19:12:55 | 显示全部楼层
WHY 发表于 2024-10-7 21:00
不用临时文件的办法:

为什么加上中文就一闪就关了? 存的是gbk编码

  1. <# :
  2. @echo off
  3. PowerShell "Start-Process PowerShell -Args 'gc -Literal ''%~f0''|Out-String|iex' -Verb RunAS" & exit/b
  4. #>
  5. echo "Done你好"
  6. [Console]::ReadLine()
复制代码
发表于 2026-3-26 11:04:44 | 显示全部楼层
学习一下win11开始powershell命令才能完成的越来越多了
发表于 2026-3-26 13:00:09 | 显示全部楼层
小白龙 发表于 2026-3-22 18:52
下面是deepseek的分析:

AI的答案,我一般只作参考。

有些时候,AI也会自以为是,并且经常一本正经地胡说八道。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-4-26 17:15

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表