Why doesn't -whatif parameter get passed to pipeline - powershell

Utilizing the common parameter -Whatif within a Powershell script e.g.:
Remove-Item -Path "$now\$basename" -Recurse -Whatif -Force |
Write-Entry -Line $(get-linenumber) -level 'Info' |
Create-Log -title "$title.log" -display
The log file is blank even though I can clearly see the text onscreen. I would like to pass the -Whatif string to a text file. I know this has something to do with redirection but that's as far as I have gotten.

The output of the -Whatif processing bypasses the standard streams for output and goes to the console directly. This TechNet question about accessing the -WhatIf output from C# explains.

Related

Is it possible to "-passthru" to Log file only and not the console when using "Start-Transcript -Path "$LogOutput"

I have a Powershell script where I want the console to output my custom messages only, but I would like to capture what the command is doing in a log only. Is this possible?
Just to make it clearer with an example below. I want to copy all the Sub Directories and Files as they are in their own directory to a new location:
Start-Transcript -Path "$LogOutput" -IncludeInvocationHeader -Append
Get-ChildItem -Path "$Source" | Copy-Item -Destination "$Destination" -Exclude "File*.xml" -Force -Recurse -PassThru
Stop-Transcript
I then use $? to get the success of the result on the console for my custom messages.
The above shows details I find helpful but it outputs the -PassThru on the console which I do not want to display there. If I don't specify it, it outputs nothing in the Transcript log either.
If I try appending to the copy command ...-PassThru | Out-File -FilePath "$LogOutput" -Append (The same Log used for Transcript) it fails as the log file is locked by the Transcript. Is there a way to make this possible, or will I have to append ...-PassThru | Out-File -FilePath "$LogOutput" -Append to all my commands individually?
Many thanks in advance.

Getting PowerShell to post all information to out file

PowerShell is writing information to file when I delete a registry entry successfully however I also need it to post errors to the file instead of the PS session.
Remove-Item -Path $path -Force -Verbose 4>&1 | Out-File "c:\registryresults.txt"
How would I be best able to achieve this?
4>&1 is the 'Verbose' stream being redirected to the 'output' stream.
you probably want to use *>&1 or just *> "c:\registryresults.txt" on its own without the Out-File

Log what is deleted

I'm very new to this but I have a problem with deleting 30days old files which I found an answer to here: Powershell - Delete subfolder(s) in folder with specific name(s) older than 30 days
But I would like to make a follow question on that.
The code I use is this:
gci P:\ -directory -recurse | ?{$_.FullName -match ".:\\.+?\\.+?\\.+?\\.+?\\.+?\\" -and $_.CreationTime -lt (get-date).AddDays(-30)}|Remove-Item -recurse -whatif
Is it possible to log what is deleted as well? Would be awesome if the size of the files are included in the log file. Thanks!
Make the remove operation verbose and redirect the verbose stream to a file:
... | Remove-Item -Recurse -Verbose 4> 'C:\path\to\your.log'
Note that this requires at least PowerShell v3.
If you only want to log what would be deleted without actually deleting it, use -WhatIf instead of -Verbose:
... | Remove-Item -Recurse -WhatIf
You can also combine the two:
$dryrun = $true # set to $false to actually delete
... | Remove-Item -Recurse -Verbose -WhatIf:$dryrun 4> 'C:\path\to\your.log'
However, -WhatIf output goes to the host console, so it can't be redirected to a file. You could use Start-Transcript as a workaround, but that would record everything, not just the would-be deletes. Or you could run the entire code/script (without redirections) in a new PowerShell process:
powershell.exe -File 'C:\path\to\your.ps1' > 'C:\path\to\your.log'
The host output of a child PowerShell process is merged into its STDOUT, so you can redirect it "from the outside".

powershell append to output

I'm 'teaching myself to powershell' and have come a cropper already, and google/this site hasn't enabled me to find a solution. I'm compiling a text file with filelists from different directories, but i'm having trouble appemnding new data to the file.
get-childitem $dir -recurse | % {write-output $_.fullname} >$file
creates my file, but then i want to APPEND new records from the below
get-childitem $dir2 -recurse | % {write-output $_.fullname} >$file
I've tried both add-content and -append, but I cant figure out what I'm not doing to get it right.
Try:
get-childitem $dir -recurse | % {write-output $_.fullname} >> $file
(Tested and works)
The double >> makes it append always, a single > overwrites each time.
Or change your syntax to use Out-File
get-childitem $dir -recurse | % {write-output $_.fullname} | out-file -filepath $file -Append
(untested)
In this case the variable $file must hold the full path. Like: C:\directory\filename.txt
You can use Out-File to write to a file, adding the append parameter will append to the file.
Get-ChildItem $dir -recurse | Select-object -ExpandProperty Fullname | Out-File -FilePath $file
Get-ChildItem $dir2 -recurse | Select-object -ExpandProperty Fullname | Out-File -FilePath $file -Append
Short Answer
The pipeline used here can be eliminated, and usage of Out-File would make life easy:
Out-File (Get-ChildItem $dir -Recurse).FullName -FilePath $File
To append would be to simply use the -Append flag:
Out-File (Get-ChildItem $dir2 -Recurse).FullName -FilePath $File -Append
Note: This only works in PowerShell v3 and up, as PowerShell v2 relied on the pipeline to expand properties of objects within an array. In that case, the best route is to use something more like #david-martin proposed on this same thread.
Long Answer, and Best Practices
In a different thread, Script to Append The File, they were having similar difficulties with appending files. Though, they were also using the pipeline in a way that was unnecessary (more so than you have used in your example).
Their pipeline usage looked like this:
$PathArray | % {$_} | Out-File "C:\SearchString\Output.txt"
Now, again, Out-File has an -Append parameter. Simply modifying their code to have it tagged on at the end took care of things.
Though, their ForEach-Object statement (the % symbol) is pretty useless in the pipeline and isn't needed (very close in similarity to how yours is used). This is because you are only using the ForEach-Object loop to output the object without any modification. This is exactly what the pipeline does by default, which is pass each object along to the next command.
For more information on the pipeline: About Pipelines
If Update-Help has been run locally, one can use Get-Help to locally run Get-Help about_pipelines to see information too.
Instead of this:
$PathArray | % {$_} | Out-File "C:\SearchString\Output.txt" -Append
We could do this:
$PathArray | Out-File "C:\SearchString\Output.txt" -Append
[Recommended] That example can also eliminate the need for the pipeline all together, as using a pipeline is less efficient if it can be done without it. Doing everything one can possibly do without the pipeline, or to the left of each pipe in the pipeline, is to "filter left" (see the following article for more about why one should filter left, format right: Filtering Command Output in PowerShell):
Out-File -InputObject $PathArray -FilePath "C:\SearchString\Output.txt" -Append
Note: In the case above, -Append is only needed if the file already exists and is being extended.
Remember: Get-Help, and Read The Friendly Manual (RTFM)
The easiest way to troubleshoot is to checkout help documentation. Use Get-Help to checkup whatever you need: parameter sets, available parameters, examples, etc. Make sure to run Update-Help in order to have detailed documentation available locally. To checkout everything:
Update-Help
Get-Help Out-File -Full
For more detailed information that is good to know about data stream/output redirection:
PowerShell redirection operators, such as > and >> (but also redirection of data streams with n> and n>&1), and the available streams per PowerShell version: About Redirection in PowerShell (or: Get-Help about_redirection in PowerShell)
Tee-Object cmdlet), a cmdlet that acts as a more robust version of Out-File (or: Get-Help tee-object in powerShell)

Powershell Move-Item logging

I would like some assistance getting a powershell script to work correctly. A piece of it is pasted below. Basically what I'm trying to do is to move all files in various subdirectories to another location. I can get the files to move and the folders to create fine, I'm just having a problem with getting the results to a text file. I've tried using out-file, but the txt file is empty. I've also tried start-transcript, but notepad doesn't seem to see line breaks and all the text bleeds together. Is there a better way to go about this? I'm using this basic command for testing.
Start-Transcript c:\log.txt
Move-Item c:\temp\*.* C:\Temp\2014 -Verbose -Force
Stop-Transcript
You may just need to collapse the output file descriptors. According to the about_Redirection page, it should work if you do the following:
Move-Item c:\temp\*.* C:\Temp\2014 -Verbose -Force *>&1 |
Out-File -FilePath $MyLogPath
Or if you want to see the output at the same time
Move-Item c:\temp\*.* C:\Temp\2014 -Verbose -Force *>&1 |
Tee-File -FilePath $MyLogPath