How to request Administrator access inside a batch file

287,841

Solution 1

This script does the trick! Just paste it into the top of your bat file. If you want to review the output of your script, add a "pause" command at the bottom of your batch file.

UPDATE: This script is now slightly edited to support command line arguments and a 64 bit OS.

Thank you Eneerge @ https://sites.google.com/site/eneerge/scripts/batchgotadmin

@echo off

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
    IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" (
>nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system"
) ELSE (
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
)

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    set params= %*
    echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    del "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------    
    <YOUR BATCH SCRIPT HERE>

Solution 2

Here's what I've been using:

@echo off
if not "%1"=="am_admin" (
    powershell -Command "Start-Process -Verb RunAs -FilePath '%0' -ArgumentList 'am_admin'"
    exit /b
)

echo main code here
pause

Notes:

  • The -Verb RunAs flag of Start-Process is what enables the administrative elevation.
  • Only tested on windows 7 and 10, you might have to mess around with the quoting
  • Doesn't support passing along arguments for now, but you might be able to add more stuff to -ArgumentList. Note that -ArgumentList accepts either a single string or a string array.

Solution 3

Here is my code! It looks big but it is mostly comment lines (the lines starting with ::).

Features:

  • Full argument forwarding
  • Does not change working folder
  • Error handling
  • Accepts paths with parenthesis (except for %TEMP% folder)
  • Supports UNC paths
  • Mapped folder check (Warn´s you if admin can´t access mapped drive)

  • Can be used as an external library (check my post at this topic: https://stackoverflow.com/a/30417025/4932683)

  • Can be called when/if needed anywhere in your code

Just attach this to the end of your batch file, or save it as a library (check above)

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:RequestAdminElevation FilePath %* || goto:eof
:: 
:: By:   Cyberponk,     v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc
::          v1.4 - 17/05/2016 - Added instructions for arguments with ! char
::          v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful
::          v1.2 - 30/07/2015 - Added error message when running from mapped drive
::          v1.1 - 01/06/2015
:: 
:: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights.
:: Returns: -1 if elevation was requested
::           0 if elevation was successful
::           1 if an error occured
:: 
:: USAGE:
:: If function is copied to a batch file:
::     call :RequestAdminElevation "%~dpf0" %* || goto:eof
::
:: If called as an external library (from a separate batch file):
::     set "_DeleteOnExit=0" on Options
::     (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD%
::
:: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file
::     call :RequestAdminElevation "%_ThisFile%" %* || goto:eof
::
:: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments:
::      set "args=%* "
::      call :RequestAdminElevation .....   use one of the above but replace the %* with %args:!={a)%
::      set "args=%args:{a)=!%" 
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
  if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
  :: UAC.ShellExecute only works with 8.3 filename, so use %~s1
  set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
  :: Remove parenthesis from the temp filename
  set _FN=%_FN:(=%
  set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"

  :: Test if we gave admin rights
  fltmc >nul 2>&1 || goto :_getElevation

  :: Elevation successful
  (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% )) 
  :: Set ERRORLEVEL 0, set original folder and exit
  endlocal & CD /D "%~dp1" & ver >nul & goto:eof

  :_getElevation
  echo/Requesting elevation...
  :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1
  echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof) 
  echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
  :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1
  echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
  echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"

  :: Run %_vbspath%, that calls %_batpath%, that calls the original file
  %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)

  :: Vbscript has been run, exit with ERRORLEVEL -1
  echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Example on how to use it

:EXAMPLE
@echo off

 :: Run this script with elevation
 call :RequestAdminElevation "%~dpfs0" %* || goto:eof

  echo/I now have Admin rights!
  echo/
  echo/Arguments using %%args%%:    %args%
  echo/Arguments using %%*: %*
  echo/%%1= %~1
  echo/%%2= %~2
  echo/%%3= %~3

  echo/
  echo/Current Directory: %CD%
  echo/
  echo/This file: %0
  echo/

pause &goto:eof

[here you paste the RequestAdminElevation function code]

Solution 4

Another approach is to

  • create a shortcut locally and set it to call for Admin permission (Properties, Advanced, Run as Admin)

and then

  • send your users the shortcut (or a link to the shortcut rather than one to the batch file itself).

Solution 5

Another PowerShell Solution...

This is not about running a batch script as admin per, but rather how to elevate another program from batch...

I have a batch file "wrapper" for an exe. They have the same "root file name", but alternate extensions. I am able to launch the exe as admin, and set the working directory to the one containing the script, with the following one line powershell invocation:

@powershell "Start-Process -FilePath '%~n0.exe' -WorkingDirectory '%~dp0' -Verb RunAs"

More info

There are a whole slew of additional Start-Process options as well that you can apply! Check out: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6

Note that I use the @ prefix. That's equivalent to @echo off for the one line. I use %~n0 here to get the "root name" of the batch script, then I concatenate the .exe to point it the adjancent binary. The use of %~dp0 provides the full path to the directory which the batch resides. And, of course, the -Verb RunAs parameter provides the elevation.

Share:
287,841

Related videos on Youtube

skb
Author by

skb

Updated on April 21, 2022

Comments

  • skb
    skb about 2 years

    I am trying to write a batch file for my users to run from their Vista machines with UAC. The file is re-writing their hosts file, so it needs to be run with Administrator permissions. I need to be able to send them an email with a link to the .bat file. The desired behavior is that when they right-click on the file and say Open, they will get one of those UAC dialogs that makes the screen go dark and forces them to answer whether they want to give the application permission to run as administrator. Instead, they are just seeing "Access denied" on the command line window.

    Is this possible to do differently?

    • Michael Repucci
      Michael Repucci over 7 years
      If you came across this and, like me, are happy with using PowerShell, don't miss the one-liner from @toster-cx. Perfect!
  • matt burns
    matt burns over 11 years
    I hate having to do this filthy dos batch nonsense but sometimes you are forced to and this works great. Cheers!
  • Robert Snyder
    Robert Snyder about 11 years
    Just as a FYI this is tested as working in Windows 8 Embedded
  • ponomy
    ponomy over 10 years
    This throws my machine into a spiral of command windows opening and closing diagonally across the screen. The only way to stop it is to delete the original batch file. It is repeatedly running my batch file and writing the vbs file. The first time it asked for authorization, but after that it just loops.
  • Ben Gripka
    Ben Gripka over 10 years
    Sorry it is causing you issues, @TomDestry. Can you troubleshoot the problem? Can you tell why it loops? What OS are you using? On my windows 7 setup and many other windows 7 systems I have used this on, it has worked without fail. Happy to help improve the script if you can provide some more input.
  • ponomy
    ponomy over 10 years
    Ben, I'm on Windows 7 too, SP1. It seems the vbs call returns error code 2, which causes the script to goto UACPrompt again, and again, and again. I don't know what error code 2 means, so I can't get much further.
  • J Higs
    J Higs over 10 years
    Yes it works for me on XP now. Thanks! You can remove the line after :gotAdmin that deletes getadmin.vbs since you now delete it after it runs. @TomDestry Usually error code 2 means ERROR_FILE_NOT_FOUND
  • Ben Gripka
    Ben Gripka over 10 years
    @TomDestry if JHigs is right about error code 2 meaning file not found, it appears the user account can't right to the temp directory. Not sure there is anything the script can do to fix that. Does the file need to be written somewhere else? JHigs, I removed the second delete. Thanks for the input.
  • Steve Jansen
    Steve Jansen over 10 years
    @BenGripka - Great post! I'm curious why you put the stdout/stderr redirects in front of the command (e.g., > nul 2>&1 foo.exe instead of foo.exe > null 2>&1). I feel proficient at windows batch scripting, but have never seen this style before; I was surprised it even worked. Is there an advantage to this? Thanks!
  • Alexandru
    Alexandru over 9 years
    runas will fail if you are running in WOW64 (a 32 bit process on 64 bit Windows) for example %systemroot%\syswow64\cmd.exe...source: ss64.com/vb/shellexecute.html
  • Ben Gripka
    Ben Gripka over 9 years
    @SteveJansen I found this script on Eneerge's website that was given credit above. Typically, like you, I put the arguments and redirects after the exe. But when something works, it seems best to leave it be.
  • Ben Gripka
    Ben Gripka over 9 years
    @Alexandru do you have a proposed edit so it works for WOW64 and the typical scenarios?
  • Alexandru
    Alexandru over 9 years
    @BenGripka Honestly, the best solution I've come up with is to not use a batch script, and instead just write an executable, sad as it is, and not necessarily the answer to this question...something like this can get the job done better and more reliably, and less chance of failure if done right, and less hoops to jump through: pastebin.com/kfivGEvt (note: I'm assuming you want UAC for something in particular, not just for the sake of getting UAC, like for launching dism...and...you can already run the application as elevated by editing the manifest for this purpose)...
  • crig
    crig over 9 years
    I ran into the exact same problem as TomDestry with the infinite loop and return code 2. This was on Windows 8.1. I know it worked on Windows 8.0, and can't say for sure whether it was the 8.1 update or something else that caused the isssue. The solution that worked for me was to not use cacls.exe (or icacls), rather: net session >nul 2>&1 IF ERRORLEVEL 1 goto UACPrompt ...
  • barbara.post
    barbara.post over 9 years
    I'm sorry I followed the advice here but keep getting infinite loop new command prompt launch with "requesting administrative privileges" when I run this script. Win 7 Pro SP1.
  • MacKinley Smith
    MacKinley Smith about 9 years
    I'm wondering what's supposed to be happening in the line set params = %*:"="". Could someone please explain to me what's going on here? For starters, %params% doesn't get assigned because there's an extra space before the equal sign. Then it looks like there's an extra quote on the end. Is there a purpose for this?
  • boen_robot
    boen_robot about 9 years
    On Windows 8.1, using "/c %~s0 %params%" doesn't seem to pass arguments. To fix this, double quotes (escaped by another double quote) are needed around the params, like "/c %~s0 ""%params%""".
  • boen_robot
    boen_robot about 9 years
    Actually, wait... The above doesn't work as expected... And like I said, it doesn't pass arguments... I'm still looking for a solution (wouldn't mind help here though). The cause is apparently that the quote replacement leads to an empty string for some reason.
  • marneborn
    marneborn about 9 years
    I had the same problem as @TomDestry on windows 8. For me the problem was that "%SYSTEMROOT%\system32\config\system" doesn't exist, so the cacls always fails causing the infinite loop. I fixed it simply by doing >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config".
  • marneborn
    marneborn about 9 years
    This solution executes the script in the directory the script lives in. I needed it to exit in the directory I ran it from (I have relative paths...). So I added cd %CD% & in the "cmd.exe", "/c cd %CD% & %~s0...
  • Chris
    Chris almost 9 years
    When I run the VBS, grant permission, and the batch file is restarted, it seems to run as intended but the new CMD session starts in the same CMD window, and still does not have admin rights - I can't write to the C;\ directory, for example. This is on a new Win7 install (in a VMware VM).
  • Matt
    Matt over 8 years
    Note that cacls is deprecated since Windows 7.
  • Rob
    Rob over 8 years
    When calling this from a batch file it caused a loop. Fixed by replacing the shell execute command with: echo UAC.ShellExecute "cmd.exe", "/c regsvr32 /s ""%~dp0myfile.ocx""", "", "runas", 1 >> "%temp%\getadmin.vbs"
  • I say Reinstate Monica
    I say Reinstate Monica over 8 years
    If you're having problems running this batch script from a network share, try copying it to a local drive first.
  • Ben Gripka
    Ben Gripka over 8 years
    @TomDestry I finally figured out the endless loop and posted an edit. Was reference to system32\cals.exe when running a 64 bit process. There may be other reasons for failure but at least now 64 bit processes are supported.
  • TomG
    TomG about 8 years
    Have suggested an edit to assign the params variable and then replace " with "" as two separate lines. This seems to solve the passing arguments issue for me.
  • cyberponk
    cyberponk about 8 years
    Check my answer to this question. It handles all these problems.
  • Mathias Müller
    Mathias Müller about 8 years
    @BenGripka Two suggested edits were approved in 2016 that changed your answer. Do you agree with the changes? If not, roll back.
  • Ben Gripka
    Ben Gripka about 8 years
    @MathiasMüller I just tested the script changes and in my environment all is working as it did before the modifications. As many have reported there was an infinite loop problem in some environments. I thought I addressed that with a change on Dec 9 2015 but potentially this edit was needed to fix that problem in other environments. I can say the edit hasn't hurt but I can't say definitively it has helped.
  • Mathias Müller
    Mathias Müller about 8 years
    @BenGripka Alright, I was asking because your answer came up in the suggested edits queue and I was not quite sure whether I should approve the edits or not. If the answer still works, then perhaps the edits aren't too bad.
  • Knyri
    Knyri almost 8 years
    Works great but I had to change a line to get it to work. The &fc;: 2>nul in set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof) was setting the errorlevel to 1. I removed that bit and it worked perfect. I'm using Windows 10 Home.
  • cyberponk
    cyberponk almost 8 years
    Does your %temp% folder have parenthesis in it´s path ? Only in this case the errorlevel 1 is supposed to be set.
  • Knyri
    Knyri almost 8 years
    Nope. Does it need the fc;: since it goes :eof right after? I'm not sure why that little bit caused the issue either, since it should be getting executed.
  • cyberponk
    cyberponk almost 8 years
    "fc;: 2>nul" is there intentionally to set ERRORLEVEL 1 before exiting, to signal an error. Could you please remove the @echo off and make a run and send me the output in a private message? Thanks!
  • cyberponk
    cyberponk almost 8 years
    Anyway, the echo/%TEMP%| findstr /C:"(" >nul tests if there is a ( char in yout %temp% environment variable, and should only run the part after the && if positive. It is strange why your ( test is returning positive though.
  • Knyri
    Knyri almost 8 years
    Ok, it seems that this issue only occurs if I'm running it from a console that I started with admin rights. Here's the output; Cleaned up for brevity. call :RequestAdminElevation "...\OXYGEN~1.BAT" || goto:eof setlocal ... ErrorLevel is 0 set "_FN=_OXYGEN~1" & echo/C:\Users****\AppData\Local\Temp | findstr /C:"(" 1>nul && (echo/ERROR: ... goto:eof) ErrorLevel is 1 ... Elevation was requested on a new CMD window New window output mirrors the above output.
  • Martin Braun
    Martin Braun almost 8 years
    Is it possible to get rid of the much code by putting it into another batch file? What I would like to see is an evaluate.bat I can put into %windir%\System32 or the same directory and then I could simply call evaluate.bat %0 or something and it will relaunch my script as admin if it has not obtained admin rights so far. Even when this solution works, it's not very handy for quick access and usage.
  • Thielicious
    Thielicious over 7 years
    So there is no other solution without using VB parts? No plain BS alternativity? Stupid Windows.
  • DarkMatter
    DarkMatter over 7 years
    Once elevated, is it possible to switch back to non-elevated ? So, in a .bat file you would have echo/I currently have non-admin/standard user rights :: Run next part with elevation call :RequestAdminElevation "%~dpfs0" %* || goto:eof echo/I now have Admin rights! :: Run next part non-elevated (ie. without elevation) call :RequestNonAdminRights "%~dpfs0" %* || goto:eof echo/I now have non-admin/standard user rights again!
  • cyberponk
    cyberponk over 7 years
    This could be done, but not with this script as is. I´m curious though, why would you want to do this ?
  • DarkMatter
    DarkMatter over 7 years
    I had planned on having a single script where I want to do certain operations in a specific order. Some of these require elevation, while others don't. For example, the order might be something like NORMAL,NORMAL,ADMIN,ADMIN,NORMAL,ADMIN,ADMIN,NORMAL
  • DarkMatter
    DarkMatter over 7 years
    What are the advantages to your script as opposed to the accepted answer ? Also, what is the reason for switching to fltmc for admin check, instead of cacls ?
  • cyberponk
    cyberponk over 7 years
    You can do normal operations after elevation is requested, I don´t think this would be a problem. Only problem would be if you are using shared network folders, because of permissions. But you can do all the normal operations first, and then request elevarion and do all the admin operations, if the order is not important.
  • cyberponk
    cyberponk over 7 years
    The advantages of this script is everything listed in the "Features" part of the answer. Basically, I work as an IT network manager and I was using the accepted answer but found many problems with it, so I created an alternative solution and got rid of all it´s bugs. I changed from cacls to fltmc for better compatibility. Cacls does not work on some windows versions and was causing error in some situations. Thanks!
  • Bill_Stewart
    Bill_Stewart over 7 years
    This answer is incorrect. The runas command cannot be used to provoke elevation.
  • Andreas Brauchle
    Andreas Brauchle over 7 years
    Is it possible to write the output of the elevated script to the main-cmd? I am calling my cmd-file from a java-application and i want to fetch the output, but I only get "Requesting elevation..." and "Elevation was requested on a new CMD window", but not the echo's of my normal cmd-File
  • cyberponk
    cyberponk over 7 years
    I´m afraid that isn´t possible with the code as is, because to request elevation the script must open a new CMD window. You might be able to write the output of your script to a file, then open the file in your java application.
  • fishbone
    fishbone over 7 years
    Please see my answer (stackoverflow.com/a/41036456/395879) about the infinite loops and how to resolve them. Also notice that "amd64" was "AMD64" in my case (upper case). And although I'm on x64, only the check for cacls in system32 worked for me. However, I would remove this check at all - see my answer
  • Arsha
    Arsha over 7 years
    This works for me but I have to replace lines like this :-------------------------------------- into this ::-------------------------------------- It just replace colon to double colon, maybe replace REM to double colon too. Thank you.
  • Arsha
    Arsha over 7 years
    arguments did not pass to the code. My command line: mybatchscript 5.6 My code: echo 'number: %1' The 5.6 is argument but it did not send to the code
  • Wolf
    Wolf about 7 years
    @vee I fixed the params part by using this line set params=%* (no spaces), what does the original version do? ...the spaces around = are obviously wrong...
  • dbenham
    dbenham over 6 years
    Major bugs fixed regarding preservation of arguments. I normally would not make such substantive changes to another user's answer. But this accepted answer is obviously important to many people, and it has been bugged since Jan 2013, when the OP attempted to enhance the code to preserve arguments. A full explanation of the bug and fix can be found at superuser.com/a/1249855/109090
  • dbenham
    dbenham over 6 years
    Note - I did not investigate the "endless loop" issue. Perhaps some techniques from the fishbone answer need to be folded into this code.
  • Tony Brix
    Tony Brix over 6 years
    If you know how many params there could be, you can pass parameters by including them after am_admin if not "%1"=="am_admin" (powershell start -verb runas '%0' 'am_admin "%~1" "%~2"' & exit) The params will be one above where they were
  • toster-cx
    toster-cx over 6 years
    Also possible to use 'am_admin %*' to pass everything, doesn't play well with quotes and spaces tho :/ You can use shift in batch to pop the first arg off, thus fixing all args except %0.
  • Laurie Stearn
    Laurie Stearn about 6 years
    Worked for you? Sadly for me, this and all the others here and from the other thread fail because of the same underlying issue. The "runas" parm (or command) fails whenever the Shell Object is created indirectly from inside another program. Thread of interest here.
  • dbenham
    dbenham over 5 years
    @rahuldottech - My fix for preserving arguments had a bug if no arguments were passed. The params var would be undefined, so the quote doubling code would result in unbalanced parens, which would escape the redirection. I fixed the code by using set params= %* instead of set params=%*, so params is guaranteed to be defined
  • undo
    undo over 5 years
    @dbenham Thank you so much! I just want to let you know that your scripts have helped me a lot over the past couple of years. Thanks a ton.
  • 世界知名伟人
    世界知名伟人 over 5 years
    I don't know why you use "%~s0 " in the vbs file which troubled me a lot when I tried to use %cd% in my batch script.Now I use %~0 instead and haven't found any thing wrong yet.
  • T.Todua
    T.Todua over 4 years
    This is good answer, but shouldnt be an accepted, because it DOESNT check if on the FIRST run it was run with ADMIN privilege or not.
  • Sritam Jagadev
    Sritam Jagadev over 4 years
    Worked for me :)
  • Pedro Duarte
    Pedro Duarte over 4 years
    To keep the working directory add cd /D %~dp0 after if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
  • AlirezaK
    AlirezaK over 4 years
    @BenGripka, Thanks a lot, However, It doesn't work for some commands such as "doskey". Is there any solutions?
  • Twonky
    Twonky over 4 years
    Good answer. Simply works while the VB script thing creates an infinite loop, even with write permission for %temp%.
  • Wolf
    Wolf almost 3 years
    Why are there two lines to change dir: pushd "%CD%" and CD /D "%~dp0"? Why is it not just pushd %~dp0?
  • Wolf
    Wolf almost 3 years
    Why are you using %~s0 instead of %~dpf0?
  • Markus AO
    Markus AO over 2 years
    Brilliant. Will save me from many a right-click. One-liner is much preferred when theres' a large amount of tiny batch files, e.g. simply for starting/stopping/restarting services, or sets thereof. (E.g. swapping config for Apache to run with different versions of PHP.)