At my university, we use VMware quite extensively to allow experimentation of admin tasks on otherwise heavily locked down computers. I use the same VM's at home so I don't have to worry about the cluttered environment of my native PC, by copying it to and from my USB flash drive.
The VM I use is snapshot'd with all the settings I like, and set to revert to snapshot on shutdown, so ideally it never changes. As I use multiple computers, I have a script that checks if the VM is present, and if not, copies it over and schedules an auto-open on next login.
My current script looks like this:
#echo off
if exist "C:\Users\[Username]\Desktop\Win7x86\Win7x86.vmx" goto open
if not exist "C:\Users\[Username]\Desktop\Win7x86\Win7x86.vmx" echo VM files not found, preparing to copy from USB
goto usb
:usb
if exist "F:" goto copy
if not exist "F:" echo Please insert USB drive.
pause
goto usb
:copy
robocopy "F:\Virtual Machines\Win7x86" "C:\Users\[Username]\Desktop\Win7x86" /mir /eta
schtasks /create /ru [Username] /rp [Password] /xml "%cd%\Win7x86 Opener.xml" /tn "Win7x86 Opener"
goto open
:open
PATH "%PROGRAMFILES%\VMware\VMware Workstation\"
START vmware.exe -x "C:\Users\[Username]\Desktop\Win7x86\Win7x86.vmx"
My problem is this; sometimes I make change to the VM, and update the snapshot.
I want my script to compare the creation dates of the source files (USB) to the local files (desktop). If the local are newer, then obviously it's been copied since the last update and is fine to run, but if the source files are newer, then the local needs updating.
I plan on using vmware.log as the comparison file as it's small and retains it's creation date (some VM files are deleted and re-created during the VM running process).
I've scoured the internet and the best I found compared dates and listed the newest; but with my very limited batch scripting knowledge, I have no idea how to pipe a robocopy command off that output.
This should do it.
#echo off
for /f "tokens=* usebackq" %%d in (`wmic datafile where Name^="C:\\Users\\[Username]\\Desktop\\Win7x86\\vmware.log" get creationdate ^| findstr ^"[0-9]^"`) do ( set tmpd=%%d )
set vmlocaldate=%tmpd:~0,8%
for /f "tokens=* usebackq" %%d in (`wmic datafile where Name^="F:\\Virtual Machines\\Win7x86\\vmware.log" get creationdate ^| findstr ^"[0-9]^"`) do ( set tmpd=%%d )
set vmusbdate=%tmpd:~0,8%
if %vmusbdate% gtr %vmlocaldate% goto copy
I don't know how this will fit into your script as it will need the USB drive plugged in; at the moment you can launch your and it will straight away open the local virtual machine if it exists, you have to decide if you always need to plug the USB drive in and check the creation date, if you only want to check when if the USB happens to be present, or change your USB prompt to allow you to skip plugging the drive in.
NB. It is significantly easier in both VBScript and PowerShell.
Related
I want to copy specific file from one machine to 5 other machines, so I have server list file contains the ip addresses of each machine like:
10.10.1.3
10.10.1.4
10.10.1.5
10.10.1.6
10.10.1.7
in my batch file:
SET File=C:\Files\servers.txt
SET User=user
SET Password=pass
IF EXIST b:\ (
NET USE b: /DELETE /Y
)
FOR /F %%A IN (%File%) DO (
START /WAIT NET USE b: \\%%A\C$\Temp /user:%User% %Password%
COPY C:\Logs\L1.log b:\L1.log /Y
IF EXIST b:\ (
NET USE b: /DELETE /Y
)
)
the problem is in the first server I get error message The system cannot find the drive specified but for the others servers everything works great.
I think it's something with the NET USE of course maybe the map network is deleted before finish copy?
Is there any way in a batch file to loop some servers and for each one of the servers open map network copy files wait till copy is completed and move on to next server?
EDIT:
I have an update for this problem:
the source machine and the target machine are both in different domains.
I have a user define as admin in both of the machines.
The machines knows each other (I can open the target folder in the source machine like \server\C$\temp and I can paste anything I want there)
I tried to copy files without using net use and just copy from C:\file.log \server\c$\temp\file.log for each server (I have 5) and for 3 servers it worked and the other two I had an error: Logon failure: unknown user name or bad password
FOR /F %%A IN (%File%) DO (
COPY C:\temp\file.log \\server\c$\temp\file.log /Y
)
What can be the problem?
Please help?
Thank you in advanced.
The best way would be if the user/password is the same on every machine (credientals shared throughout the domain)
In that case, no need for NET USE, just copy to UNC path directly
FOR /F %%A IN (C:\Files\servers.txt) DO COPY /Y C:\Logs\L1.log \\%%A\C$\Temp\L1.log
I understood you have a problem on 2 machines out of 5. You cannot access C$ directly if you are not administrator of the machines.
Check:
domain (echo %USERDOMAIN% on the remote machine): All machines must be on the same domain for it to work
whether you are administrator or not on the remote machine: you cannot mount drives with the C$ trick if you are not administrator.
There is an alternate solution for you if this doesn't work out:
Share C:\TEMP (read/write) as the same name ex: sharedtemp on the 5 machines (or ask an admin to do that)
Then adapt the script like this:
FOR /F %%A IN (C:\Files\servers.txt) DO COPY /Y C:\Logs\L1.log \\%%A\sharedtemp\L1.log
Even if you are not an administrator, you'll be able to access the share that way.
When using START command, you need to either specify new window name, or leave it blank in double quotes, if you want it to run in the same open CMD window. However, you don't need to use START in this particular case. Try adding timeout for the 1st or all server connections in the list:
IF EXIST b:\null NET USE b: /DELETE
:: more code here
NET USE b: \\%%A\C$\Temp /user:%User% %Password%
if "%%A"=="10.10.1.3" timeout 5 >nul
I've gotten excellent help here recently, which I keenly appreciate. Thanks to the breadth of knowledge on this site I've been able to cobble together some code which is trivial in its purpose, yet important for my environment.
The simplified purpose, and my problem:
The goal: for the current user, upon login to Windows, move all files and folders into a desktop folder named "Archive" [create the latter if necessary]. (The content moved is put into a dynamically created subfolder based on timestamp.)
The existing problem: the code fails to move desktop folders into the (deskstop) Archive folder. (I obviously don't want to move the Archive folder itself.)
Any insight / solution would be hugely helpful. (PS if at all possible I wish to keep to DOS bat files vs more complex languages.)
My current .BAT file [note- the many variables are for initial debugging]:
++++++++++++++++++++++++++++
:: Establish desired base name for the primary desktop archive folder
set ARCH=Archives
:: Establish logged in user path to desktop
set G=%USERPROFILE%\Desktop
:: Now, if "Archives" folder does not yet exist on desktop, create it
if not exist "%G%\Archives" mkdir "%G%\%ARCH%
:: Consolidate pathname <user\desktop\Archives> into single variable (TARGET)
set TARGET=%G%\%ARCH%
:: Create [date+time specific] subfolder name -- two steps - build string, then assign
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
:: Set variable to hold new name Archives\Saved-<time-specific-subfolder> in final form
set "savedirname=Saved-%YYYY%-%MM%-%DD%-%HH%-%Min%-%Sec%"
:: Finally, append new foldername to user-specfic path (TARGET)
set MoveTo=%TARGET%\%savedirname%
:: Create final targeted destination folder - complete pathname
mkdir %MoveTo%
:: Move all desktop files/folders EXCEPT the Archives folder into the targeted destination
for %%i in (%G%\*.*) do move %%i %MoveTo%
Thank you!
(PS if at all possible I wish to keep to DOS bat files vs more complex languages.)
This isn't the answer you ask for, but this is PowerShell (v4) code to do what your code does:
$arch = "Archives"
$desktop = [Environment]::GetFolderPath("Desktop")
$saveDirName = Get-Date -f "yyyy-MM-dd-hh-mm-ss"
$target = "$desktop\$arch\$saveDirName"
mkdir $target -Force
dir $desktop | where Name -ne $arch | Move-Item -Destination $target -Force
Is it really "more complex" than your original code?
Your original code guesses that %USERPROFILE%\Desktop is the desktop - that's incorrect if the desktop is redirected, it could be \\fileserver\users\username\desktop\. It's incorrect if the OS is installed in a foreign language, in Swedish it's %UserProfile%\Skrivbord. Asking Windows where the desktop is gets the correct location every time. My code does this.
PowerShell handles dates sanely. No string manipulation, no WMI calls, one formatting string for what format you want.
I use the mkdir -Force option, it can make folders two levels deep in one go, and it does nothing if they already exist. No need for IF NOT EXIST... tests, although you could do them with Test-Path. You could use this approach in the batch file, mkdir can make multiple nested folders there, too.
NB. your code has a bug where you check for "%G%\Archives" but you mkdir "%G%\%ARCH%. If %ARCH% is meant to be configurable, they could differ.
And this version does the folder moving which you are asking about that your code doesn't yet do, and will need another abuse of a for loop to handle.
This script is half the amount of code, more readable because it directly does what it needs instead of wandering out to wmi and string manipulation and for loops for string handling, it's more correct in more situations, more resilient, and does the extra things your original doesn't.
Yes it's a bigger and more complex language - that's how it makes things easier for you, because it can do more things directly.
set fldr="%userprofile%\desktop\archive\%date:/=%%time::=%"
md %fldr%
For /f "delims=" %A in ('dir /a-d /b "%userprofile%\desktop" ^| Findstr /I /v /c:"archive"') Do #echo move "%userprofile%\desktop\%A" %fldr%
The above is all you need.
Batch isn't a programming language, although IBM engineers added programming like features.
It designed for copying files and starting programs. It becomes a stupid language if used as a programming language.
Use %%A in a batchfile. Remove Echo to have it actually move files.
To get the doc folder, which is always called desktop (explorer substitutes localised names for real names via the desktop.ini file)
for /f "skip=2 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Personal"') do set doc=%A
Use %%A in a batchfile.
I have a simple batch script that copies files locally from a Sharepoint drive that's mapped on the local machine. This runs just fine when being manually run, but when run using task scheduler, it seems as though the script cannot access the drive at all. Even a simple DIR print out fails. It's also worth noting that the user set to run the script in scheduler has full rights to everything involved and is the same account being used to run it manually.
A couple of the settings for the scheduled task:
set to run whether user is logged in or not
running with highest privileges
Any idea how I could get this working in scheduler?
Edit:
Screen shots of the scripts and the task run history
http://imgur.com/a/wCsET
EDIT 2
callCopyFiles.bat
del "C:\apache\htdocs\IESite\Reports\*.*?"
FOR /f "delims=" %%L in (directorylist.txt) do (
echo %%L >> log.txt
CALL copyfiles.bat "%%L"
)
copyfiles.bat
FOR /F "delims=" %%I IN ('DIR %1 /s /b /O:-D') DO (
COPY "%%I" "C:\apache\htdocs\IESite\Reports"
goto :end
)
:ender
My suspicion is that this line in callCopyFiles.bat:
CALL copyfiles.bat "%%L"
is failing because the current directory is different when your batch file is running as a scheduled task.
Try changing this line to list the full path...something like:
CALL C:\YourFolderHere\copyfiles.bat "%%L"
EDIT
Based on the comments, I think you likely need to map the Z: drive within the copyfiles.bat file.
EDIT 2
Don't specify the credentials when mapping the drive.
Just add NET USE Z: \\YourServer\ShareName to the copyfiles.bat file.
I've been working to clean up a messy Active Directory as well as a network file system in the same state and I understand the concept of mapping users network drives and currently use a combination of batch and vbs files to do so. However, I need to start fresh and was wondering if there was any way to detect and delete the users shortcuts on their desktop associated with the previous network drives. (Yes - I understand how to delete all of the network drives, but: How do I detect and delete the shortcuts on the desktop associated with them?)
I've already written and custom tailored my own scripts to map drives and place shortcuts. I just need to get rid of any old shortcuts. I can't afford to delete all of the .ink files on the desktop, either. Only any associated with preexisting network drives.
I'm working in an XP / Server 2003 client/server environment.
Another question: If a script runs every time a user logs on through the domain and adds the same network shares over and over again without first deleting them, (even though it would be the same script every time) would it / does it - do any harm? <- I didn't research this one a whole lot yet because i've been crawling through Google and took a peak see through Stack to try and find a solution for the first question/issue.
Any help / advice would be greatly appreciated. Thanks!
Let's say there was before in logon batch
%SystemRoot%\System32\net.exe use Z: \\OldServer\OldShare
and the users created shortcuts to files / directories on this share on their desktop or in a subdirectory of the desktop.
A shortcut file contains always both – the path to the file with drive letter as well as the UNC path with server and share names.
A simple batch file to find in the desktop directory and all its subdirectories *.lnk files containing \\OldServer\OldShare and delete all found shortcut files is:
#echo off
for /F "delims=" %%I in ('%SystemRoot%\System32\findstr.exe /I /M /S "\\\\OldServer\\OldShare" "%USERPROFILE%\Desktop\*.lnk" 2^>nul') do (
echo Deleting shortcut file "%%I"
del "%%I"
)
For details about /I /M /S run in a command prompt window findstr /?
As it can be seen each backslash in the find string must be escaped with one more backslash.
It is also possible to search for "Z:\\" instead of "\\\\OldServer\\OldShare"
But be careful with deletion of a *.lnk file just based on drive letter because users could have mapped a different share to this drive letter. Those users would not be happy if their shortcuts are deleted, too.
The batch file could ask the user for confirmation before deleting every found shortcut containing the drive letter of not anymore existing drive:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
echo Searching for shortcuts to drive Z: ...
for /F "delims=" %%I in ('%SystemRoot%\System32\findstr.exe /I /M /S "Z:\\" "%USERPROFILE%\Desktop\*.lnk" 2^>nul') do (
echo/
echo Shortcut "%%~nI" might be not valid anymore.
echo/
setlocal EnableDelayedExpansion
set Confirm=
set /P "Confirm=Delete the shortcut (y/n)? "
if /I "!Confirm!" == "y" (endlocal & del /F "%%I") else endlocal
)
endlocal
It is no problem if a network drive mapping using a command like
%SystemRoot%\System32\net.exe use Z: \\MyServer\MyShare
is done in logon batch file on every logon. An error message is output by net use if drive letter Z: is used already, for example if the network drive mapping was done persistent and the user started the computer first without a network connection, then plugged-in the network cable and next after a few seconds entered user name and password to logon to Windows and on domain server of the company.
It is possible to use
%SystemRoot%\System32\net.exe use Z: /delete 2>nul
%SystemRoot%\System32\net.exe use Z: \\MyServer\MyShare
to first delete an already existing network drive mapping before mapping the share to drive letter Z:. I do not recommend to use wildcard * instead of Z: as that would delete also all network drive mappings created by the user.
For computers not only used in the company network, it is often better to make the drive mapping not persistent by using
%SystemRoot%\System32\net.exe use /persistent:no
%SystemRoot%\System32\net.exe use Z: \\MyServer\MyShare
%SystemRoot%\System32\net.exe use /persistent:yes
Windows does not save in this case in Windows registry under key HKEY_CURRENT_USER\Network that \\MyServer\MyShare should be mapped to Z: and therefore the network drive mapping exists only for current user session. The network drive mapping is removed automatically once Windows is restarted or the user logs off.
I'm trying to build a batch file script, which will copy the outlook.pst file, from the user's My Documents folder and move it to the server, which I've mapped as a drive, "B:\"
This is the code I have so far:
#echo on
xcopy "c:\Documents and Settings\%username%\My Documents\outlook.pst" "B:\PST\%username%\" -c -d -i -y
exit
The script is designed for Windows XP.
However, when I run this code on the client machine, it doesn't copy the .pst file across, it just runs the command over and over again, until I Ctrl + C it...
Thanks
If I recall correctly, the default location for PST files is in %localappdata%\Microsoft\Outlook\. And if the user has PST files in multiple locations, it's possible that he has more than one with the same name, just in different folders. Good times.
If it's possible that your users might have PST files in locations other than My Documents, I recommend modifying your script with just a couple of very minor changes.
#echo off
setlocal enabledelayedexpansion
for /r "%userprofile%" %%I in (*.pst) do (
rem avoid overwriting in case "outlook.pst" exists in two locations, for instance
if exist "B:\PST\%username%\%%~nxI" (
set cnt=000
rem get count of files matching b:\pst\username\filename*.pst
for /f %%a in ('dir "B:\PST\%username%\%%~nI*%%~xI" 2^>NUL ^| find " File(s) "') do (
set "cnt=!cnt!%%a"
)
rem file of the same name will become filename001.pst, filename002.pst, etc.
set "dest=%%~nI!cnt:~-3!%%~xI"
rem otherwise leave the filename alone
) else set "dest=%%~nxI"
set /P "=Copying !dest!... "<NUL
copy "%%~fI" "B:\PST\%username%\!dest!"
echo Done.
)
I wished to copy outlook.pst from its Microsoft default location to a memory stick using a batch file in Windows XP
I found that xcopy failed to copy Outlook.pst to the memory stick or to My Documents
I now xcopy it in 2 steps, firstly to C:\ then to the Memory Stick
It has worked reliably