This started out as a short entry for my Powershell Snippets page, but it quickly turned out that this cmdlet needs a longer text for explaining proper handling…
Background
The cmdlet Write-Information is interesting, but also a bit tricky.
It’s for using the ‘Information Stream’, which was added by Powershell 5.0 (released around 2016), and is the sixth stream, added to prevent further stream pollution:
- Output/Success
- Error
- Warning
- Verbose
- Debug
- Information
More on the topic:
- June Blender, Microsoft Scripting DevBlog
- Steve König, Active Directory FAQ (German!)
- Jeff Hicks, Petri.com
Pitfall #1: InformationAction is set to SilentlyContinue by default
By default, one will see/get nothing from it in the shell; sometimes, this may be the right thing (for example if one is just collecting data for a logfile), but often, it is not:
> Write-Information -MessageData "Text"
>
You then need to either change the global preference variable $InformationPreference
from
“SilentlyContinue” to “Continue”, or instruct the particular call of the cmdlet by setting its parameter
-InformationAction
to “Continue”:
> Write-Information -MessageData "Text" -InformationAction Continue
Text
Pitfall #2: Inquire doesn’t tell you what you should confirm
A nice feature is -InformationAction Inquire
, which shows a confirmation inquiry to the user:
> Write-Information -MessageData "Text" -InformationAction Inquire
Confirm
Continue with this operation?
[Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is "Y"):
But as you may have noticed: The MessageData (“Text”) doesn’t appear anywhere!
When using -InformationAction Inquire
, you only get the confirmation inquiry;
the actual -MessageData
will not be shown (unlike when using -InformationAction Continue
).
This seems to be a bug (opened 2019-12, still unresolved 2022-07), that one needs to work around for now (e.g. by explicitly printing text before the inquiry).
After those stumbling blocks, let’s finish this section with a few nice features…
MessageData
The value of parameter MessageData doesn’t have to be a text string; it can be any kind ob object:
> Write-Information -MessageData (gci) -InformationAction Continue -InformationVariable iv
System.Object[]
> $iv
System.Object[]
> $iv | select -expand MessageData
Directory: C:\Test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2021-01-01 11:00 Folder 1
d----- 2022-02-02 12:00 Folder 2
d----- 2023-03-03 13:00 Folder 3
Collecting InformationRecords in an InformationVariable
One can also collect so-called “information records” in a variable:
Notes:
- Just the name, no dollar sign-prefix ($) when delivering it as a parameter argument!
- Does not need to be defined before!
> Write-Information -MessageData "Text" -Tags "Foo", "Bar" -InformationAction Continue -InformationVariable iv
Text
> $iv | gm
TypeName: System.Management.Automation.InformationRecord
# ...
> $iv
Text
But there’s more to it:
> $iv | select *
MessageData : Text
Source : Write-Information
TimeGenerated : 2023-07-16 00:00:00
Tags : {Foo, Bar}
User : COMPUTER\Sascha
Computer : Computer
ProcessId : 4321
NativeThreadId : 1234
ManagedThreadId : 10
If you want to collect multiple records, which you can then later filter for its tags, for example, try this:
Invoke a script or function with the common parameter -InformationVariable
, like before
(Common parameters
are available to any Powershell cmdlet and your own advanced(!) scripts or functions).
The InformationVariable will automatically and implicitly be handed down; one doesn’t even have to mention the parameter in the call of Write-Information:
function Test-Me
{
[CmdletBinding()] Param() # This makes it an 'advanced function'.
0..3 | % { write-information -MessageData "Text $_" -Tag "FixedTag", "Tag $_" -InformationAction Continue }
}
Test-Me -InformationVariable iv
Now you can further examine the variable $iv in detail:
> $iv | ? { $_.Tags -eq 'FixedTag'} | select MessageData, Tags
MessageData Tags
----------- ----
Text 0 {FixedTag, Tag 0}
Text 1 {FixedTag, Tag 1}
Text 2 {FixedTag, Tag 2}
Text 3 {FixedTag, Tag 3}
or
> $iv | ? { $_.Tags -eq 'Tag 0'} | select MessageData, Tags
MessageData Tags
----------- ----
Text 0 {FixedTag, Tag 0}
Film & Television (54)
How To (63)
Journal (17)
Miscellaneous (4)
News & Announcements (21)
On Software (12)
Projects (26)