Giter Site home page Giter Site logo

dlwyatt / powershellloggingmodule Goto Github PK

View Code? Open in Web Editor NEW
65.0 12.0 18.0 120 KB

Automatically capture and save PowerShell console output from a script (without the limitations and headaches of Start-Transcript)

License: Apache License 2.0

C# 65.42% PowerShell 34.58%

powershellloggingmodule's Introduction

PowerShellLoggingModule

Uses Reflection to intercept text output headed for the PowerShell console. All lines of output are sent to any number of subscriber objects producing complete log files of script output (adding date/timestamps) without needing extra code by the script author.

The upside is that any text which would have shown up in the console is logged, and the downside is that only that text is logged. For example, verbose output is only logged if VerbosePreference is Continue...

Supports PowerShell 2, 3, 4, 5, 6 and 7

Install from the PowerShell Gallery

Install-Module PowerShellLogging

Compile your own copy

You can compile the assembly with:

dotnet build -c Release

To generate the full module, you can run the build script:

.\build -Version $(gitversion -showvariable nugetversion)

Note: this script builds into a version numbered folder in the module root. The expectation is that you have the source in a folder like ~\Projects\Modules\PowerShellLogging where the parent folder can be added to your PSModulePath for testing purposes, so the build will end up in, e.g.: ~\Projects\Modules\PowerShellLogging\1.4.0 and the build script will update the metadata to make it all versioned properly!

Testing

The test cases are very minimal (basically just covering the fact that it logs, and testing a couple of edge cases where it used to fail to log). Despite that, weand have some problems due to the way that WindowsPowerShell breaks when they fail.

As a result, to be sure that the tests are actually working (reporting the correct results), you should run each test case in a new session. There is a wrapper script test.ps1 which you can use to do that, it basically just runs each test case in PowerShell and pwsh to ensure everything is working in both WindowsPowerShell and PowerShell core. E.g.:

foreach ($testcase in Get-ChildItem Tests\*.Tests.ps1) {
    powershell -NoProfile -Command Invoke-Pester $testcase.FullName
}

Alternative Download

Note, the original version is also available from:

http://gallery.technet.microsoft.com/scriptcenter/Enhanced-Script-Logging-27615f85

powershellloggingmodule's People

Contributors

dlwyatt avatar rbernardino avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

powershellloggingmodule's Issues

PowerShell 7 - Enable-LogFile: Object reference not set to an instance of an object.

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

When using with PowerShell.Create PowerShellLogging throws on all Write Output

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:

  • Avoid breaking PowerShell when there's no host
  • Allow logging even when there's no a host

Calling script from CLI

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

Logging fails when using ThreadJobs

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.

Enable-OutputSubscriber script blocks have the potential for a stackoverflow exception

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?

Examples showing how to use it

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!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.