Passing Unicode parameters to Windows .bat file when rerunning it - windows

My .bat file looks like this:
#echo off
CD /D "%~dp0"
if [%2]==[] (
set user=%USERNAME%
) else (
set user=%2%
)
:getFile
if [%1]==[] (
set /p file=Enter file name :
) else (
set file=%~f1
echo File name: %~f1
)
:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a
if not exist "%file%" (
echo Error: Could not find file: %file%
echo.
)
:: Check for admin permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' == '0' (
goto gotAdmin
)
:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" ""%file%"" ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
echo.
:eof
pause
exit /B
I have these two test files:
C:\Test\Folder\ファイル.txt
C:\Test\フォルダ\File.txt
When I run the batch file above and drag 1 onto the cmd window I get:
, which is good.
When I do the same for 2, I get:
When I call UAC.ShellExecute, %file% isn't passed correctly.
How can I get around this problem?

My preferred way of starting a batch file with administrator permissions is to create a shortcut, and then mark that shortcut as requiring administrator permissions.
First right-click foo.bat, then create a shortcut. Open the properties for that shortcut, click the Advanced… button and enable Run as administrator.
This has a downside: you can't drag file names onto the resulting command prompt window. But you can drag a file onto the shortcut.
But what if I don't want or can't use a shortcut?
You can avoid the need to write arbitrary Unicode characters to the file by passing your file name as an argument to your script. Even if the VBS file is in ANSI encoding, the script host always uses Unicode internally.
So here is how you write the VBS file and run it:
:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" """ + Wscript.Arguments.Item(0) + """ ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs" "%file%"
exit /B

Try adding a CHCP (CHange Code Page) command to start of you batch file, using the UTF-8 code page 65001, e.g:
#echo off
chcp 65001
.
.
.
See here for a bit more info on code page identifiers: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
EDIT: You MUST also use a unicode capable font such as Lucida Console for your command window. Without this the command processor chokes on the unicode characters, and will either not find the files, or may display a "system cannot write to the specified device" error.
Click the window icon at the top-left of the command window, choose Defaults on the menu, then on the Fonts tab choose Lucida Console.
UPDATE - Test batch file and output below.
Here's the batch file I'm using to test this:
#echo off
chcp 65001
CD /D "%~dp0"
:getFile
if [%1]==[] (
set /p file=Enter file name :
) else (
set file=%~f1
echo File name: %~f1
)
:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a
if not exist "%file%" (
echo Error: Could not find file: %file%
echo.
) else (
echo Found file "%file%"
)
Here is the output from my test, when I drag firstly "C:\temp\test\ファイル.txt" into the window, then secondly "C:\temp\test\フォルダ\file2.txt".
My system is Win 7 Pro x64 SP1, with English UK settings.

Your problem is that the way you create your temporary VBS file means it is not a valid unicode file and so Windows doesn't know how to interpret the unicode name you have passed in.
Following beercohol's advice to use code page 65001, I still found that I could not access a file in a unicode directory. However, if I tried to create the file by hand with a unicode editor (e.g. using notepad and saving as a unicode encoding) and invoke that manual script instead of the autogenerated VBS file, it all just worked.
I've re-worked your script to use iconv to create a utf-16 file instead. Note that this script needs to be run with code page 65001 in order to work.
#echo off
CD /D "%~dp0"
if [%2]==[] (
set user=%USERNAME%
) else (
set user=%2
)
:getFile
if [%1]==[] (
set /p file=Enter file name :
) else (
set file=%~f1
echo File name: %~f1
)
:checkFile
for /f "useback tokens=*" %%a in ('%file%') do set file=%%~a
if not exist "%file%" (
echo Error: Could not find file: %file%
echo.
)
:: Check for admin permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' == '0' (
goto gotAdmin
)
:: Rerun this batch with admin rights
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd", "/c """"%~f0"" ""%file%"" ""%user%""""", "%CD%", "runas", 1 >> "%temp%\getadmin.vbs"
iconv.exe -f utf-8 -t utf-16le "%temp%\getadmin.vbs" > "%temp%\getadmin2.vbs"
"%temp%\getadmin2.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
if exist "%temp%\getadmin2.vbs" ( del "%temp%\getadmin2.vbs" )
pushd "%CD%"
CD /D "%~dp0"
echo.
:eof
pause
exit /B

Related

Batch file won't copy folder and files from batch directory

I have a batch file with three multiple choice options. If I select A, it is supposed to copy a folder called Files (located in the same root directory as the batch file) to the root of the C:\ drive. I can't seem to understand why the %SystemDrive% variable isn't working and wants to point to C:\Windows\system32.
Any ideas?
run.bat
#echo off
set /a _Debug=0
::==========================================
:: Get Administrator Rights
set _Args=%*
if "%~1" NEQ "" (
set _Args=%_Args:"=%
)
fltmc 1>nul 2>nul || (
cd /d "%~dp0"
cmd /u /c echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "cmd.exe", "/k cd ""%~dp0"" && ""%~dpnx0"" ""%_Args%""", "", "runas", 1 > "%temp%\GetAdmin.vbs"
"%temp%\GetAdmin.vbs"
del /f /q "%temp%\GetAdmin.vbs" 1>nul 2>nul
exit
)
#ECHO OFF
TITLE WINDOWS AUTOMATION UTILITY
COLOR 02
CLS
ECHO.
ECHO THIS UTILITY HELPS AUTOMATE WINDOWS 10
ECHO ======================================
ECHO.
:MENU
ECHO [A] Copy 'Files' directory from installation media to System Drive
ECHO [B] Set default Start menu for all users
ECHO [C] EXIT Remove bloatware apps from Windows 10
choice /C ABC /M "Select Mode:" /N
IF %ERRORLEVEL% EQU 3 goto End
IF %ERRORLEVEL% EQU 2 goto B
IF %ERRORLEVEL% EQU 1 goto A
::
:B
CLS
ECHO THIS IS B
TIMEOUT 2 >nul
CLS
GOTO MENU
::
:A
CLS
ECHO THIS IS A
TIMEOUT 2 >nul
CLS
ROBOCOPY "%~dp0Files" %SystemDrive% /MT
GOTO MENU
::
:End
CLS
ECHO You've reached the end
PAUSE
EXIT 0
Robocopy result
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : 23 March 2020 00:15:09
Source : D:\Users\Will\Documents\IT Projects\Windows\Windows 10 Image\Files\
Dest : C:\Windows\system32\
Files : *.*
Options : *.* /DCOPY:DA /COPY:DAT /MT:8 /R:1000000 /W:30
------------------------------------------------------------------------------
UPDATE
#Durry42
Typing Set into Command Prompt does return C:\
#aschipfl
I think I tried appending a backslash at the end of %SystemDrive% and it made no difference.

Copying a file from local folder to "C:\Windows\System32\" using batch file

I am writing an application which uses batch file to copy some files to another location. I am using 64-bit windows 7.
I have asked for admin privileges too using below code:
Code block to get ADMIN right:
#echo off
:: BatchGotAdmin (Run as Admin code starts)
REM --> Check for permissions
>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"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
:: BatchGotAdmin (Run as Admin code ends)
:: Your codes should start from the following line
Code to copy a file to system32 folder:
copy /d /Y "D:\opt\optPath.txt" "C:\Windows\System32\"
There is no error in copy operation, but the file is copied to "C:\Windows\SysWOW64" location automatically. Need help.
Try using:
#echo off
:: Batch-Admin API
net file>nul 2>&1&&if "%~1"=="64" (goto:GotAdmin) else (if exist "%windir%\Sysnative\" (call start %windir%\Sysnative\cmd /c "%~0" 64&exit) else (goto:GotAdmin))
echo Requesting administrative privileges...
(echo Set UAC = CreateObject^("Shell.Application"^)
echo UAC.ShellExecute "%~s0", "ELEV","", "runas", 0 ) > "%temp%\admin.vbs"
cscript /Nologo "%temp%\admin.vbs"&exit
:GotAdmin
:: Place ADMIN tasks below
copy /d /Y "D:\opt\optPath.txt" "C:\Windows\System32\"
pause
exit
I modified rewrote your script to:
Use an alternative way to check for admin permissions net file && echo Admin || echo No-admin
Added 64-bit launcher VBScript launches everything as 32-bit (redirecting C:\Windows\System32 to C:\Windows\SysWOW64).
64-Bit launcher:
call start %WinDir%\SysNative\cmd /c %0 (This window is hidden)

How to write a batch file can run parameters as command with administrative privileges?

The question is different from How can I auto-elevate my batch file, so that it requests from UAC administrator rights if required?
since there will be some problems when passing arguments to a batch file which has the code of acquiring administrative privileges.
After the privileges have been obtained, the arguments is lost and become undefined.
I solve this problem by storing the arguments to a file first, please see detail in my answer.
Say the require batch file is run_as_admin.bat,
By running run_as_admin.bat your_command your_params we can execute the command with administrative privileges (e.g. run_as_admin delete /path/to/system_file).
To run parameters as command, run_params_as_cmd.bat
%*
pause
To get administrative privileges, I find some code
from http://larrynung.github.io/2014/01/01/batch-run-as-administrator/
Then I tried the following code run_as_admin.bat:
#echo off
call:TryToRunAsAdmin
if %ERRORLEVEL%==1 exit /B
echo got administrative privileges...
:: run parameters as command <<< Here '%*' seems not be executed as a command.
%*
pause
goto :eof
:TryToRunAsAdmin
set GetAdminScriptFile="%temp%\getadmin.vbs"
REM --> Check for permissions
>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...
call:UACPrompt
set ERRORLEVEL=1
) else (
if exist %GetAdminScriptFile% ( del %GetAdminScriptFile% )
set ERRORLEVEL=0
)
goto :eof
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > %GetAdminScriptFile%
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> %GetAdminScriptFile%
call %GetAdminScriptFile%
goto :eof
To test that code, I tried some command which needs admin privileges
run_as_admin.bat reg add "HKLM\SOFTWARE\Classes\.php" /v PerceivedType /d text
run_as_admin.bat %SystemRoot%\system32\drivers\etc\hosts_old.txt
but these commands seem to be not executed but ignored as a string.
I guess the problem is related to the code, is there any other ways to
write a batch file can run parameters as a command with administrative privileges?
The arguments passing to run_as_admin.bat will gone when requesting administrative privileges.
So you need to store the arguments first.
Here is the solution:
#echo off
SET commandline=%*
:: store it to file
echo %commandline% > "__temp__.bat"
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
>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"
:--------------------------------------
:: execute command administrative privileges with and then delete the temp file
call "__temp__.bat"
del "__temp__.bat"
pause

Run bat file as administrator but shown on user's profile

I wrote this script to run a file remotely on another computer, however I would like to run it as an administrator user but for it to be shown on the user's computer. How do I run a script as administrator remotely but to show it on the user's profile?
#echo off
color 0a
SET /p ComputerName=ComputerName:
SET /p UserName=Please enter the username:
SET /p UserNamePassword=Please enter Username Password:
tasklist /s \\%ComputerName% /u %UserName% /p %UserNamePassword% /FI "memusage gt 200000"
SET /p Value=would you like to continue? Press 1 if yes.Press 2 to exit:
IF %Value% EQU 1 pushd \\NetworkPath & copy batfile.bat \\%ComputerName%\c$\Users\%UserName%\Desktop & popd & psexec -i -s -d \\%ComputerName% -u %UserName% -p %UserNamePassword% "C:\Users\%UserName%\Desktop\batfile.bat"
IF %Value% EQU 2 exit
You could try using the command line nircmd elevate "the path of your program.bat" to start the program. Or you could create another .bat file reading this:
nircmd elevate "the path of your program.bat"
exit
To open your main program, just open this second .bat program and it will open your main program as the administrator and then close itself out.
Nircmd is not a default windows command. You would have to download it from this website by clicking on the "Download NirCmd" button on the bottom of the webpage. Choose to save this .zip file, and when it is done, extract it. Then only copy the file "nircmd.exe" into your "system32" directory or %systemroot%. Now nircmd is part of the commands you can use in "cmd.exe".
I have nircmd on my computer, if you have trouble trusting it. It is a very useful tool to have. The above link also has a list of all of the functions and their descriptions.
You could also use this to make a batch-file run as admin:
SET ADMIN=0
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (GOTO askAdmin)
SET ADMIN=1
GOTO gotAdmin
:askAdmin
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
Put that at the top of your batch-file

Using command prompt , How can I get the path where chrome exe is installed?

I am writing a batch file and I need to start chrome exe using that batch file . So for that I need to get the path of the directory where chrome is installed .
Usually it is installed in " C:\Program Files (x86)\Google\Chrome\Application" but some users change the path while they install chrome.
I will like to get the path of that chrome exe on run time using command prompt and start it from there.
The content of my batch file are : Where for the highlighted code I want to get on run time instead of hard coding it into my .bat file
(I took help of this to get admin rights.)
#echo
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
>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"
:----------------------https://stackoverflow.com/questions/1894967/how-to-request-administrator-access-inside-a-batch-file----------------
echo Closing all instances of chrome.....
taskkill /f /im chrome.exe
echo All instances of chrome closed. Now going to chrome exe location
cd **C:\Program Files (x86)\Google\Chrome\Application**
echo Reached to chrome exe location. Ready to start new chrome with web security off.
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Get the installed location of Google Chrome from the registry
"HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\Google Chrome\shell\open\command"
"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Clients\StartMenuInternet\Google Chrome\shell\open\command"
Example:
set "Command="
for /f "tokens=2,*" %%A in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\Google Chrome\shell\open\command" /ve 2^>nul') do set "Command=%%~B"
if not defined Command for /f "tokens=2,*" %%A in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Clients\StartMenuInternet\Google Chrome\shell\open\command" /ve 2^>nul') do set "Command=%%~B"
if not defined Command echo Google Chrome was not found.
if defined Command start "Browser" "%Command%"

Resources