dlwyatt / powershellloggingmodule Goto Github PK
View Code? Open in Web Editor NEWAutomatically capture and save PowerShell console output from a script (without the limitations and headaches of Start-Transcript)
License: Apache License 2.0
Automatically capture and save PowerShell console output from a script (without the limitations and headaches of Start-Transcript)
License: Apache License 2.0
We're using this module in some of our modules, and now someone's tried to call our module from C# with a PowerShell.Create (no host).
We expected the logs would still show up, but instead PowerShellLogging throws on any output.
A quick review of source shows that (almost) all the output methods are deliberately throwing when the host is null (as it is, presumably, in the case where we're using PowerShell.Create).
Proposal: (I will implement, if you're OK with this). I think that simply changing the methods to use the null check just to skip calling the host (rather than throwing) would:
Dear All
When trying to use the module in PowerShell 7 I get the following error.
C:\> import-module PowerShellLogging
C:\> Enable-LogFile -Path "c:\temp\test.txt"
ErrorCallback Path Streams DateTimeFormat
------------- ---- ------- --------------
C:\temp\test.txt All r
Enable-LogFile: Object reference not set to an instance of an object.
Thank you very much.
Marc
$PSVersionTable
Name Value
---- -----
PSVersion 7.0.0
PSEdition Core
GitCommitId 7.0.0
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
get-module -Name PowerShellLogging
ModuleType Version PreRelease Name ExportedCom
---------- ------- ---------- ---- -----------
Script 1.3.0 PowerShellLogging {Disable-Lo
I'm using the logging module in a script and it works fine when ran from the IDE. Not when called from CLI. powershell -file "path". I'm sure it's something simple but I havent been able to find it with google.
Thanks,
Levi
The commands all use a static HostIOInterceptor.Instance
When AttachToHost
is called on that static instance (from any command) the current InternalHost
shim (the one that's active in the current runspace) gets attached. It's only detached when the module is unloaded -- so there can only ever be one logged runspace per process.
In a parallel runspace scenario (like ThreadJob or PoshRSJob) each runspace has it's own
InternalHost` shim (even though none of them have an actual host).
With many InternalHosts, and only one Interceptor, only the first one to Attach actually gets logged, and the rest silently fail to log with no errors! The Attach simply returns and only the first runspace in a process logs properly -- unless the module is unloaded from that runspace before the registration of listeners in the second runspace.
To fix this we'd have to cache the attached hosts somehow (probably by creating a HostIOInterceptor
per host).
We could try using a caching Factory pattern to have a static HostIOInterceptor HostIOInterceptor.GetInterceptor(PSHost Host)
which would keep a collection of active interceptors and return the right one for the given host.
So for instance, Enable-LogFile
could call:
HostIOInterceptor.GetInstance(Host).AddSubscriber();
Instead of:
HostIOInterceptor.Instance.AttachToHost(Host);
HostIOInterceptor.Instance.AddSubscriber(logFile);
I believe this would require a change to the LogFile
as well (in order to be able to pause logging when it's writing exceptions). It would need to either store a reference to the HostIOInterceptor which it was created for, or a pointer to the Paused
property, or a callback/event for pausing and unpausing.
When inside one of the script blocks, something will be written to the console, then this is also captured. Initially it sounds reasonable but there is a danger here.
$onWriteDebugBlock={
param(
[string]$Message
)
Write-Host "[OnWriteDebug] $Message"
}
$onWriteVerboseBlock={
param(
[string]$Message
)
Write-Host "[OnWriteVerbose] $Message"
}
$onWriteErrorBlock={
param(
[string]$Message
)
Write-Host "[OnWriteError] $Message"
}
$onWriteWarningBlock={
param(
[string]$Message
)
Write-Host "[OnWriteWarning] $Message"
}
$onWriteOutputBlock={
param(
[string]$Message
)
Write-Host "[OnWriteOutput] $Message"
}
$splat=@{
OnWriteDebug=$onWriteDebugBlock
OnWriteVerbose=$onWriteVerboseBlock
OnWriteError=$onWriteErrorBlock
OnWriteOutput=$onWriteOutputBlock
OnWriteWarning=$onWriteWarningBlock
}
$outputSubscriber=Enable-OutputSubscriber @splat
Write-Error "An error message"
The Write-Error "An error message"
will be captured by onWriteErrorBlock
and written to the host as [OnWriteError] An error message
which in turn will be captured by onWriteOutputBlock
and written to the host as [OnWriteError] [OnWriteError] An error message
. This flow is recursive.
The danger here is not only with the error or output but also with debug. Imagine using in the OnWriteDebug
block a cmdlet that outputs debug messages.
The module is very cool but have you considered this flow?
Adding some examples to the ReadMe showing how to use it (not just install it) and what that looks like would be helpful. I (and I imagine others) don't even bother trying out modules/packages when there's no docs showing how to use it. Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.