我必须执行ewfmgr.exe
,它只能在以管理员身份打开命令窗口时执行。
如果我转到Start
-> type cmd.exe
-> Right click
-> Run as Administrator
,则会出现以下命令提示窗口。在这个窗口中,如果我写ewfmgr.exe
(我必须执行的EXE文件),那么命令执行没有任何问题。
我的要求:我的要求是通过脚本文件(RunasAdmin.cmd
文件)执行命令,这个脚本文件将通过NSIS安装程序执行。
因为ewfmgr.exe
只能通过Admin执行,所以我必须升级我的脚本以获得Admin权限。为此,我有以下脚本:
获取管理员权限的脚本:"(RunasAdmin.cmd)"
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================
:init
setlocal DisableDelayedExpansion
set cmdInvoke=0
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & pushd .
cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
REM Run shell as admin (example) - put here code as you like
ewfmgr c: -enable
pause
cmd /k
**问题:**如果我双击脚本(RunasAdmin.cmd
),脚本会被执行,任务完成,没有任何错误。但是如果我通过我的NSIS安装程序(EWFMGR_Run.exe
)执行脚本(RunasAdmin.cmd
),那么我会得到一个错误:ewfmgr is not recognised as an internal or external command
NSIS安装程序代码:(EWFMGR_Run.exe)
OutFile "EWFMGR_Run.exe"
section
ExecWait "D:\Disk\RunasAdmin.cmd"
sectionEnd
运行脚本(RunasAdmin.cmd
)后,NSIS安装程序打开的命令窗口如下所示:
**Queston:**两个命令窗口都以Admin打开,并且在同一个工作目录下。但是为什么NSIS安装程序打开的窗口无法找到ewfmgr.exe
?
**UPDATE-1:**基本上问题出在NSIS安装程序打开的CMD窗口中。即使我使用cd /D C:\Windows\System32
手动移动到路径C:\Windows\System32
并尝试执行ewfmgr.exe
(在该路径中可用),CMD也无法识别它。
**参考:**提升到Admin的脚本文件取自Matt的答案。
3条答案
按热度按时间p1iqtdky1#
在将命令脚本(批处理文件)提升到管理员级别时,必须至少考虑哪些因素?
1.当前目录在任何情况下都将更改为
%SystemRoot%\System32
。1.如果当前用户不在管理员组中,则环境可能会完全改变,因此用户必须使用不同的用户帐户以管理员的提升权限运行批处理文件,例如必须使用本地管理员帐户而不是当前用户帐户。这会影响网络资源上的环境变量和权限。
1.该脚本最初总是在64位Windows上的父进程的环境中启动,如果父进程是32位应用程序,则在32位环境而不是64位环境中启动。
1.脚本可以用一个或多个参数(用双引号括起来)来执行,这些参数应该在执行时以提升的权限传递给脚本。
如何处理这四个问题?
1.当前目录
许多命令行脚本(批处理文件)都被编码为使用当前目录,并假设当前目录与批处理文件是同一目录。双击存储在本地驱动器或网络驱动器上的批处理文件时,当前目录与存储批处理文件的目录相同,但安全设置禁用从网络驱动器执行批处理文件。
但是Windows将
%SystemRoot%\System32
设置为使用系统帐户运行cmd脚本作为计划任务的当前目录。Windows将
%SystemRoot%\System32
设置为使用RunAs
以提升的管理员权限运行cmd脚本的当前目录。Windows将
%SystemRoot%
设置为当前目录后,打印到控制台窗口中,双击执行批处理文件时显示以下消息,该批处理文件存储在使用UNC path打开的网络共享上。'\server\share\directory'
CMD.EXE以上述路径作为当前目录启动。
不支持UNC路径。默认为Windows目录。
可以启用使用UNC路径作为当前目录,如How to run batch file from network share without "UNC path are not supported" message?上的答案所述
最好的方法是编写整个脚本代码,使其独立于当前目录。
这意味着不只是使用引用文件的文件名,而是使用
"Full path to\FileName.exe"
,即带有文件扩展名和完整路径的文件名用双引号括起来。如果cmd脚本中要运行或引用的所有文件都存储在未知文件夹中,但始终与cmd脚本位于同一文件夹中,则获取所有文件路径的简单方法是使用命令行:
%~dp0
扩展到批处理文件的路径,始终以反斜杠结尾,并且从不用双引号括起来,即使文件夹路径包含空格字符或其他命令行语法关键字符(如&符号)。然后使用
**注意:**没有反斜杠(Windows上的目录分隔符),因为环境变量
SourceFolder
保存的文件夹路径已经有反斜杠结尾。当然,也可以使用
cd /D "%~dp0"
将当前目录设置为cmd脚本的目录,但这对UNC路径不起作用。但是如果默认情况下启用了命令扩展名,则
pushd "%~dp0"
命令也可以与UNC路径一起使用。有关在命令提示符窗口
cd /?
和pushd /?
中运行的命令CD和PUSHD的详细信息,请阅读输出帮助。2.环境变量
每当创建新进程时,Windows都会创建当前进程的当前活动环境表的副本。
但当批处理文件将其自身提升到管理员级别时,情况并非如此。因此,不可能在批处理文件的初始运行时定义环境变量,然后提升到管理员级别,并在初始环境中访问之前定义的环境变量。甚至可能发生批处理文件最初在64位Windows上的32位环境中执行的情况,但在提升到管理员级别后在64位环境中运行。
因此,需要从初始执行传递到提升执行的所有内容都必须通过命令行参数或通过本地驱动器上的文件进行解析,该文件在所有环境中都可以完全访问,即对所有人都是
3. 32位与64位环境
有时,32位安装程序用于安装32位或64位应用程序,具体取决于Windows的位宽,因为它可以在所有Windows上运行。批处理文件由32位安装程序在32位环境中由32位
cmd.exe
处理,即使在64位Windows上执行。在进一步阅读之前,至少应仔细研究以下三篇Microsoft文章:
依赖环境变量
PROCESSOR_ARCHITECTURE
的值绝对不是好主意,因为当在32位环境中在64位Windows上执行32位进程时,其值为x86
。直接从Windows注册表查询处理器的架构也不好。不保证在具有64位CPU的计算机上运行64位Windows。这是不经常做的,但仍然可以在主板上有64位处理器的计算机上使用32位Windows。
默认情况下,在32位Windows上未定义环境变量
ProgramFiles(x86)
,因为它在64位Windows上可以用于确定命令文件脚本是在32位还是64位Windows上运行。文件
%SystemRoot%\Sysnative\cmd.exe
和%SystemRoot%\Sysnative\wscript.exe
仅存在于64位Windows上32位执行环境中运行的32位进程中,因为特殊别名Sysnative
仅存在于64位Windows上32位环境中的32位进程中。可用于确定批处理文件当前在哪个执行环境中运行。4.参数传递
很容易将不带任何参数执行的批处理文件提升到更高的管理员级别。
将不需要用双引号括起来的简单参数传递给运行提升的批处理文件也没有问题。
但是传递一个或多个参数,其中至少包含一个空格字符或其中一个字符
&()[]{}^=;!'+,
~<|>,这需要将参数字符串括在双引号中,这真的很不容易,特别是在从批处理文件中创建Visual Basic脚本以提升到管理员级别时。 这是一个真实的的噩梦,试图编码双引号在批处理文件正确地通过VB脚本传递到同一批处理文件执行提升的特权。万维网中提供的大多数解决方案根本不支持双引号参数。[Matt's Elevate.cmd - Version 4](https://stackoverflow.com/a/12264592/3074564)也不例外。使用此代码以
"%ProgramFiles%\Installation Folder"作为第一个参数运行批处理文件会导致
"C:\Program Files\Installation Folder"作为第一个也是唯一的参数的初始执行,以及在删除三个参数
C:\Program、
Files\Installation和
Folder中的参数
ELEV`后的提升执行。5.此任务的可能解决方案
对于此任务,32位NSIS安装程序正在调用命令行脚本,该脚本必须将自身提升到管理员级别,并且应该在64位环境中的64位Windows上运行,而不是在初始运行时的32位环境中运行。
我曾经分析过Matt's Elevate.cmd - Version 4的批处理和VB脚本代码,删除了所有无用的代码,增强了它,使用比其他发布的方法更容易的方法来支持双引号中的参数,并完全注解了代码,以便其他人也可以理解它来回答UNC paths as current directories in batch file where admin rights are requested。
这里发布的批处理脚本是独立于当前目录工作的,也可以使用UNC路径从网络共享执行批处理文件,当然,只有在提升到管理员级别后,根据共享的权限设置,网络共享仍然可以访问时才有效。今天我发现Richard在his answer on Open Command Window in Windows x64 mode上发表评论后,网页SS64 - Run with elevated permissions包含的代码几乎与我开发的代码相同,而没有阅读过那里的代码。
下面的修改后的批处理文件代码应该可以完成此任务。它期望可执行文件
ewfmgr.exe
与cmd脚本位于同一目录中,或者ewfmgr.exe
在执行脚本时指定完整路径作为第一个参数,以防在不同的目录中。6.此任务的最佳解决方案
但结果是,在我完成了上面的代码编写和测试之后,在写了这个很长的答案并在发布之前,阅读了Richard在Open Command Window in Windows x64 mode上对他的答案所写的评论,最好的解决方案很可能是使用NSIS代码,如在
How do you request administrator permissions using NSIS?
并在命令脚本中使用底部的几行也作为我在Open Command Window in Windows x64 mode上从32位切换到64位环境的答案。
dzhpxtsq2#
尝试修改RunasAdmin.cmd,使用Sysnative代替System32:
set winSysFolder=Sysnative
我猜测EWFMGR_Run.exe正在启动一个32位cmd窗口,并且Windows正在强制c:\windows\syswow64覆盖您尝试覆盖的set winSysFolder=System32
根据此article,您应该使用Sysnative虚拟文件夹。
“Sysnative”文件夹
如上所述,通过简单地在文件夹路径中插入“\System32”来从32位应用程序访问64位System32文件夹是不可能的。如果您尝试重定向到SysWOW64文件夹,系统会自动进行重定向。但还有另一个文件夹名称可以替代使用:系统化。
Sysnative是一个虚拟文件夹,一个特殊的别名,可用于从32位应用程序或脚本访问64位System32文件夹。例如,如果在应用程序的源代码中指定此文件夹路径:
C:\Windows\系统提示
实际使用了以下文件夹路径:
C:\Windows\System32
deyfvvtc3#
我想指出NSIS处理UAC和提升权利的具体方式。
如果您的NSIS安装程序需要运行具有提升权限的任何内容,则必须在NSIS脚本中指示如下:
一旦你这样做,当你启动安装程序,它会弹出UAC提示,并在连续运行外部脚本或程序,需要提升权限不会有任何问题。
这与Mofi的答案#5非常一致-我仍然发布这一条,因为我认为它归结为需要知道。国家情报局似乎是你的压轴好戏。
供参考:NSIS -无法将更新的PATH写入HKLM