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

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.

Related

Batch to copy all files in subfolders to a destination without recreating the subfolders

I'm still pretty new to batch scripting, but I'm currently working on a batch file that when launched lets me select a source and destination folder from a menu. Now in my source folder, it has sub-directories with more directories in those. I'm trying to get the batch file to take any and all files in my source folder and copy them into a single folder[Destination] without recreating the folder structure so that all of the files in my sources sub-directories are nice compiled at destination.
I've tried xcopy, robocopy, and to an extent for loops. My guess is that it'll have to be done through for loops, however I'm not sure the appropriate code I should be using for this. I would like all file types to be workable with this program and not just: jpg, jpeg, png, and gif.
Thanks for the help.
#echo off
title File Copier
color 0a
:Menu
cls
echo Main Menu
echo ---------
echo Press 1 to copy files
echo.
echo Press 2 for information
echo.
echo Press 3 to exit
echo ---------------
set /p input=
if %input% == 1 goto 1
if %input% == 2 goto 2
if %input% == 3 goto 3
goto Menu
:1
rem Source
cls
echo Please select your source folder.
echo ---------------------------------
setlocal
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please select your source folder:',0,0).self.path""
for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"
setlocal enabledelayedexpansion
cls
rem Destination
echo Please select your destination folder.
echo --------------------------------------
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please select your destination folder:',0,0).self.path""
for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder2=%%I"
setlocal enabledelayedexpansion
cls
rem Source/Destination Info
Set source=!folder!
Set target=!folder2!
Echo Source: %source%
Echo Destination: %target%
echo ---------------------------------------------------------------------
:Choice
set /P c=Would you like to proceed? [Y/N]
if /I "%c%" EQU "Y" goto Yes
if /I "%c%" EQU "N" goto No
goto Choice
:Yes
cls
rem echo D | xcopy %source% %target% /-y
rem robocopy "%source%" "%destination%" *.* /E
for /d %a in (%source%) do #copy %a\*.jpg %target%
for /d %a in (%source%) do #copy %a\*.png %target%
for /d %a in (%source%) do #copy %a\*.gif %target%
pause
goto Success
:No
goto 1
:Success
cls
echo The file(s) were successfully copied.
timeout /t 4 >nul
goto Menu

Batch: How to scroll through files to read to a variable?

I'm trying to have it scroll through a directory and present a new variable when the user replies "N". I have it all figured out except how to go to the next variable.
cd "C:\Test"
for /r %%F in (*) do SET Show=%%~NF
echo %Show%
echo.
SET /P Continue=Continue?(Y/N)
if /I "%Continue%" EQU "y" goto :Run
if /I "%Continue%" EQU "n" goto :Start
If you're looking to scroll the directory and prompt the user the file name and have them choose to choose it or continue, then bellow should help you.
Firstly, we can use dir /b /a:d to display only directories (folders) in the the current directory. By using a code block ( & ) we can put batch script inside the for loop. For your sake, we can use the CHOICE command to prompt to continue the loop or to save current folder to string and do something with it.
ScrollTreeWithPrompt.bat:
#echo off
setlocal EnableDelayedExpansion
Rem | Configuration
Set "MainDir=C:\Test"
Rem | Get Each Project Folder
for /f "tokens=*" %%A in ('dir "!MainDir!\" /b /a:d') do (
Cls
Echo Current Folder: %%A
echo(
CHOICE /M "Continue?"
Rem | Check for "N" - If so Set String & goto
IF "!ERRORLEVEL!"=="2" (
Set "Choice=%%A"
GOTO Run
)
)
Rem | No Further Results
Cls
Echo Warning: No further folders found.
pause>NUL
goto :EOF
:Run
Cls
echo Currently selected: !MainDir!\!Choice!
pause>NUL
goto :EOF
I have left a few Rem comments in the script to help you along. For any more help on the commands, type the following into a command prompt:
choice /?
set /?
for /?
goto /?
Is this what you need:
For /R "C:\Test" %%A In (*) Do (Choice /M "%%~nA"
If Not ErrorLevel 2 (Set "Show=%%~nA" & GoTo Run))
Exit /B
:Run
Echo Running against %Show%
Pause
Alternatively, should you wish to return to the loop after running against the file name, then use Call instead of GoTo:
For /R "C:\Test" %%A In (*) Do (Choice /M "%%~nA"
If Not ErrorLevel 2 Call :Run "%%~nA")
Exit /B
:Run
Set "Show=%~1"
Echo Running against %Show%
Pause

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)

Run Batch File as Administrator using RunOnce

I have a program installed on various machines, which needs a manual update.
I have all of the updated files stored on a share on a server, and have written a batch file that will copy these into the correct local directory (Program Files (x86))
My plan is to deploy a group policy which will execute this batch file on RunOnce, updating the program when the users first log in.
The problem is to write to the directory, I have to run the batch file as Administrator.
How can I do this using RunOnce? Is there another way?
I've tried using RoboCopy, but just get "Access Denied" and the same problem.
Below is my batch file code.
IF EXIST "C:\Program Files (x86)\NetHelpDesk\\." (goto CopyNetHelp) else Goto ExitLoop
:CopyNetHelp
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\nethdclient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\NetHelpDeskClientUpdater.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\nhescalatorclient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
:ExitLoop
Exit
Try this:
#echo off
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (GOTO askAdmin)
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" )
pushd "%CD%"
CD /D "%~dp0"
:: batch is being ran as admin
:skipAdmin
IF EXIST "C:\Program Files (x86)\NetHelpDesk\\." (goto CopyNetHelp) else Goto ExitLoop
:CopyNetHelp
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\nethdclient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\NetHelpDeskClientUpdater.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\nhescalatorclient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
:ExitLoop
Exit
Just for future searches, this is how I got it to work.
I created a new batch file. This will be the one run from RunOnce.
This simply copies the "real" batch file into the users document folder if required. It then calls that batch file from the document folder, thus running it locally getting around the issue.
The "real" batch file as posted by Dennis then runs and once finished, deletes itself from the documents folder.
Copy Batch
IF EXIST "C:\Program Files (x86)\NetHelpDesk\\." (goto CopyNetHelp) else Goto ExitLoop
:CopyNetHelp
copy "\\server\data\pc_support\UpdateNetHelpAdmin.bat" "%USERPROFILE%\Documents" /y
"%USERPROFILE%\Documents\UpdateNetHelpAdmin.bat"
:ExitLoop
Exit
"Real" batch file
#echo off
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (GOTO askAdmin)
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" )
pushd "%CD%"
CD /D "%~dp0"
:: batch is being ran as admin
:skipAdmin
IF EXIST "C:\Program Files (x86)\NetHelpDesk\\." (goto CopyNetHelp) else Goto ExitLoop
:CopyNetHelp
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\nethdclient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\NetHelpDeskClientUpdater.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
COPY "\\server\programs\Nethelpdesk\NetHelpUpgrade\NhEscalatorClient.exe" "C:\Program Files (x86)\NetHelpDesk\" /y
del "%USERPROFILE%\Documents\UpdateNetHelpAdmin.bat" /q
:ExitLoop
del "%USERPROFILE%\Documents\UpdateNetHelpAdmin.bat" /q
Exit

Passing Unicode parameters to Windows .bat file when rerunning it

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

Resources