GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Make PowerShell able to enable logging of script block execution on Unix platforms by daxian-dbw · Pull Request #5791 · PowerShell/PowerShell Conversation
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There are a lot of changes in this PR. When reviewing this PR, I recommend you review each commit because I intentionally group logically related changes into separate commits. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
- Remove the unneeded base type; - Rename 'ConfigPropertyAccessor' to 'PowerShellConfig'; - Move 'PowerShellConfig' to the namespace 'System.Management.Automation.Configuration'
87ff37f to
a6c62bf
Compare
| // Current user policy takes precedence. | ||
| var groupPolicySettings = Utils.GetGroupPolicySetting(s_groupPolicyBase, s_consoleSessionConfigurationKey, Utils.RegCurrentUserThenLocalMachine); | ||
| if (groupPolicySettings != null) | ||
| var consoleSessionSetting = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
With this change, the Windows PowerShell GPO settings don't apply to PSCore6, correct? This seems correct to me, but is a breaking change. We should label this PR as such. cc Joey Aiello (@joeyaiello)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, GPO settings in Registry won't apply to PowerShell Core. I have added the breaking change label. Thanks for catching that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This does not seem correct to me. Indhu Sivaramakrishnan (@Indhukrishna) DSC has had feedback that seems to indicate that they expect GPO to apply.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I will start to work on enabling GPO as well on windows. The preference order of the settings should be config file --> GPO, meaning if a policy setting is defined in the config file, then use it; if it's not defined in the config file, query registry. This way, you can have control whether you want the GPO settings to take effect.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Common rule is that Computer GPO is high priority, then User GPO, then computer wide config, then user config. It is critical rule and security related.
Update.
Software\Policies\Microsoft\Windows\PowerShell - here Policies assume that it is high priority and should overlap other configs - users can not change its.
Software\Microsoft\Windows\PowerShell - it is a normal config corresponding to a text config file. This setting can be set manually by user or by using Group Policy Preferences (GPP). I think it should be low priority over a text config file (looks as changing defaults or set recommended defaults that the user can change by a config file).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
For the policy related settings, we are having a debate on which one should take preference. I will talk to Travis Plunk (@TravisEz13) later today about it.
For non-policy related settings, we shouldn't use registry settings anymore but only refer to the config file.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The conclusion is: on windows, we query group policies from registry first, and if the requested policy is not defined in GP, then we query from the configuration file.
New commit has been pushed to enable this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
For non-policy related settings, we shouldn't use registry settings anymore but only refer to the config file.
I don't agree - GPO is great Enterprise feature and Domain Admins should have full and flexible control on PowerShell. We could discuss this in a Issue (as I mention below too).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I mean "non-policy related settings", like the settings in "SOFTWARE\Microsoft\PowerShell" today. They are not group policies.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Still reviewing
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /// { | ||
| /// "DefaultSourcePath" : "path to local updatable help location" | ||
| /// } | ||
| /// Corresponding settings of the original Group Policies |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
If we're moving GPO support, we shouldn't mention "original Group Policies", just call it "PowerShell Policies"
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Since we now re-enabled the GPO support on Windows, I will leave this comment unchanged.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Correct
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| try | ||
| { | ||
| key = Registry.LocalMachine.OpenSubKey(Utils.GetRegistryConfigurationPrefix()); | ||
| key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds"); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
this path should be a const somewhere
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This code is in a #if !CORECLR ... #endif block. I leave the registry key path here only for reference, so that when we clean up this !CORECLR block, we know what the key is.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ok
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // file or internal, skip logging. | ||
| if (ScriptBlockLoggingExplicitlyDisabled() || | ||
| if (logSetting?.EnableScriptBlockLogging == false || | ||
| scriptBlock.ScriptBlockData.IsProductCode) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Why isn't the IsProductCode check in the outer if statement since it's never logged when set.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Theoretically, this can be re-written as
if ((force && logSetting?.EnableScriptBlockLogging != false) || logSetting?.EnableScriptBlockLogging == true) { if ((!scriptBlock.HasLogged || InternalTestHooks.ForceScriptBlockLogging) && !scriptBlock.ScriptBlockData.IsProductCode) { .... } }
Or even more aggressively, these two if blocks can be merged into one. But this doesn't look very readable, so I think I'm fine with the original code.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // If script block logging is explicitly disabled, or it's from a trusted | ||
| // file or internal, skip logging. | ||
| if (ScriptBlockLoggingExplicitlyDisabled() || | ||
| if (logSetting?.EnableScriptBlockLogging == false || |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This behavior change may be confusing without some documentation.
We've essentially now have 3 logging states, on, off, and warnings. When the setting is not defined, scripts that have suspicious content are logged.
I suggest a doc change to clarify this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
There is no behavior change, the check logSetting?.EnableScriptBlockLogging == false is to make sure that the EnableScriptBlockLogging is explicitly set to false in the config file. If you look at the original implementation of ScriptBlockLoggingExplicitlyDisabled(), it returns true only if the registry key EnableScriptBlockLogging exists and its value is explicitly 0.
I agree to have docs to clarify how logging works in PowerShell. Not sure if we already have some docs about it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Dongbo Wang (@daxian-dbw) Could you please add this in PR description for future docs?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, a documentation section is added to PR description.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| { | ||
| object enableModuleLoggingValue = null; | ||
| if (groupPolicySettings.TryGetValue("EnableModuleLogging", out enableModuleLoggingValue)) | ||
| if (moduleLogging.EnableModuleLogging == false) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Do we really need multiple return paths? Why not if (... == false) else if (... == true) and set status in both cases.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I didn't change the original code, will update it to set status in both cases.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| @@ -921,7 +921,7 @@ internal static TranscriptionOption GetSystemTranscriptOption(TranscriptionOptio | |||
| { | |||
| if (systemTranscript == null) | |||
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This lock is not used consistently with other usages. if the intent is to return the updated or original value, the lock should also encapsulate both the "if (transcription != null)" block and the implied else block.
As written, there is a possible race between this path and StopAllTranscribing
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I didn't change the original code. I guess you are right, this method could return a TranscriptionOption object or null depending on whether StopAllTranscribing set systemTranscript to null before return systemTranscript; in this method. But I'm not familiar enough with the transcribing code to know if that could be a problem.
Can you open an issue tracking this comment? We can look at the transcribing code more closely when addressing that issue.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| internal sealed class ScriptExecution : PolicyBase | ||
| { | ||
| public string ExecutionPolicy { get; set; } | ||
| public bool? EnableScripts { get; set; } |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand the value of having this nullable. EnableScripts == null is same as EnableScripts == true, correct? Same question for the nullable properties below where they should have a default value and being null is the same as the default value.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
EnableScripts == null means this setting is not defined in the config file, so it's up to powershell to define the default behavior. EnableScripts == true means it's defined in the config file and the value is true. Likewise, EnableScripts == false means it's defined in the config file and the value is false.
It's the same in registry -- a key is not defined, which means the application needs to use the pre-defined behavior; when the key is defined, the value will be either 1 or 0.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
An example is the use of EnableScriptBlockLogging in LogScriptBlockCreation(ScriptBlock scriptBlock, bool force)
force == trueforce == true.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Ok, the force case makes sense that there is a difference with null. Thanks.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I don't like the nullable too. I see no reason to emulate registry keys. If now we use static classes it is more readable and maintainable to set defaults explicitly. Force works with this too.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's mimicking registry keys, but a requirement to represent three states: enabled, disabled and undefined. Without bool?, if EnableScriptBlockLogging is not specified in the config file while EnableScriptBlockInvocationLogging is specified, then the deserialized ScriptBlockLogging object will have EnableScriptBlockLogging set to false (the default value), which will be interpreted as "script block logging" is explicitly disabled.
The EnableScriptBlockLogging example is from existing code, I didn't change the logic. If it turns out we don't need the bool? type in future, we can always change it since it's internal.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // execution scenario. Writes will attempt to create the directory | ||
| // if it does not already exist. | ||
| // | ||
| appDataConfigDirectory = Utils.GetUserConfigurationDirectory(); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
We can install PowerShell Core side-by-side with other PowerShell Core-s. So we should have configs for "default" system wide installation and for "local" for every user installation.
Also it seems we should have GPO option - "Force GPO for Side-By-Side PowerShell installations" - by default we should apply GPO only for system wide PowerShell installation.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Based on internal discussion today, the current plan is to have PSCore6 GPO settings separate from Windows PowerShell. For now, we don't plan to have side-by-side GPO settings per version of PSCore6 until there is customer need for it. New admx will be published later for the PSCore6 settings (which will be the same as Windows PowerShell, but reside in a different location in registry).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
GPO is Enterprise feature. GPO should allow Domain Admins get full control on PowerShell. I full trust MSFT experts but I'd prefer discuss GPO in a Issue. Also we forget about AppLocker.
I'd as Domain Admin prefer don't separate PowerShell Core GPO - it is better by default use Windows PowerShell setting until PowerShell Core GPOs is set explicitly otherwise users can ignore corporate policies.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Ilya (@iSazonov) since PSCore6 is not inbox in Windows and doesn't replace Windows PowerShell, we shouldn't use the same settings. PSCore6 in this case is no different from any 3rd party app.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /// Lock used to enable multiple concurrent readers and singular write locks within a | ||
| /// single process. | ||
| /// TODO: This solution only works for IO from a single process. A more robust solution is needed to enable ReaderWriterLockSlim behavior between processes. | ||
| /// Lock used to enable multiple concurrent readers and singular write locks within a single process. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
We have lock (s_cachedPolicies) in Utils.cs - maybe that's enough?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
There are other settings except for the policy related ones and they may query the config file simultaneously, so this lock is needed.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think we could find a way to use only one global lock - if we want to have consistency, it doesn't matter how and what settings change.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The querying for GP setting is a hot code path, especially for the script block logging, every script block execution will query for it. The lock s_cachedPolicies is to make sure that when multiple threads are querying for GP settings at the same time, only one thread will actually hit and read the configuration file.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
On windows, group policy settings from registry takes precedence over the configuration file. If a policy is not defined in GP, then we query from configuration file.
| @@ -921,7 +921,7 @@ internal static TranscriptionOption GetSystemTranscriptOption(TranscriptionOptio | |||
| { | |||
| if (systemTranscript == null) | |||
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /// <summary> | ||
| /// Get a specific kind of policy setting from the configuration file. | ||
| /// </summary> | ||
| internal static T GetPolicySettingFromConfigFile<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new() |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be private?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should. Will update.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /// <summary> | ||
| /// Get a specific kind of policy setting from the group policy registry key. | ||
| /// </summary> | ||
| internal static T GetPolicySettingFromGPO<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new() |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This should be private, right?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should. Will update.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| private string psHomeConfigDirectory; | ||
| private string appDataConfigDirectory; | ||
| private const string configFileName = "PowerShellProperties.json"; | ||
| private const string configFileName = "powershell.config.json"; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
about_Logging.md will need to be updated.
See https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/6/Microsoft.PowerShell.Core/About/about_Logging.md
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Opened MicrosoftDocs/PowerShell-Docs#2017 to track the documentation update.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Note that about_logging.md needs to be updated regardless since it refers to 'PowerShellProperties.json'.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| {nameof(UpdatableHelp), @"Software\Policies\Microsoft\PowerShellCore\UpdatableHelp"}, | ||
| {nameof(ConsoleSessionConfiguration), @"Software\Policies\Microsoft\PowerShellCore\ConsoleSessionConfiguration"} | ||
| }; | ||
| private readonly static ConcurrentDictionary<Tuple<ConfigScope, string>, PolicyBase> s_cachedPoliciesFromRegistry = |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Really, we should register for GP change notifications and clear the cache. Not a regression, so, can you add a comment or file an issue: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374404(v=vs.85).aspx
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Issue #5804 is opened to track this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Concern has been addressed.
|
Dan Travison (@dantraMSFT) Steve Lee (@SteveL-MSFT) Ilya (@iSazonov) Travis Plunk (@TravisEz13) I think all comments have been addressed (code updated, or question answered, or issue opened). Can you please take another look to see if the PR is ready to merge? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| /// <summary> | ||
| /// The GroupPolicy related settings used in PowerShell are as follows in Registry: | ||
| /// - Software\Policies\Microsoft\Windows\PowerShell -- { EnableScripts (0 or 1); ExecutionPolicy (string) } |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Needs to be updated as we're putting it under ...\Microsoft\PowerShellCore now
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Will do. Done.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| case nameof(Transcription): result = policies.Transcription; break; | ||
| case nameof(UpdatableHelp): result = policies.UpdatableHelp; break; | ||
| case nameof(ConsoleSessionConfiguration): result = policies.ConsoleSessionConfiguration; break; | ||
| default: Diagnostics.Assert(false, "Unreachable code"); break; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Perhaps have the same assert message as line 656 below?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Done.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
We should add GPO tests at some point.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks all for the reviews! |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Travis Plunk (@TravisEz13) can you open an issue to track the GPO tests? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…werShell Core (PowerShell#5791) Make PowerShell Core reads group policy settings from different registry keys (Windows only) and the configuration files (both Windows and Unix). - On Windows, move to different GPO registry keys. - On both Windows and Unix, read GPO related settings from the configuration file `powershell.config.json`. - On Windows, the policy settings in registry take precedence over the configuration file. - Enable policy controlled logging and transcription on Unix.
…werShell Core (#5791) Make PowerShell Core reads group policy settings from different registry keys (Windows only) and the configuration files (both Windows and Unix). - On Windows, move to different GPO registry keys. - On both Windows and Unix, read GPO related settings from the configuration file `powershell.config.json`. - On Windows, the policy settings in registry take precedence over the configuration file. - Enable policy controlled logging and transcription on Unix.
…werShell Core (PowerShell#5791) Make PowerShell Core reads group policy settings from different registry keys (Windows only) and the configuration files (both Windows and Unix). - On Windows, move to different GPO registry keys. - On both Windows and Unix, read GPO related settings from the configuration file `powershell.config.json`. - On Windows, the policy settings in registry take precedence over the configuration file. - Enable policy controlled logging and transcription on Unix.
…werShell Core (PowerShell#5791) Make PowerShell Core reads group policy settings from different registry keys (Windows only) and the configuration files (both Windows and Unix). - On Windows, move to different GPO registry keys. - On both Windows and Unix, read GPO related settings from the configuration file `powershell.config.json`. - On Windows, the policy settings in registry take precedence over the configuration file. - Enable policy controlled logging and transcription on Unix.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
Logging of script block execution cannot be enabled on Unix
There was an error while loading. Please reload this page.