Unable to capture screen output of a cmdlet in a text file

How can I get the screen output of a cmdlet into a text file? I have tried multiple options for what I thought would be simple redirection and am stumped. I think this may be a newbie problem, but I could really use some feedback to point me in the right direction.

Here is an example of my script and commented out are the redirection methods I’ve tried with the vendor provided cmdlet “Backup-PortalStore” that is not logging the screen output.


runs a full Click Commerce backup

#VARIABLES
$hostname = “granttest-cf”
$storename = “granttest”
$cifsshare = “\anthill\click”
$maxbackup = 3
$logdest = “$cifsshare$hostname\logs”
$storedest = “$cifsshare$hostname\backups”

#Test to capture output command line output from backup-portalstore
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus | Tee-Object -FilePath $logdest"$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log"
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus | out-file -FilePath $logdest"
$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log"
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus 3>&1 2>&1 > $logdest"$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log"
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus 2>&1 > $logdest"
$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log"
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus *> $logdest"_$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))granttest-cf-backup.log"

#PAYLOAD
Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus


I’ve also tried start-transcript and stop-transcript, wrapping up the commands into a function and still the only output captured into the log file in all of these attempts is:

Server : GRANTTEST-CF
Store : granttest
IsEnabled : True
PortalVersion :
FrameworkVersion :
MigrationVersion :
Status :
VirtualRoot :

What I want to capture in my log file is what I see when I run my script or cmdlet in a PS window which is:

Backup store ‘granttest’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.28.14.17’
Backing up store database ‘granttest9’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.28.14.17_incomplete\Database.bak’ with compression and copyOnly=False
10% completed
20% completed
30% completed
40% completed
50% completed
60% completed
70% completed
80% completed
90% completed
100% completed
Skip corpus backup on user request.
Backing up WebrCommon files.
Zipping path ‘C:\ClickPortal\DataServer\InetPub\Common\granttest’
ArchiveWebrCommon completed successfully
Backing up Webr runtime files.
Backing up Website files.
Backing up store configuration.
Writing backup details.
Saving backup details to store configuration
Enforcing maximum number of backups to keep 3
Found 3 old backups, Deleting 1 backup(s)
Deleting old backup \anthill\click\granttest-cf\backups\granttest-2020.10.28.13.55
Backup of store completed successfully

 

 

Hello Laura,

You are correct in that, to redirect the pipeline output (or the error output) to a file, you’d need to make use of the redirection operators .

For instance, to redirect the output of the Get-Date Cmdlet into a text file, you’d use “>” operator:

PS D:\temp\Powershell> Get-Date > current-date.txt
PS D:\temp\Powershell> Get-Content .\current-date.txt

29 October 2020 17:56:27

 

What do you see in the test.txt file if you were to attempt the following?

Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus > c:\temp\test.txt

I suspect that Backup-PortalStore (or a cmdlet it depends on) is using Write-Host which is a bad practice. Write-Host just writes to the console so you can’t do anything with the output, like pipe it to another command or redirect it to a file.

I think what you’ll have to do is call your script and redirect the output of that, but then you won’t see it on the screen:

powershell.exe myScript.ps1 > e:\Temp\log.txt

When I run the script and redirect on the ps cmdline, I get the same result.

PS C:\options\scripts> .\backup-test-v2.ps1 > .\test.txt
Backup store ‘granttest’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.29.11.57’
Backing up store database ‘granttest9’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.29.11.57_incomplete\Database.bak’ with compression and copyOnly=False
10% completed
20% completed
30% completed
40% completed
50% completed
60% completed
70% completed
80% completed
90% completed
100% completed
Skip corpus backup on user request.
Backing up WebrCommon files.
Zipping path ‘C:\ClickPortal\DataServer\InetPub\Common\granttest’
ArchiveWebrCommon completed successfully
Backing up Webr runtime files.
Backing up Website files.
Backing up store configuration.
Writing backup details.
Saving backup details to store configuration
Enforcing maximum number of backups to keep 3
Found 3 old backups, Deleting 1 backup(s)
Deleting old backup \anthill\click\granttest-cf\backups\granttest-2020.10.28.14.09
Backup of store completed successfully

PS C:\options\scripts> Get-Content .\test.txt

Server : GRANTTEST-CF
Store : granttest
IsEnabled : True
PortalVersion :
FrameworkVersion :
MigrationVersion :
Status :
VirtualRoot :

You may also want to have a look at Start-Transcript. In theory, anything going to StdOut also goes to the log file you define. Here is a what I use to create the log file in %TEMP% for the user running the script.

$startTime = Get-Date
$logFileName =“MyLogFile-$($ENV:ComputerName)-$($startTime.Month)-$($startTime.Day)-$($startTime.Year).LOG”
$tempFolder = $ENV:Temp
$logFile = Join-Path $tempFolder $logFileName

Start-Transcript -Path $logFile -Append

do a bunch of stuff …

Stop-Transcript

I did a quick test and Write-Host is captured.

Assuming you are using PS version 5 or greater you should be able to redirect Write-Host output using stream 6 since it is a wrapper for write-information. See note here: Write-Host (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs

To redirect other streams just add the stream to your > operator i.e. .\script.ps1 6> script.log or .\script.ps1 *> script.log for all streams. See this doc for more info: about Redirection - PowerShell | Microsoft Docs

I am using PS 5.1

6> would be included in *>. I attempted to use the following redirects with the same output below.

#Test to capture output command line output from backup-portalstore
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus | Tee-Object -FilePath $logdest\”_$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log”

#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus | out-file -FilePath $logdest\”_$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log”

#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus 3>&1 2>&1 > $logdest\”_$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log”

#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus 2>&1 > $logdest\”$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log”
#Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus *> $logdest\”
$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))granttest-cf-backup.log”

 

 

I’ve also tried start-transcript and stop-transcript, wrapping up the commands into a function and still the only output captured into the log file in all of these attempts is:

Server : GRANTTEST-CF
Store : granttest
IsEnabled : True
PortalVersion :
FrameworkVersion :
MigrationVersion :
Status :
VirtualRoot :

Would you be able to share the source code for your Backup-PortalStore cmdlet?

If not all, maybe the part that would be responsible for generating the outputs like:

“Backup store (…)”
“Backing up store database (…) with compression and copyOnly=(…)”
“(…) completed”

I’m struggling to duplicate this issue. Can you verify a couple of things? In your previous post it looks like you commented out the lines with #, so did the actually run? Can you try send the script output stream to a file instead of individual commands like this?

C:\options\scripts> .\backup-test-v2.ps1 *> .\test.txt

 

Can you please run it as
powershell.exe .\backup-test-v2.ps1 > .\test.txt

I think you need to call PowerShell again as a new session is required to capture the output. That should at least prove if the cmdlet is using Write-Host or perhaps even Out-Default.

Thank you everyone for your feedback and thank you Matt. Running within PS as administrator and calling a new session, I am (thank you) getting the desired output to the text file. This confirms the cmdlet is using write-host?

I’ve updated the “payload” of my script to be:
<p style=“padding-left: 40px;”>powershell.exe Backup-PortalStore -Store $storename -Destination $storedest -NoCopyOnly -MaxFiles $maxbackup -NoCorpus *> $logdest"_$((Get-Date).ToString(‘yyyy.MM.dd_HH.mm.ss’))$hostname-backup.log"</p>
 

<hr />

Test Results


<p style=“padding-left: 40px;”>PS COMMAND: PS C:\options\scripts> powershell.exe .\backup-test-v2.ps1 > .\test.txt</p>
<p style=“padding-left: 40px;”>Here’s what’s in test.txt</p>
<p style=“padding-left: 80px;”>Backup store ‘granttest’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.29.15.35’
Backing up store database ‘granttest9’ to ‘\anthill\click\granttest-cf\backups\granttest-2020.10.29.15.35_incomplete\Database.bak’ with compression and copyOnly=False
10% completed
20% completed
30% completed
40% completed
50% completed
60% completed
70% completed
80% completed
90% completed
100% completed
Skip corpus backup on user request.
Backing up WebrCommon files.
Zipping path ‘C:\ClickPortal\DataServer\InetPub\Common\granttest’
ArchiveWebrCommon completed successfully
Backing up Webr runtime files.
Backing up Website files.
Backing up store configuration.
Writing backup details.
Saving backup details to store configuration
Enforcing maximum number of backups to keep 3
Found 3 old backups, Deleting 1 backup(s)
Deleting old backup \anthill\click\granttest-cf\backups\granttest-2020.10.28.14.17
Backup of store completed successfully</p>
<p style=“padding-left: 80px;”>
Server : GRANTTEST-CF
Store : granttest
IsEnabled : True
PortalVersion :
FrameworkVersion :
MigrationVersion :
Status :
VirtualRoot :</p>

Awesome! Thank you both. For your feedback Laura, and for your solution Matt.

I just tested it, this time I could reproduce. I was then able to see that Matt’s solution is working great.

See below. The first Get-Content .\output.txt shows there is nothing in the output text file. The second time, the console output is redirected into the text file as we are creating a new session, as per Matt’s solution.

PS D:\Temp\Powershell> @’
>> Write-Host “Hello World!”
>> '@ > myscript.ps1
PS D:\Temp\Powershell> Get-Content .\myscript.ps1
Write-Host “Hello World!”
PS D:\Temp\Powershell> .\myscript.ps1
Hello World!
PS D:\Temp\Powershell> .\myscript.ps1 > output.txt
Hello World!
PS D:\Temp\Powershell> Get-Content .\output.txt
PS D:\Temp\Powershell> powershell.exe .\myscript.ps1 > output.txt
PS D:\Temp\Powershell> Get-Content .\output.txt
Hello World!

So yes, it does feel like Write-Host is being used in your custom Backup-PortalStore cmdlet.
I learned something new today (i.e. you can redirect - kind of - the output of Write-Host by creating a new session) :slight_smile:

Glad that worked for you. I certainly think that points to the script using Write-Host.

I’d be inclined to log a ticket with the vendor about it. They may just give a response to say that you’re not supposed to script with their cmdlets, just use them, but even so there are well documented, better ways to provide output.