【问题标题】:Open Command Window in Windows x64 mode在 Windows x64 模式下打开命令窗口
【发布时间】:2017-05-20 01:42:48
【问题描述】:

我有一个安装在 x64 中的应用程序。我想在 x64 命令提示符下执行这个 EXE。

案例 1:

如果我以管理员 (Start->Type, cmd.exe->Right click->Run as Administrator) 身份手动打开命令提示符,则 EXE 工作正常。我在 cmd 窗口中使用SET 命令得到以下关于环境变量的规范:

CommonProgramFiles=c:\Program Files\Common Files
CommonProgramFiles(x86)=c:\Program Files (x86)\Common Files
CommonProgramW6432=c:\Program Files\Common Files
PROCESSOR_ARCHITECTURE=AMD64

案例 2:

如果我使用提升为管理员权限的脚本文件打开命令窗口,则找不到 EXE。我通过使用SET 命令获得了环境变量的以下值:

CommonProgramFiles=c:\Program Files (x86)\Common Files
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_ARCHITEW6432=AMD64
ProgramFiles=c:\Program Files (x86)
ProgramFiles(x86)=c:\Program Files (x86)

winSysFolder=System32

问题:我必须处理 案例 2。我认为ProgramFiles 路径的差异可能是我的EXE 在第二种情况下不起作用的原因。 如何在脚本中指定它应该在 x64 命令提示符下执行?

PS:我的主要问题的链接是here

参考资料:提升为管理员的脚本文件取自 Matt 的回答 given here.

【问题讨论】:

    标签: windows batch-file cmd


    【解决方案1】:

    您似乎正在使用 32 位可执行文件以提升的权限运行批处理文件。在这种情况下,批处理文件在 %SystemRoot%\SysWOW64 中使用 32 位 cmd.exe 执行,请参阅 Microsoft 文章:

    由于批处理文件已经以提升的权限执行,并且只需要在 64 位 Windows 上由 64 位 cmd.exe 处理,因此这里有几行来确保批处理文件由 64 位执行64 位 Windows 上的 Windows 命令处理器。

    @echo off
    if "%ProgramFiles(x86)%" == "" goto MainCode
    if not exist %SystemRoot%\Sysnative\cmd.exe goto MainCode
    %SystemRoot%\Sysnative\cmd.exe /C "%~f0" %*
    goto :EOF
    
    :MainCode
    set Program
    pause
    

    将您的主要批次代码放在标签:Maincode下方。

    如果批处理文件在环境变量 ProgramFiles(x86) 根本不存在的 32 位 Windows 上运行,则第一个 IF 条件跳转到主批处理代码。

    仅在 64 位 Windows 上执行的第二个 IF 条件如果找不到文件 %SystemRoot%\Sysnative\cmd.exe,则跳转到主批处理代码,因为批处理文件已由 64 位 cmd.exe 处理。

    Sysnative 不是目录。它是一个特殊别名,仅当 32 位环境在 64 位 Windows 上处于活动状态时才存在。因此,只能使用条件if exist %SystemRoot%\Sysnative\* 来检查任何文件是否存在,但不能使用条件if exist %SystemRoot%\Sysnative 来检查目录是否存在,因为Sysnative 不是目录。

    要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

    • cmd /?
    • echo /?
    • goto /?
    • if /?
    • pause /?
    • set /?

    【讨论】:

    • 非常感谢,我认为它已经解决了我的问题,但在我的 windows 嵌入式系统上测试后会更新。
    【解决方案2】:

    最简单的方法是使用 SysNative 路径。这是您的 RunAsAdmin.cmd(最初发布在此处:How can I auto-elevate my batch file, so that it requests from UAC administrator rights if required?)的修改版本:

    ::::::::::::::::::::::::::::::::::::::::::::
    :: 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
     IF EXIST %SystemRoot%\SysNative\cmd.exe set winSysFolder=SysNative
     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
    

    【讨论】:

    • 抄袭自Matt's post,网站许可要求正确署名。
    • 正如我已经告诉 Mofi,它来自 skm 的原始问题。没想到之前已经发过了。由于您提供了原始链接,因此我现在已将其包含在我的答案中。
    • 好吧,如果批处理文件使用双引号括起来的 1 个或多个参数执行,Matt 的代码将不起作用,因为参数字符串包含 1 个或多个空格。例如,使用exit /B 在行上方插入echo %* & pause,将ewfmgr c: -enable 替换为echo %*,使用"%ProgramFiles%" "hello world" 运行此批处理文件,然后在海拔提示上单击“是”按钮会导致两个控制台窗口。底部的来自初始调用,参数列表正确,顶部的参数列表错误,因为双引号丢失。
    • 但是,如果最初调用批处理文件时没有参数或仅使用不包含在双引号中的参数字符串,因为不包含需要使用双引号的字符,则代码有效。顺便说一句:set cmdInvoke=1 无法使用Richard 发布的代码,因为这会导致错误消息Windows cannot find 'C:\Windows\SysNative\cmd.exe',即使从 32 位环境中启动也是如此。 skm 应该选择比 Matt 编写的代码更好的东西。
    • ss64.com 上的脚本包含处理引用参数的代码:ss64.com/vb/syntax-elevate.html 或者,由于 skm 无论如何都在使用 NSIS,使用它来请求管理员权限会简单得多:stackoverflow.com/questions/8732019/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 2015-12-23
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    相关资源
    最近更新 更多