windows 无法以管理员身份运行

mqkwyuun  于 2023-05-19  发布在  Windows
关注(0)|答案(3)|浏览(390)

我必须执行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的答案。

p1iqtdky

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脚本位于同一文件夹中,则获取所有文件路径的简单方法是使用命令行:

set "SourceFolder=%~dp0"

%~dp0扩展到批处理文件的路径,始终以反斜杠结尾,并且从不用双引号括起来,即使文件夹路径包含空格字符或其他命令行语法关键字符(如&符号)。
然后使用

"%SourceFolder%FileName.exe"

**注意:**没有反斜杠(Windows上的目录分隔符),因为环境变量SourceFolder保存的文件夹路径已经有反斜杠结尾。

当然,也可以使用cd /D "%~dp0"将当前目录设置为cmd脚本的目录,但这对UNC路径不起作用。
但是如果默认情况下启用了命令扩展名,则pushd "%~dp0"命令也可以与UNC路径一起使用。
有关在命令提示符窗口cd /?pushd /?中运行的命令CDPUSHD的详细信息,请阅读输出帮助。

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:\ProgramFiles\InstallationFolder中的参数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路径从网络共享执行批处理文件,当然,只有在提升到管理员级别后,根据共享的权限设置,网络共享仍然可以访问时才有效。今天我发现Richardhis answer on Open Command Window in Windows x64 mode上发表评论后,网页SS64 - Run with elevated permissions包含的代码几乎与我开发的代码相同,而没有阅读过那里的代码。
下面的修改后的批处理文件代码应该可以完成此任务。它期望可执行文件ewfmgr.exe与cmd脚本位于同一目录中,或者ewfmgr.exe在执行脚本时指定完整路径作为第一个参数,以防在不同的目录中。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls

rem The console application NET with parameter FILE can be executed
rem successfully only if the account used for running this batch file
rem has local administrator privileges. See the Microsoft documentation
rem https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490702(v=technet.10)
rem for details about NET FILE.

rem The output written to handle STDOUT on successful execution is redirected
rem to device NUL to suppress it. The exit code of NET assigned to ERRORLEVEL
rem is in this case 0 indicating a successful execution.

rem But on a failed execution because of not having administrator
rem privileges NET outputs to handle STDERR the two error messages
rem "System error 5 has occurred." and "Access is denied." which
rem are redirected from handle STDERR to device NUL to suppress them.
rem And exit/return code of NET is 1 indicating a failed execution.

rem Read https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490982(v=technet.10))
rem for details about using command redirection operators.

%SystemRoot%\System32\net.exe FILE >nul 2>nul
if not errorlevel 1 goto RunMainCode

if "%~1" == "ELEV" (

    rem This condition is just for safety. If the batch file was started
    rem already a second time with ELEV as first parameter and execution
    rem of NET FILE failed nevertheless because of missing permissions,
    rem the batch file outputs an error message, waits for any key press
    rem by the user to make sure that the user had the chance to read the
    rem error message and then exits the batch file processing without
    rem doing anything at all.

    echo %~nx0 should run already with elevated privileges, but it isn't.
    echo(
    echo Press any key to exit %~nx0 without doing anything ...
    pause >nul
    exit /B
)

rem Define as application to run by default the file ewfmgr.exe in folder
rem of the batch file which can be a folder on a local drive or on a
rem network drive or even a UNC path.

set "AppToRun=%~dp0ewfmgr.exe"
set "BatchFileName=%~f0"
set "vbsGetPrivileges=%TEMP%\OEgetPriv_%~n0.vbs"

rem This batch file can be started without any parameter resulting in %* being
rem expanded to nothing which results in environment variable BatchArgs being
rem deleted if already existing or with ewfmgr.exe with full path as parameter
rem which must be enclosed in double quotes in case of path containing
rem one or more spaces.

rem As the batch file needs to be executed once again in a separate command
rem process running as local administrator for full access at least on local
rem machine it is necessary to prepare the parameters/arguments list. Each
rem double quote in the arguments list must be doubled to be correct escaped
rem in the VB script file.

rem This is necessary as otherwise running this batch file with
rem "Full path to\ewfmgr.exe"
rem as first parameter would result in execution of the batch file by the
rem Windows Scripting Host as Full path to\ewfmgr.exe without the double
rem quotes as arguments for the batch file and therefore the first parameter
rem is on elevated execution "Full" instead of "Full path to\ewfmgr.exe" as
rem it was initially.

rem Many "run as administrator" solutions which can be found in World Wide Web
rem don't handle parameter strings correct which are enclosed in double quotes
rem because the parameter string has one or more spaces or other critical
rem characters requiring enclosing the parameter string in double quotes.

set "BatchArgs=%*"
setlocal EnableDelayedExpansion
if defined BatchArgs set "BatchArgs= !BatchArgs:"=""!"

rem Everything output by the ECHO command lines within the next command block
rem is redirected into the VB script file created in the folder for temporary
rem files of current user with name of batch file in VB script file name. This
rem makes it possible that multiple batch files with different names can run
rem at the same time using same code for creating a VB script file to run the
rem batch file once again as administrator with elevated privileges.

rem For details on ShellExecute parameters see the Microsoft documentation
rem https://learn.microsoft.com/en-us/windows/win32/shell/shell-shellexecute

rem The tricky part is quoting the arguments list correct which should be
rem finally passed to cmd.exe executed from the VB script. The command process
rem running the batch file with elevated privileges of local administrator
rem should automatically close after execution of batch file finished which
rem is the reason for first argument /C.

rem The second argument is the command to execute by cmd.exe which is
rem the batch file name with complete path which must be enclosed in double
rem quotes for safety in case of batch file name or path contains one or more
rem spaces. But additionally the batch file itself must be started with at
rem least two more arguments.

rem The first argument for the batch file is ELEV which is used as indication
rem to detect if this batch file is already started a second time via the
rem VB script using local built-in administrator account.

rem The second argument for the batch file is the application to
rem run with full default path which is the batch file folder.

rem And last all parameters passed to this batch file on initial run should
rem be also passed to second execution of this batch file under the different
rem environment of local built-in administrator account.

rem This nesting of batch file arguments in command processor arguments written
rem into a VB script file which requires additionally escaping each double quote
rem within a string with one more double quote results in a strange syntax for
rem the line to write into the VB script file.

(
    echo Set UAC = CreateObject("Shell.Application"^)
    echo UAC.ShellExecute "%SystemRoot%\System32\cmd.exe", "/D /C """"!BatchFileName!"" ELEV ""!AppToRun!""!BatchArgs!""", , "runas", 1
) >"!vbsGetPrivileges!"
endlocal

rem Now the created VB script file can be executed with Windows Script Host.
rem That should be preferred the 64-bit wscript.exe on 64-bit Windows.
rem Then the VB script file can be deleted as no longer needed and processing
rem of this batch file under current user account ends resulting in returning
rem to command process which results in closing the console window if not
rem executed by cmd.exe started with option /K to keep the console window
rem opened like on opening a command prompt window and running this batch
rem file from within the command prompt window.

if not exist %SystemRoot%\Sysnative\WScript.exe (
    %SystemRoot%\System32\WScript.exe "%vbsGetPrivileges%"
) else %SystemRoot%\Sysnative\WScript.exe "%vbsGetPrivileges%"
del "%vbsGetPrivileges%"
exit /B

rem Here starts the main code of the batch file which needs to be
rem executed with elevated privileges of a local administrator.

rem First is checked if the first parameter of the batch file is ELEV
rem which indicates that this batch file was started a second time
rem using administrator privileges or local administrator account.

:RunMainCode
if "%~1" == "ELEV" (

    rem In this case the second argument is the application to run with
    rem batch file folder passed from initial run to this second run of
    rem the batch file. The current directory is now not anymore the initial
    rem current directory, but %SystemRoot%\System32 as set by Windows on
    rem starting a command process using RunAs and administrator account.
    rem This must be taken into account on further batch file processing.

    rem For this batch file it does not matter what is the current directory
    rem as it is written to work with path of the application to run defined
    rem on starting the batch file (initially). So there is no need to use
    rem CD /D "%~dp0"  or  PUSHD "%~dp0"  as many "run as administrator"
    rem solutions use to change the current directory to directory of the
    rem batch file. There is also no need for  CD /D "%~2"  or  PUSHD "%~2"
    rem here which of course could be also used.

    rem The two additionally added arguments ELEV and the application to
    rem run are removed from the arguments lists by using twice the
    rem command SHIFT to restore the initial arguments list.

    set "AppToRun=%~2"
    shift /1
    shift /1
)

rem The batch file could be still processed by 32-bit cmd.exe on 64-bit
rem Windows in case of an elevation was not necessary at all. Start with
rem 32-bit cmd.exe in this case the 64-bit cmd.exe for processing the batch
rem file. The 32-bit cmd.exe waits for self-termination of 64-bit cmd.exe
rem which happens on batch file processing is exited by 64-bit cmd.exe.

if not exist %SystemRoot%\Sysnative\cmd.exe goto RunApp
%SystemRoot%\Sysnative\cmd.exe /D /C ""%~f0" %*"
exit /B

rem If this batch file was started (initially) with a parameter string,
rem interpret the first parameter string as application to run with
rem full path if the specified executable file exists at all.

rem Then run the application with full path and its parameters.

:RunApp
if not "%~1" == "" (
    if exist "%~1" set "AppToRun=%~1"
)
"%AppToRun%" c: -enable
endlocal

6.此任务的最佳解决方案

但结果是,在我完成了上面的代码编写和测试之后,在写了这个很长的答案并在发布之前,阅读了RichardOpen Command Window in Windows x64 mode上对他的答案所写的评论,最好的解决方案很可能是使用NSIS代码,如在
How do you request administrator permissions using NSIS?
并在命令脚本中使用底部的几行也作为我在Open Command Window in Windows x64 mode上从32位切换到64位环境的答案。

dzhpxtsq

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

deyfvvtc

deyfvvtc3#

我想指出NSIS处理UAC和提升权利的具体方式。
如果您的NSIS安装程序需要运行具有提升权限的任何内容,则必须在NSIS脚本中指示如下:

RequestExecutionLevel admin

一旦你这样做,当你启动安装程序,它会弹出UAC提示,并在连续运行外部脚本或程序,需要提升权限不会有任何问题。
这与Mofi的答案#5非常一致-我仍然发布这一条,因为我认为它归结为需要知道。国家情报局似乎是你的压轴好戏。
供参考:NSIS -无法将更新的PATH写入HKLM

相关问题