Robocopy failed to run in VB script


Author
Message
Anthony Tan
Anthony Tan
New Member
New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)New Member (14 reputation)
Group: Forum Members
Posts: 6, Visits: 16
Need help to check if there is a bug in Macrium Reflect VB Script Generation.

After much troubleshooting on issue with Robocopy, I realize that VB script refuse to run "robocopy" command. Instead it use "xcopy" to do Directory Synchronization.

I run a test by generating a VB Script and Powershell Script from a Backup Definition File. Then I ran the VB script first. I monitor through the "Resource Monitor" and saw that "xcopy" command was executed after the backup. After this I ran the Powershell Script. With Powershell Script, the "robocopy" command executed as expected.

For your information, I am running Macrium Reflect Server Edition (v.6.1.871) on Windows Server 2012 Standard. I am not familiar with script and I have attach the VB and Powershell script for analysis.

I wonder why VB script prefer to run "xcopy" command instead of "robocopy" command?


-----------------------VB Script------------------------

'******************************************************************************
'*
'*
'* Module Name:  Test Backup.vbs
'*
'* Abstract:   This is a template VB Script file generated by Reflect v6
'*      Modify to add your own functionality if required
'*
'*
'******************************************************************************

OPTION EXPLICIT

' call the main function
Call VBMain()


'******************************************************************************
'* Sub:  VBMain
'*
'* Purpose: This is main function to start execution
'*
'* Input: None
'*
'* Output: None
'*
'******************************************************************************
Sub VBMain()
Dim objShell
Dim ExitCode

' Elevate this script for Admin privileges in Vista
Elevate

Set objShell = WScript.CreateObject("WScript.Shell")

' Do the backup
ExitCode = Backup ("""C:\Program Files\Macrium\Reflect\Reflect.exe"" -e -w <BACKUP_TYPE> ""C:\Users\Administrator\Documents\Reflect\Test Backup.xml""")

' Copy the file(s) just created
SynchroniseDirectories ExitCode, "I:"

' done
Set objShell = nothing
wscript.quit(ExitCode)
End Sub


'******************************************************************************
'* Function: Backup
'*
'* Purpose: Calls Reflect.exe passing an XML BDF as a parameter
'*
'* Input:  strCmdLine Command Line Arguments
'* Output: Exit Code
'*
'******************************************************************************
Function Backup(Byref strCmdLine)
Dim objShell
Dim objExecObject
Dim iReturnCode

strCmdLine = Replace(strCmdLine, "<BACKUP_TYPE>", GetBackupTypeParameter)

' Run the backup or image
Set objShell = WScript.CreateObject("WScript.Shell")
iReturnCode = objShell.Run(strCmdLine, 1, true)

if iReturnCode = 2 then
' Handle XML validation error

elseif iReturnCode = 1 then
' Handle backup error
elseif iReturnCode = 0 then
' Everything OK
end if
Backup = iReturnCode
Set objShell = nothing
End Function


'******************************************************************************
'* Sub:  Elevate
'*
'* Purpose: Elevates this script for Vista UAC.
'*    This means that only one UAC Elevation prompt is displayed and
'*    functions/programs will not fail if they require admin privileges
'*
'* Input: None
'* Output: None
'*
'******************************************************************************
Sub Elevate
Dim ShellApp
Dim objShell
Dim objWshProcessEnv

' Don't elevate if run from Windows Task Scheduler
If WScript.Arguments.Count > 0 Then
If WScript.Arguments.Item(0) = "-s" then
Exit Sub
End If
End If

Set objShell = WScript.CreateObject("WScript.Shell")
Set objWshProcessEnv = objShell.Environment("PROCESS")

If objWshProcessEnv("ELEVATED_APP") <> "True" Then
objWshProcessEnv("ELEVATED_APP") = "True"
Set ShellApp = CreateObject("Shell.Application")
Call ShellApp.ShellExecute("""" & WScript.FullName & """", """" & WScript.ScriptFullName & """" & " " & GetBackupTypeParameter, , "runas")
set ShellApp = nothing
Set objWshProcessEnv = nothing
wscript.quit
End If
Set objWshProcessEnv = nothing
Set objShell = nothing
End Sub


'******************************************************************************
'* Function: RobocopyExists
'*
'* Purpose: determines whether the program Robocopy can be called from the
'*    command line.
'*
'* Input:  None
'* Output: boolean - true if Robocopy exists
'*
'******************************************************************************
Function RobocopyExists()
On Error Resume Next
Dim objShell
Dim objExec
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExec = objShell.Exec ("robocopy.exe", 0)

If Err.Number = 0 Then
RobocopyExists = True
Else
RobocopyExists = False
End If
End Function


'******************************************************************************
'* Function: SynchroniseDirectories
'*
'* Purpose: Copies all files created by the previous backup / image
'*    to a supplied directory. Uses Macrium environment variables to
'*    determine which files to copy.
'*
'* Input:  ExitCode - The exit code of the last backup
'*    strBackupDirectory - Directory to copy to
'*
'******************************************************************************
Function SynchroniseDirectories(Byval ExitCode, Byval strSyncDirectory)
On Error Resume Next
Dim objShell
Dim objWshProcessEnv
Dim strEnvPrefix
Dim strBackupDirectory
Dim strCmdLine
Dim iReturnCode
  Dim fs
Dim objSyncFiles
Dim objBackupDirectory
Dim objSyncDirectory
Dim objBackupFile
Dim objSyncFile
Dim strExtension
Dim dateBackupFile
Dim dateSyncFile

' Only copy files if backup was successful
if ExitCode <> 0 Then
  Exit Function
End If

Set objShell   = WScript.CreateObject("WScript.Shell")
Set objWshProcessEnv = objShell.Environment("VOLATILE")

' Get the prefix for the last backup set
strEnvPrefix = objWshProcessEnv("MACRIUM_PREFIX")

' Get the directory where we just created a backup
strBackupDirectory = objWshProcessEnv(strEnvPrefix + "_DIRECTORY")

If right(strBackupDirectory, 1) = "\" Then strBackupDirectory = left(strBackupDirectory, len(strBackupDirectory)-1)
If right(strSyncDirectory, 1) = "\" Then strSyncDirectory = left(strSyncDirectory, len(strSyncDirectory)-1)

If RobocopyExists Then
  strCmdLine = "robocopy ""<SOURCE>"" ""<DESTINATION>"" *.mr* /copyBigGrinAT /lev:0 /purge /r:0"
Else
' Robocopy does not exist - using xcopy
Set fs = CreateObject("Scripting.FilesystemObject")
Set objBackupDirectory = fs.GetFolder(strBackupDirectory)
Set objSyncDirectory = fs.GetFolder(strSyncDirectory)

For Each objSyncFile in objSyncDirectory.Files
strExtension = fs.GetExtensionName(objSyncFile)
dateSyncFile = objSyncFile.DateLastModified
If Left(strExtension,2) = "mr" Then
' Check if file has been deleted
If Not(fs.FileExists(strBackupDirectory+"\"+objSyncFile.name)) Then
fs.DeleteFile(objSyncFile)
Else
' Check if file has been modified
Set objBackupFile = fs.GetFile(strBackupDirectory+"\"+objSyncFile.name)
dateBackupFile = objBackupFile.DateLastModified
If DateDiff("m", dateBackupFile, dateSyncFile) <> 0 Then
fs.DeleteFile(objSyncFile)
End If
End If
End If
Next

strCmdLine = "xcopy ""<SOURCE>\*.mr*"" ""<DESTINATION>"" /c /d /h /i /v /y"
End If

strCmdLine = Replace(strCmdLine,"<SOURCE>", strBackupDirectory)
strCmdLine = Replace(strCmdLine,"<DESTINATION>", strSyncDirectory)
iReturnCode = objShell.Run(strCmdLine,0,true)

if iReturnCode <> 0 then
' Handle synchronisation error
else
' Everything OK
end if

' Clean up
Set objShell   = nothing
Set objWshProcessEnv = nothing
End Function

'******************************************************************************
'* Function: GetBackupTypeParameter
'*
'* Purpose: determines the backup type from command line parameter
'*    -full Full backup
'*    -inc Incremental backup
'*    -diff Differential backup
'*
'* Input:  None
'* Output: the parameter
'*
'******************************************************************************
Function GetBackupTypeParameter
Dim i

for i = 0 to Wscript.Arguments.Count - 1
  If Wscript.Arguments(i) = "-full" OR _
   Wscript.Arguments(i) = "-inc" OR _
   Wscript.Arguments(i) = "-diff" Then
   GetBackupTypeParameter = Wscript.Arguments(i)
   Exit Function
  End If
Next

GetBackupTypeParameter = ""

End Function




------------------------------------------------ Powershell Script-------------------------------------------------------

#******************************************************************************
#*
#* Module Name: Test Backup.ps1
#*
#* Abstract:  This is a template PowerShell Script file generated by Reflect.
#*     Modify to add your own functionality if required.
#*
#* Returns:  0 - Success.
#*     1 - Error: Invalid XML.
#*     2 - Error: Backup failed.
#*     3 - Error: Not elevated (script will try to execute elevated).
#*
#******************************************************************************
Param([switch]$s, [switch]$full, [switch]$inc, [switch]$diff)

$strReflectPath = "C:\Program Files\Macrium\Reflect\Reflect.exe";
$strXmlFilePath = "C:\Users\Administrator\Documents\Reflect\Test Backup.xml";
$strScriptPath = $MyInvocation.MyCommand.Definition;

#******************************************************************************
#* Func: OnXmlValidationError
#*
#* Desc: Called when a backup fails due to an XML validation error.
#*   This is here to be modified for your own uses.
#*
#******************************************************************************
function OnXmlValidationError()
{
Write-Warning " ! XML invalid ($strXmlFilePath).";
# Handle invalid XML error...

}

#******************************************************************************
#* Func: OnBackupError
#*
#* Desc: Called when a backup fails.
#*   This is here to be modified for your own uses.
#*
#******************************************************************************
function OnBackupError()
{
Write-Warning " ! Backup failed ($strXmlFilePath).";
# Handle backup error...

}

#******************************************************************************
#* Func: OnBackupSuccess
#*
#* Desc: Called when a backup succeeds.
#*   This is here to be modified for your own uses.
#*
#******************************************************************************
function OnBackupSuccess()
{
Write-Host " * Backup succeeded ($strXmlFilePath).";
# Handle backup success...

}

#******************************************************************************
#* Func: Main
#*
#* Desc: This is main function to start execution.
#*
#******************************************************************************
function Main()
{
Write-Host 'PowerShell script for Macrium Reflect Backup Definition File';
Write-Host "BDF: $strXmlFilePath";
Elevate;

$iExitCode = Backup;

if ($iExitCode -eq 0) # if backup completed successfully...
{
  $strBackupDir = GetLastBackupPath;
  if (![string]::IsNullOrEmpty($strBackupDir))
  {
  SynchroniseDirectories $strBackupDir 'I:';
  }
}

Write-Host "Script finished with exit code $iExitCode.";
Exit $iExitCode;
}

#******************************************************************************
#* Func: GetLastBackupPath
#*
#* Desc: Gets the path of the last backup made by Reflect.
#*
#******************************************************************************
function GetLastBackupPath()
{
Write-Host ' * Getting path of last backup... ' -NoNewLine;
$strResult = '';
try
{
  $strRegPath = 'HKCU:\Volatile Environment';
  $strName = 'MACRIUM_PREFIX';
  $strPrefix = (Get-ItemProperty -Path $strRegPath -Name $strName -ErrorAction Stop).$strName;
  $strName = $($strPrefix + '_DIRECTORY');
  $strResult = (Get-ItemProperty -Path $strRegPath -Name $strName -ErrorAction Stop).$strName;
} catch { };
Write-Host 'Done.';
return $strResult;
}

#******************************************************************************
#* Func: Elevate
#*
#* Desc: Elevates this script for UAC.
#*   This means that only one UAC Elevation prompt is displayed and
#*   functions/programs will not fail if they require admin privileges.
#*
#******************************************************************************
function Elevate()
{
# Only elevate if not ran from the task scheduler.
Write-Host ' * Checking elevated access rights... ' -NoNewLine;
if (-Not $s)
{
  # Check to see if we are currently running "as Administrator"
  if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator"))
  {
  $ElevatedProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
  # Specify the current script path and name as a parameter
  $strType = GetBackupTypeParameter;
  $ElevatedProcess.Arguments = "-ExecutionPolicy Bypass & '" + $script:MyInvocation.MyCommand.Path + "' $strType";
  # Indicate that the process should be elevated
  $ElevatedProcess.Verb = "runas";
  # Start the new process
  [System.Diagnostics.Process]::Start($ElevatedProcess);
  # Exit this unelevated script with exit code for "Error: Not elevated"
  Exit 3;
  }
}
Write-Host 'Done.';
}

#******************************************************************************
#* Func: Backup
#*
#* Desc: Calls Reflect.exe passing an XML BDF as a parameter.
#*
#******************************************************************************
function Backup()
{
Write-Host ' * Running the backup... ' -NoNewLine;
$strType = GetBackupTypeParameter;
$strArgs = "-e -w $strType `"$strXmlFilePath`"";
$iResult = (Start-Process -FilePath $strReflectPath -ArgumentList $strArgs -PassThru -Wait).ExitCode;
Write-Host 'Done.';
switch ($iResult)
{
  2 { OnXmlValidationError; break; }
  1 { OnBackupError;   break; }
  0 { OnBackupSuccess;  break; }
}
return $iResult;
}

#******************************************************************************
#* Func: SynchroniseDirectories
#*
#* Desc: Copies all Macrium Reflect files to a supplied directory.
#*
#******************************************************************************
function SynchroniseDirectories($strSrcDir, $strDstDir)
{
Write-Host ' * Synchronising directories... ' -NoNewLine;
if (Get-Command robocopy -ErrorAction SilentlyContinue)
{
  # robocopy is available...
  # /copyBigGrinAT - DBigGrinata
  #     A:Attributes
  #     T:Time stamps
  # /purge  - deletes destination files and directories that no longer
  #     exist in the source
  # /lev:0  - Does not copy subdirectories
  &robocopy $strSrcDir $strDstDir *.mr* /copyBigGrinAT /lev:0 /purge /r:0 | Out-Null
}
else
{
  # Fall back to xcopy...
 
  # Delete files from the target directory not present in the source directory
  $strDstDirChildren = $strDstDir+"\*";
  Get-ChildItem $strDstDirChildren -include "*.mr*" | Foreach-Object {
  $strMaybeDeletedSrcFile = $strSrcDir + '\' + $_.Name;
  if (-not (Test-Path $strMaybeDeletedSrcFile))
  {
   Remove-Item $_
  }
  else
  {
   $SrcFileTime = [datetime](Get-ItemProperty -Path $strMaybeDeletedSrcFile -Name LastWriteTime).lastwritetime;
   $DstFileTime = [datetime](Get-ItemProperty -Path $_.FullName     -Name LastWriteTime).lastwritetime;

   $SrcFileTimeString = $SrcFileTime.ToString("yyyMMddHHmmss")
   $DstFileTimeString = $DstFileTime.ToString("yyyMMddHHmmss")

   if ($SrcFileTimeString -ne $DstFileTimeString)
   {
    Remove-Item $_
   }
  }
  }

  # /c - Continues copying even if errors occur.
  # /d - Date check; only copies if file does not exist or is older.
  # /h - Copies hidden and system files.
  # /i - If the destination does not exist, and you are copying more than one
  #   file, this switch assumes that the destination is a folder.
  # /v - Verifies each new file.
  # /y - Overwrites existing files without prompting.
  &xcopy $strSrcDir\*.mr* $strDstDir /c /d /h /i /v /y | Out-Null
}
Write-Host 'Done.';
}

#******************************************************************************
#* Func: GetBackupTypeParameter
#*
#* Desc: Determines the backup type from command line parameter...
#*   "-full": Full backup
#*   "-inc" : Incremental backup
#*   "-diff": Differential backup
#*
#******************************************************************************
function GetBackupTypeParameter()
{
if ($full -eq $true) { return '-full'; };
if ($inc -eq $true) { return '-inc'; };
if ($diff -eq $true) { return '-diff'; };
return ''; # Clone
}

# Execute the Main function
Main;

Edited 17 October 2015 6:06 AM by Anthony Tan
GlennChambers
GlennChambers
Junior Member
Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)Junior Member (55 reputation)
Group: Forum Members
Posts: 12, Visits: 100
It seems that robocopy is not being found when you invoke it through VBScript which is strange but maybe you can just remove the IF statement and see what happens if you add the full path to robocopy.

  strCmdLine = "C:\Windows\SysWOW64\robocopy.exe ""<SOURCE>"" ""<DESTINATION>"" *.mr* /copy:DAT /lev:0 /purge /r:0"



GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search