Prof. Powershell
PowerShell Command History Lesson Part 3: Group Policies
Here's how to use a Group Policy setting to automate logging for commands in PowerShell 3.
- By Jeffery Hicks
- 04/15/2014
In the last lesson we looked at enabling logging for commands in a PowerShell module. This requires PowerShell 3.0 and later and must be enabled for whatever module you wish, every time. That's a lot of potential work. Fortunately, there is a Group Policy setting you could define.
In your group policy, navigate to Policies – Administrative Templates – Windows Components – Windows PowerShell. There are settings under both the Computer and User nodes. I'm going to make my change under the computer so it should apply to all users of a given computer. Within the setting you should see a policy for "Turn on Module Logging." Figure 1 shows the un-configured setting.
As you can see, this will require Windows 7 or Windows Server 2008 (and later) and I'm almost certain it will also require PowerShell 3.0 because that is when module logging was introduced.
Enable it and click the Show button. In the entry form enter the name of every module you wish to log. You can include wildcards. Figure 2 shows my settings.
Click OK and apply the GPO. Now, as I use commands within any of these modules, activity should be logged in the Windows PowerShell event log. As with any information in an event log, if the log is cleared, either manually or by the system, you will lose the events.
On a system with the policy applied, I can see which ones have logging enabled.
PS C:\> get-module | where {$_.logpipelineExecutionDetails}
Be aware, that an administrator can still disable logging even when set by Group Policy. Although an advantage is that this should apply to commands run in any host.
But after running some commands I can get some idea about what was run using my code from last time.
[regex]$cmd="CommandLine=.*"
[regex]$user="UserId=.*\\.*"
[regex]$script="ScriptName=.*"
Get-Eventlog "Windows PowerShell" -InstanceId 800 |
Select MachineName,TimeGenerated,
@{Name="UserID";Expression={ $user.Matches($_.Message).Value.Split("=")[1].Trim()}},
@{Name="Command";Expression={ $cmd.Matches($_.Message).Value.Split("=")[1].Trim()}},
@{Name="Script";Expression={ $script.Matches($_.Message).Value.Split("=")[1].Trim()}} |
Out-Gridview -title "CIM Command Log"
This is still far from perfect, at least when it comes to pulling data from the event log, but as Figure 3 shows, it is better than nothing.
As with any logging, you want to be careful here about not logging more than you need or make sure your log files are configured to maintain an adequate history.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.