How to catch PowerShell backup script output to a file?


Author
Message
RefDM
RefDM
Junior Member
Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)
Group: Forum Members
Posts: 70, Visits: 191
I have generated a PowerShell script file from an XML backup definition file and scheduled the script. What I would like to do next is to catch the PowerShell script output and redirect it e.g. to a file so that I can use another program to read that file in real-time and monitor the backup progress.

(I am aware of the standard Macrium user interface which provides you with about the same the information in a window, but we'd like to see the information in a bit different format and in somewhat discreet way. I'm currently running a pilot project on migrating over to Macrium from another disk imaging solution, and we'd like the user experience to be as similar as to what our users have been used to, and to what they appreciate).

I wonder if anyone has succeeded in catching Macrium's PowerShell backup script output and redirecting it to a file in a disk directory? At first I thought it'd be as simple as redirecting a MS-DOS BAT script file's output - but I found myself to be wrong...

jphughan
jphughan
Most Valuable Professional
Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)
Group: Forum Members
Posts: 3.4K, Visits: 25K
(EDIT: Having gotten a chance to test all of this, turns out neither of the methods below works. I'm not sure why Reflect's output can't be captured through these conventional methods that work on other applications. I'm guessing it's either because the output is explicitly designated as just console output that can't be redirected to a file, rather than text output that can be, or else perhaps that Reflect.exe calls another application to actually do the work. Surprisingly, even using Start-Transcript didn't capture the output, even though Microsoft says it captures all output that appears in the console. Anyhow, I'm stuck at this point, but I'll update this post if I figure this out.)

If you just want everything you see when you run the script manually, the easiest way to send that to a file is to execute the script with syntax like this:

C:\scripts\Reflect.ps1 > C:\Logs\ReflectLog.txt

Using >> rather than just > as above will cause PowerShell to append to the output file rather than overwriting it, but either way you'd have to edit the scheduled task manually to achieve that syntax.

Alternatively, if you want to generate uniquely named log files for each job run (and/or avoid a manual scheduled task), you could leave the task alone and edit the script instead. I haven't tested this, but it should work.  Find this line in the script:

$iResult = (Start-Process -FilePath $strReflectPath -ArgumentList $strArgs -PassThru -Wait).ExitCode;

and replace it with all of this:

$Date = Get-Date
$XMLFileName = (($strXmlFilePath -split '\\')[-1]).trim('.xml')
$LogFilePath = "C:\Logs\ReflectLog_$($XMLFileName)_$($Date.ToString('yyyy-MM-dd_HHmm')).txt"
$RunBackup = Start-Process -FilePath $strReflectPath -ArgumentList $strArgs -PassThru -Wait -RedirectStandardOutput $LogFilePath
$iResult = $RunBackup.ExitCode;

Note that the above design will only send the output of the call to Reflect to the log file, whereas the first option sends the output of the entire script to the log file.

Edited 2 February 2018 4:29 PM by jphughan
RefDM
RefDM
Junior Member
Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)
Group: Forum Members
Posts: 70, Visits: 191
Yeah, I experienced exactly the same problems as you - that's why I wrote "I found myself to be wrong"... Smile

I hope that a solution or at least a working workaround can be found for this one. I'll try do some testing myself, too. Please do post an update if you happen to find the way to do it!

RayG
RayG
Advanced Member
Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)
Group: Forum Members
Posts: 241, Visits: 1.1K
You mean like this - see attached


Regards
RayG
Windows10 X64 V1803 B17134.228 MR v7.1.3317

Attachments
jphughan
jphughan
Most Valuable Professional
Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)
Group: Forum Members
Posts: 3.4K, Visits: 25K
Now Ray you know you can’t just post an attachment like that in a thread like this without explaining how you achieved it. Out with it man! Smile
Edited 6 February 2018 2:52 PM by jphughan
RayG
RayG
Advanced Member
Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)Advanced Member (497 reputation)
Group: Forum Members
Posts: 241, Visits: 1.1K
jphughan - 6 February 2018 2:51 PM
Now Ray you know you can’t just post an attachment like that in a thread like this without explaining how you achieved it. Out with it man! Smile

It is a function I included when I made this script back in V6 days see this post:
My Backup Script
The script posted at the bottom of the page above is not the latest as there was no takeup I decided it was not worth keeping the info up to date. I can post the whole script if required but this code may help it does call other functions and they do the formatting of the line(s) but this is the basis of getting the HTML Info:
Function Get-MacriumLogFileInfo
{
[CmdletBinding(PositionalBinding = $False)]
Param (
  [Parameter(Mandatory=$True,HelpMessage = 'Enter the Macrium log file name')]
  [String]$FileName
)
If ($Script:log2)
{Write-MyLog -Message ('Function:[{0}] Line:[{1}] Called from:[{2}] Line:[{3}]' -f (Get-PSCallStack).FunctionName[0], (Get-PSCallStack).ScriptLineNumber[0].tostring('#0').padleft($Script:LinePad), (Get-PSCallStack).FunctionName[1], (Get-PSCallStack).ScriptLineNumber[1].tostring('#0').padleft($Script:LinePad))}
If ($Script:Log1)
{
  Write-MyLog -Message ("Log File Name: [$FileName]")
  If (-Not (Test-Path -Path $FileName))
  {Write-MyLog -Message 'Log File Not Found'}
}
$Msg = @()
$Msg1 = @()
If (-Not (Test-Path -Path $FileName))
{Write-MyLog -Message (Get-MyLine -InitialLF "$($Script:StrCRLF)" -ParamTrail ' : ' -Parameter 'Macrium Log File Not Found' -Text "$FileName")}
Else
{
  $Error.clear()
  $ErrorActionPreference = 'Stop'
  Try
  {
  $HTML = New-Object -ComObject 'HTMLFile'
  try
  {
   # This works in PowerShell 4
   $HTML.IHTMLDocument2_write((Get-Content -Raw -Path "$FileName"))
   Write-MyLog -Message 'html.IHTMLDocument2_write Ran as V4'
  }
  catch
  {
   # This works in PowerShell 5
   $HTML.write((Get-Content -Raw -Path "$FileName"))
   Write-MyLog -Message 'html.write Ran as V5'
  }
  $MyHTMLText = $HTML.body.InnerText.split("$Script:StrLF").Replace("$($Script:StrTab)",' ')
  $MaxLength = [int]0
  $Pad = [int]0
  $PadLen = [int]6
  $PadParam = [int]28
  $BlankLine = $True
  foreach ($Item in ($MyHTMLText -split "$($Script:StrLF)"))
  {
   if ([int]$Item.length -gt [int]$MaxLength)
   {$MaxLength = $Item.Length}
  }
  $MaxLength = $MaxLength+$PadParam-($PadLen*2)
  $DivideLine = ''.padright(60) -replace ' ', '_'
  $Msg1 += "$($Script:StrCRLF)$DivideLine"
  foreach ($Item in ($MyHTMLText -split "$($Script:StrLF)"))
  {
   if ($Item.length -eq [int]1 -and -Not $BlankLine)
   {
    #Write-host -Object $DivideLine
    $Pad = [int]0
    $BlankLine = $True
    $Msg1 += Get-MyLine -ParamLen $Pad -InitialLF "$($Script:StrCRLF)" -Text $DivideLine
   }
   elseif ($Item.length -gt [int]1)
   {
    $BlankLine = $False
    if ($Item.IndexOf(':') -gt [int]0 -and $Item.IndexOf(':') -ne [int]1)
    {
    if ($Item -Match 'New File: [\d]+([ ]KB|[ ]MB|[ ]GB|[ ]TB|[ ]PB)')
    {
     $File = (Split-Path -Path $FileName -leaf).split('.')[0]
     $Item = $Item -replace "$File", " $File"
    }
    $Text = ($Item.Substring($Item.IndexOf(':')+1,$Item.Length-$Item.indexof(':')-1).Trimstart(' ').TrimEnd(' '))
    $Param = $Item.Substring(0,$Item.IndexOf(':')).TrimStart(' ').TrimEnd(' ')
    $Msg1 += Get-MyLine -IndentLen $Pad -ParamTrail ': ' -ParamLen $PadParam -InitialLF "$($Script:StrCRLF)" -Parameter $Param -Text "$Text"
    }
    elseif ($Item.IndexOf(':') -eq [int]1)
    {$Msg1 += Get-MyLine -ParamTrail ': ' -ParamLen $PadParam -InitialLF "$($Script:StrCRLF)" -Parameter '' -Text "$Item"}
    else
    {$Msg1 += Get-MyLine -ParamLen $Pad -InitialLF "$($Script:StrCRLF)" -Text $Item.TrimStart(' ')}
    $Pad = $PadLen
   }
  }
  $Msg1[-1] = $Msg1[-1].split('-')[0]
  }
  Catch
  {
  $x = Get-MyErrors -Return -NotFormatted
  $Pad = [int]27
  $Msg += Get-MyLine -ParamLen $Pad -InitialLF "$($Script:StrCRLF)$($Script:StrCRLF)" -ParamTrail ' : ' -Parameter 'Cannot Process HTML File' -Text "[$FileName]"
  $Msg += Get-MyLine -ParamLen $Pad -InitialLF "$($Script:StrCRLF)" -ParamTrail ' : ' -Parameter '' -Text "[$($x[0]), $($x[3]), $($x[4])]"
  if ($Log)
  {Write-MyLog -Message "$Msg"}
  }
  Finally
  {
  $ErrorActionPreference = 'Continue'
  $Msg1
  }
}
}



Regards
RayG
Windows10 X64 V1803 B17134.228 MR v7.1.3317

jphughan
jphughan
Most Valuable Professional
Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)
Group: Forum Members
Posts: 3.4K, Visits: 25K
Ok, so you're parsing the log file after it's been generated.  The OP wants a way to capture the activity log as it's being sent to the console while the job is running so that he can send those updates immediately to some other file that can then be used to monitor job progress in real-time, presumably through some other tool.  I personally don't know how useful that would be since the console doesn't seem to update with periodic "percent complete" messages, so you might just get a message that it's backing up some partition or folder, but of course everyone's use case is different, and I agree with the central point that it shouldn't be this difficult to capture that console output to begin with.  And just as a point of technical curiosity, I'd love to know HOW Reflect's console output seems to elude the conventional mechanisms of achieving this, such as adding "> File.txt" to the script command, piping the Reflect command within the script to Out-File, or even running Start-Transcript.

Edited 6 February 2018 5:40 PM by jphughan
RefDM
RefDM
Junior Member
Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)Junior Member (89 reputation)
Group: Forum Members
Posts: 70, Visits: 191
Thank you for your replies, RayG and jphughan!

Yes, I want to capture the activity log in real-time, INCLUDING THE "PERCENT COMPLETE" messages. They are an essential part of the information I want to be able to capture in real-time.

I did a quick test on one of my test backup definitions by creating an MS-DOS BAT file, and indeed it seems to still update the "percentage complete" messages in real-time:

The "overall progress" indicator counts nicely all the way up to 98% during the backup. If the progress indicator were not displayed, I would not have even tried capturing the output. It is pity that there seems to be no way to capture information MR produces in clear ASCII format into a command prompt console - and it is the first time I have seen anything like this.

I really wonder if this has been intentional, or if someone in the development has only made some unconventional design decision with such a side-effect...

In the former case I'd like to understand the reasoning behind such decision.
In the latter case I'd be grateful if the activity log text stream could be freed in a future MR release from the captivity it is now kept in.


jphughan
jphughan
Most Valuable Professional
Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)Most Valuable Professional (4.9K reputation)
Group: Forum Members
Posts: 3.4K, Visits: 25K
A Wish List thread was also created for this, but for anyone who finds this thread later, this functionality was provided in 7.1.2899 and a KB article about it is now available here.

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