Make sure that SettingFile arg is parsed before we load the settings (#7449)
Make sure that SettingFile arg is parsed before we load the settings - Add ability to parse some setting before console host is created - Trigger the Parse before the console host is created - disable snapin loading from loading setting before this point - re-enable mac logging tests. Also, fix the following Travis-ci issues: - make sure the Linux and macOS caches are separate to reduce the size - update the macOS image to the closest image as used by the official build system (equivalent to VSTS hosted mac builds)
This commit is contained in:
parent
0c11582e6c
commit
1523c218a6
|
@ -8,8 +8,10 @@ matrix:
|
|||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
env: TRAVIS_CI_CACHE_NAME=linux
|
||||
- os: osx
|
||||
osx_image: xcode8.1
|
||||
osx_image: xcode9.4
|
||||
env: TRAVIS_CI_CACHE_NAME=macOS
|
||||
fast_finish: true
|
||||
|
||||
addons:
|
||||
|
|
|
@ -200,6 +200,7 @@ namespace Microsoft.PowerShell
|
|||
_helpText = helpText;
|
||||
}
|
||||
|
||||
#region Internal properties
|
||||
internal bool AbortStartup
|
||||
{
|
||||
get
|
||||
|
@ -393,6 +394,205 @@ namespace Microsoft.PowerShell
|
|||
get { return _workingDirectory; }
|
||||
}
|
||||
|
||||
#endregion Internal properties
|
||||
|
||||
#region static methods
|
||||
/// <summary>
|
||||
/// Processes the -SettingFile Argument.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// The command line parameters to be processed.
|
||||
/// </param>
|
||||
/// <param name="settingFileArgIndex">
|
||||
/// The index in args to the argument following '-SettingFile'.
|
||||
/// </param>
|
||||
/// <param name="parser">
|
||||
/// Used to allow the helper to write errors to the console. If not supplied, no errors will be written.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Returns true if the argument was parsed successfully and false if not.
|
||||
/// </returns>
|
||||
private static bool TryParseSettingFileHelper(string[] args, int settingFileArgIndex, CommandLineParameterParser parser)
|
||||
{
|
||||
if (settingFileArgIndex >= args.Length)
|
||||
{
|
||||
if (parser != null)
|
||||
{
|
||||
parser.WriteCommandLineError(
|
||||
CommandLineParameterParserStrings.MissingSettingsFileArgument);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string configFile = null;
|
||||
try
|
||||
{
|
||||
configFile = NormalizeFilePath(args[settingFileArgIndex]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (parser != null)
|
||||
{
|
||||
string error = string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.InvalidSettingsFileArgument, args[settingFileArgIndex], ex.Message);
|
||||
parser.WriteCommandLineError(error);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(configFile))
|
||||
{
|
||||
if (parser != null)
|
||||
{
|
||||
string error = string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.SettingsFileNotExists, configFile);
|
||||
parser.WriteCommandLineError(error);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
PowerShellConfig.Instance.SetSystemConfigFilePath(configFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the command line parameters to ConsoleHost which must be parsed before the Host is created.
|
||||
/// Success to indicate that the program should continue running.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// The command line parameters to be processed.
|
||||
/// </param>
|
||||
internal static void EarlyParse(string[] args)
|
||||
{
|
||||
// indicates that we've called this method on this instance, and that when it's done, the state variables
|
||||
// will reflect the parse.
|
||||
|
||||
EarlyParseHelper(args);
|
||||
}
|
||||
|
||||
private static string GetConfigurationNameFromGroupPolicy()
|
||||
{
|
||||
// Current user policy takes precedence.
|
||||
var consoleSessionSetting = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
|
||||
|
||||
return (consoleSessionSetting?.EnableConsoleSessionConfiguration == true && !string.IsNullOrEmpty(consoleSessionSetting?.ConsoleSessionConfigurationName)) ?
|
||||
consoleSessionSetting.ConsoleSessionConfigurationName : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the command line parameters to ConsoleHost which must be parsed before the Host is created.
|
||||
/// Success to indicate that the program should continue running.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// The command line parameters to be processed.
|
||||
/// </param>
|
||||
private static void EarlyParseHelper(string[] args)
|
||||
{
|
||||
if(args == null)
|
||||
{
|
||||
Dbg.Assert(args != null, "Argument 'args' to EarlyParseHelper should never be null");
|
||||
return;
|
||||
}
|
||||
|
||||
bool noexitSeen = false;
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
(string SwitchKey, bool ShouldBreak) switchKeyResults = GetSwitchKey(args, ref i, parser: null, ref noexitSeen);
|
||||
if (switchKeyResults.ShouldBreak)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
string switchKey = switchKeyResults.SwitchKey;
|
||||
|
||||
if (MatchSwitch(switchKey, match: "settingsfile", smallestUnambiguousMatch: "settings"))
|
||||
{
|
||||
// parse setting file arg and don't write error as there is no host yet.
|
||||
if (!TryParseSettingFileHelper(args, ++i, parser: null))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the word in a switch from the current argument or parses a file.
|
||||
/// For example -foo, /foo, or --foo would return 'foo'.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// The command line parameters to be processed.
|
||||
/// </param>
|
||||
/// <param name="argIndex">
|
||||
/// The index in args to the argument to process.
|
||||
/// </param>
|
||||
/// <param name="parser">
|
||||
/// Used to parse files in the args. If not supplied, Files will not be parsed.
|
||||
/// </param>
|
||||
/// <param name="noexitSeen">
|
||||
/// Used during parsing files.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Returns a Tuple:
|
||||
/// The first value is a String called SwitchKey with the word in a switch from the current argument or null.
|
||||
/// The second value is a bool called ShouldBreak, indicating if the parsing look should break.
|
||||
/// </returns>
|
||||
private static (string SwitchKey, bool ShouldBreak) GetSwitchKey(string[] args, ref int argIndex, CommandLineParameterParser parser, ref bool noexitSeen)
|
||||
{
|
||||
string switchKey = args[argIndex].Trim().ToLowerInvariant();
|
||||
if (string.IsNullOrEmpty(switchKey))
|
||||
{
|
||||
return (SwitchKey: null, ShouldBreak: false);
|
||||
}
|
||||
|
||||
if (!SpecialCharacters.IsDash(switchKey[0]) && switchKey[0] != '/')
|
||||
{
|
||||
// then its a file
|
||||
if (parser != null)
|
||||
{
|
||||
--argIndex;
|
||||
parser.ParseFile(args, ref argIndex, noexitSeen);
|
||||
}
|
||||
|
||||
return (SwitchKey: null, ShouldBreak: true);
|
||||
}
|
||||
|
||||
// chop off the first character so that we're agnostic wrt specifying / or -
|
||||
// in front of the switch name.
|
||||
switchKey = switchKey.Substring(1);
|
||||
|
||||
// chop off the second dash so we're agnostic wrt specifying - or --
|
||||
if (!string.IsNullOrEmpty(switchKey) && SpecialCharacters.IsDash(switchKey[0]))
|
||||
{
|
||||
switchKey = switchKey.Substring(1);
|
||||
}
|
||||
|
||||
return (SwitchKey: switchKey, ShouldBreak: false);
|
||||
}
|
||||
|
||||
private static string NormalizeFilePath(string path)
|
||||
{
|
||||
// Normalize slashes
|
||||
path = path.Replace(StringLiterals.AlternatePathSeparator,
|
||||
StringLiterals.DefaultPathSeparator);
|
||||
|
||||
return Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
private static bool MatchSwitch(string switchKey, string match, string smallestUnambiguousMatch)
|
||||
{
|
||||
Dbg.Assert(switchKey != null, "need a value");
|
||||
Dbg.Assert(!String.IsNullOrEmpty(match), "need a value");
|
||||
Dbg.Assert(match.Trim().ToLowerInvariant() == match, "match should be normalized to lowercase w/ no outside whitespace");
|
||||
Dbg.Assert(smallestUnambiguousMatch.Trim().ToLowerInvariant() == smallestUnambiguousMatch, "match should be normalized to lowercase w/ no outside whitespace");
|
||||
Dbg.Assert(match.Contains(smallestUnambiguousMatch), "sUM should be a substring of match");
|
||||
|
||||
return (match.Trim().ToLowerInvariant().IndexOf(switchKey, StringComparison.Ordinal) == 0 &&
|
||||
switchKey.Length >= smallestUnambiguousMatch.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ShowHelp()
|
||||
{
|
||||
Dbg.Assert(_helpText != null, "_helpText should not be null");
|
||||
|
@ -463,24 +663,6 @@ namespace Microsoft.PowerShell
|
|||
}
|
||||
}
|
||||
|
||||
private static string GetConfigurationNameFromGroupPolicy()
|
||||
{
|
||||
// Current user policy takes precedence.
|
||||
var consoleSessionSetting = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
|
||||
if (consoleSessionSetting != null)
|
||||
{
|
||||
if (consoleSessionSetting.EnableConsoleSessionConfiguration == true)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(consoleSessionSetting.ConsoleSessionConfigurationName))
|
||||
{
|
||||
return consoleSessionSetting.ConsoleSessionConfigurationName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private void ParseHelper(string[] args)
|
||||
{
|
||||
Dbg.Assert(args != null, "Argument 'args' to ParseHelper should never be null");
|
||||
|
@ -488,32 +670,13 @@ namespace Microsoft.PowerShell
|
|||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
// Invariant culture used because command-line parameters are not localized.
|
||||
|
||||
string switchKey = args[i].Trim().ToLowerInvariant();
|
||||
if (String.IsNullOrEmpty(switchKey))
|
||||
(string SwitchKey, bool ShouldBreak) switchKeyResults = GetSwitchKey(args, ref i, this, ref noexitSeen);
|
||||
if (switchKeyResults.ShouldBreak)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SpecialCharacters.IsDash(switchKey[0]) && switchKey[0] != '/')
|
||||
{
|
||||
// then its a file
|
||||
|
||||
--i;
|
||||
ParseFile(args, ref i, noexitSeen);
|
||||
break;
|
||||
}
|
||||
|
||||
// chop off the first character so that we're agnostic wrt specifying / or -
|
||||
// in front of the switch name.
|
||||
switchKey = switchKey.Substring(1);
|
||||
|
||||
// chop off the second dash so we're agnostic wrt specifying - or --
|
||||
if (!String.IsNullOrEmpty(switchKey) && SpecialCharacters.IsDash(switchKey[0]))
|
||||
{
|
||||
switchKey = switchKey.Substring(1);
|
||||
}
|
||||
string switchKey = switchKeyResults.SwitchKey;
|
||||
|
||||
// If version is in the commandline, don't continue to look at any other parameters
|
||||
if (MatchSwitch(switchKey, "version", "v"))
|
||||
|
@ -711,34 +874,13 @@ namespace Microsoft.PowerShell
|
|||
}
|
||||
}
|
||||
|
||||
else if (MatchSwitch(switchKey, "settingsfile", "settings") )
|
||||
else if (MatchSwitch(switchKey, "settingsfile", "settings"))
|
||||
{
|
||||
++i;
|
||||
if (i >= args.Length)
|
||||
// Parse setting file arg and write error
|
||||
if (!TryParseSettingFileHelper(args, ++i, this))
|
||||
{
|
||||
WriteCommandLineError(
|
||||
CommandLineParameterParserStrings.MissingSettingsFileArgument);
|
||||
break;
|
||||
}
|
||||
string configFile = null;
|
||||
try
|
||||
{
|
||||
configFile = NormalizeFilePath(args[i]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string error = string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.InvalidSettingsFileArgument, args[i], ex.Message);
|
||||
WriteCommandLineError(error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(configFile))
|
||||
{
|
||||
string error = string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.SettingsFileNotExists, configFile);
|
||||
WriteCommandLineError(error);
|
||||
break;
|
||||
}
|
||||
PowerShellConfig.Instance.SetSystemConfigFilePath(configFile);
|
||||
}
|
||||
#if STAMODE
|
||||
// explicit setting of the ApartmentState Not supported on NanoServer
|
||||
|
@ -818,25 +960,6 @@ namespace Microsoft.PowerShell
|
|||
_exitCode = ConsoleHost.ExitCodeBadCommandLineParameter;
|
||||
}
|
||||
|
||||
private bool MatchSwitch(string switchKey, string match, string smallestUnambiguousMatch)
|
||||
{
|
||||
Dbg.Assert(switchKey != null, "need a value");
|
||||
Dbg.Assert(!String.IsNullOrEmpty(match), "need a value");
|
||||
Dbg.Assert(match.Trim().ToLowerInvariant() == match, "match should be normalized to lowercase w/ no outside whitespace");
|
||||
Dbg.Assert(smallestUnambiguousMatch.Trim().ToLowerInvariant() == smallestUnambiguousMatch, "match should be normalized to lowercase w/ no outside whitespace");
|
||||
Dbg.Assert(match.Contains(smallestUnambiguousMatch), "sUM should be a substring of match");
|
||||
|
||||
if (match.Trim().ToLowerInvariant().IndexOf(switchKey, StringComparison.Ordinal) == 0)
|
||||
{
|
||||
if (switchKey.Length >= smallestUnambiguousMatch.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ParseFormat(string[] args, ref int i, ref Serialization.DataFormat format, string resourceStr)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -892,15 +1015,6 @@ namespace Microsoft.PowerShell
|
|||
executionPolicy = args[i];
|
||||
}
|
||||
|
||||
private static string NormalizeFilePath(string path)
|
||||
{
|
||||
// Normalize slashes
|
||||
path = path.Replace(StringLiterals.AlternatePathSeparator,
|
||||
StringLiterals.DefaultPathSeparator);
|
||||
|
||||
return Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
private bool ParseFile(string[] args, ref int i, bool noexitSeen)
|
||||
{
|
||||
// Process file execution. We don't need to worry about checking -command
|
||||
|
|
|
@ -148,6 +148,12 @@ namespace Microsoft.PowerShell
|
|||
|
||||
try
|
||||
{
|
||||
// We need to read the settings file before we create the console host
|
||||
string[] tempArgs = new string[args.GetLength(0)];
|
||||
args.CopyTo(tempArgs, 0);
|
||||
|
||||
CommandLineParameterParser.EarlyParse(tempArgs);
|
||||
|
||||
// We might be able to ignore console host creation error if we are running in
|
||||
// server mode, which does not require a console.
|
||||
HostException hostException = null;
|
||||
|
@ -168,8 +174,6 @@ namespace Microsoft.PowerShell
|
|||
s_cpp = new CommandLineParameterParser(
|
||||
(s_theConsoleHost != null) ? s_theConsoleHost.UI : (new NullHostUserInterface()),
|
||||
bannerText, helpText);
|
||||
string[] tempArgs = new string[args.GetLength(0)];
|
||||
args.CopyTo(tempArgs, 0);
|
||||
|
||||
s_cpp.Parse(tempArgs);
|
||||
|
||||
|
|
|
@ -967,7 +967,12 @@ namespace System.Management.Automation
|
|||
strongName, moduleName, psVersion, assemblyVersion, types, formats, null,
|
||||
s_coreSnapin.Description, s_coreSnapin.DescriptionIndirect, null, null,
|
||||
s_coreSnapin.VendorIndirect, null);
|
||||
#if !UNIX
|
||||
// NOTE: On Unix, logging has to be deferred until after command-line parsing
|
||||
// complete. On Windows, deferring the call is not needed
|
||||
// and this is in the startup code path.
|
||||
SetSnapInLoggingInformation(coreMshSnapin);
|
||||
#endif
|
||||
|
||||
return coreMshSnapin;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ Describe 'Basic SysLog tests on Linux' -Tag @('CI','RequireSudoOnUnix') {
|
|||
}
|
||||
}
|
||||
|
||||
Describe 'Basic os_log tests on MacOS' -Tag @('CI','RequireSudoOnUnix') {
|
||||
Describe 'Basic os_log tests on MacOS' -Tag @('Feature','RequireSudoOnUnix') {
|
||||
BeforeAll {
|
||||
[bool] $IsSupportedEnvironment = $IsMacOS
|
||||
[bool] $persistenceEnabled = $false
|
||||
|
@ -201,34 +201,33 @@ Describe 'Basic os_log tests on MacOS' -Tag @('CI','RequireSudoOnUnix') {
|
|||
}
|
||||
}
|
||||
|
||||
## Logging seems broken on macOS 10.13. It works fine on macOS 10.12.6.
|
||||
## Travis CI updated macOS to 10.13.3 (kernel 17.4) and the logging tests start to fail.
|
||||
# It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) {
|
||||
It 'Verifies basic logging with no customizations' -Pending {
|
||||
It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) {
|
||||
$configFile = WriteLogSettings -LogId $logId
|
||||
& $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null'
|
||||
$testPid = & $powershell -NoProfile -SettingsFile $configFile -Command '$PID'
|
||||
|
||||
Export-PSOsLog -After $after -Verbose | Set-Content -Path $contentFile
|
||||
$items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 -Verbose
|
||||
# Made tests more reliable
|
||||
Start-Sleep -Milliseconds 500
|
||||
|
||||
Export-PSOsLog -After $after -LogPid $testPid -Verbose | Set-Content -Path $contentFile
|
||||
$items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 -Verbose)
|
||||
|
||||
$items | Should -Not -Be $null
|
||||
$items.Length | Should -BeGreaterThan 1
|
||||
$items.Count | Should -BeGreaterThan 1
|
||||
$items[0].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational'
|
||||
$items[1].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational'
|
||||
# if there are more items than expected...
|
||||
if ($items.Length -gt 2)
|
||||
if ($items.Count -gt 2)
|
||||
{
|
||||
# Force reporting of the first unexpected item to help diagnosis
|
||||
$items[2] | Should -Be $null
|
||||
}
|
||||
}
|
||||
|
||||
# It 'Verifies logging level filtering works' -Skip:(!$IsSupportedEnvironment) {
|
||||
It 'Verifies logging level filtering works' -Pending {
|
||||
It 'Verifies logging level filtering works' -Skip:(!$IsSupportedEnvironment) {
|
||||
$configFile = WriteLogSettings -LogId $logId -LogLevel Warning
|
||||
& $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null'
|
||||
$testPid = & $powershell -NoLogo -NoProfile -SettingsFile $configFile -Command '$PID'
|
||||
|
||||
Export-PSOsLog -After $after -Verbose | Set-Content -Path $contentFile
|
||||
Export-PSOsLog -After $after -LogPid $testPid -Verbose | Set-Content -Path $contentFile
|
||||
# by default, powershell startup should only logs informational events.
|
||||
# With Level = Warning, nothing should be logged.
|
||||
$items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3
|
||||
|
|
|
@ -142,22 +142,34 @@ enum SysLogIds
|
|||
|
||||
# Defines the array indices when calling
|
||||
# String.Split on an OsLog log entry
|
||||
enum OsLogIds
|
||||
Class OsLogIds
|
||||
{
|
||||
Date = 0;
|
||||
Time = 1;
|
||||
Thread = 2;
|
||||
Type = 3;
|
||||
Activity = 4;
|
||||
Pid = 5;
|
||||
ProcessName = 6;
|
||||
Module = 7;
|
||||
Id = 8;
|
||||
CommitId = 9;
|
||||
EventId = 10;
|
||||
Message = 11;
|
||||
[int] $Date = 0;
|
||||
[int] $Time = 1;
|
||||
[int] $Thread = 2;
|
||||
[int] $Type = 3;
|
||||
[int] $Activity = 4;
|
||||
[int] $Pid = 5;
|
||||
[int] $TTL = 6;
|
||||
[int] $ProcessName = 7;
|
||||
[int] $Module = 8;
|
||||
[int] $Id = 9;
|
||||
[int] $CommitId = 10;
|
||||
[int] $EventId = 11;
|
||||
[int] $Message = 12;
|
||||
|
||||
[void] UseOldIds()
|
||||
{
|
||||
$this.ProcessName=6;
|
||||
$this.Module =7;
|
||||
$this.Id =8;
|
||||
$this.CommitId=9;
|
||||
$this.EventId=10;
|
||||
$this.Message=11;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PSLogItem
|
||||
{
|
||||
[string] $LogId = [string]::Empty
|
||||
|
@ -336,12 +348,13 @@ class PSLogItem
|
|||
3: Type Default
|
||||
4: activity 0x12
|
||||
5: PID 39437
|
||||
6: processname pwsh:
|
||||
7: sourcedll (libpsl-native.dylib)
|
||||
8: log source [com.microsoft.powershell.powershell]
|
||||
9: commitid:treadid:channel (v6.0.1:1:10)
|
||||
10:[EventId] [Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational]
|
||||
11:Message Text
|
||||
6: TTL (introduced in ~ 10.13) 0
|
||||
7: processname pwsh:
|
||||
8: sourcedll (libpsl-native.dylib)
|
||||
9: log source [com.microsoft.powershell.powershell]
|
||||
10: commitid:treadid:channel (v6.0.1:1:10)
|
||||
11:[EventId] [Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational]
|
||||
12:Message Text
|
||||
#>
|
||||
|
||||
[object] $result = $content
|
||||
|
@ -382,17 +395,28 @@ class PSLogItem
|
|||
$item.Count = 1
|
||||
|
||||
$item.Timestamp = $time
|
||||
$item.ProcessId = [int]::Parse($parts[[OsLogIds]::Pid])
|
||||
$item.Message = $parts[[OsLogIds]::Message]
|
||||
$osLogIds = [OsLogIds]::new();
|
||||
$item.ProcessId = [int]::Parse($parts[$osLogIds.Pid])
|
||||
|
||||
# Around macOS 13, Apple added a field
|
||||
# Detect if the field is the old or new field and if it is old
|
||||
# Switch to the old schema
|
||||
if($parts[$osLogIds.TTL] -match '\:')
|
||||
{
|
||||
$osLogIds.UseOldIds()
|
||||
}
|
||||
|
||||
$item.Message = $parts[$osLogIds.Message]
|
||||
|
||||
# [com.microsoft.powershell.logid]
|
||||
$splitChars = ('[', '.', ']')
|
||||
$item.LogId = $parts[[OsLogIds]::Id]
|
||||
|
||||
$item.LogId = $parts[$osLogIds.Id]
|
||||
$subparts = $item.LogId.Split($splitChars, [StringSplitOptions]::RemoveEmptyEntries)
|
||||
if ($subparts.Length -eq 4)
|
||||
{
|
||||
$item.LogId = $subparts[3]
|
||||
if ($id -ne $null -and $id -ne $item.LogId)
|
||||
if ($null -ne $id -and $id -ne $item.LogId)
|
||||
{
|
||||
# this is not the log id we're looking for.
|
||||
$result = $null
|
||||
|
@ -401,7 +425,7 @@ class PSLogItem
|
|||
}
|
||||
# (commitid:TID:ChannelID)
|
||||
$splitChars = ('(', ')', ':', ' ')
|
||||
$item.CommitId = $parts[[OsLogIds]::CommitId]
|
||||
$item.CommitId = $parts[$osLogIds.CommitId]
|
||||
$subparts = $item.CommitId.Split($splitChars, [System.StringSplitOptions]::RemoveEmptyEntries)
|
||||
if ($subparts.Count -eq 3)
|
||||
{
|
||||
|
@ -416,7 +440,7 @@ class PSLogItem
|
|||
|
||||
# [EventId]
|
||||
$splitChars = ('[', ']', ' ')
|
||||
$item.EventId = $parts[[OsLogIds]::EventId]
|
||||
$item.EventId = $parts[$osLogIds.EventId]
|
||||
$subparts = $item.EventId.Split($splitChars, [System.StringSplitOptions]::RemoveEmptyEntries)
|
||||
if ($subparts.Count -eq 1)
|
||||
{
|
||||
|
@ -805,22 +829,41 @@ function Export-PSOsLog
|
|||
[ValidateNotNullOrEmpty()]
|
||||
[DateTime] $After,
|
||||
|
||||
[string] $LogId = "powershell"
|
||||
[string] $LogId = "powershell",
|
||||
|
||||
[int] $LogPid
|
||||
)
|
||||
|
||||
Test-MacOS
|
||||
|
||||
# NOTE: The use of double quotes and single quotes for the predicate parameter
|
||||
# is mandatory. Reversing the usage (e.g., single quotes around double quotes)
|
||||
# causes the double quotes to be stripped breaking the predicate syntax expected
|
||||
# by log show
|
||||
$extraParams = @()
|
||||
if($LogPid)
|
||||
{
|
||||
$extraParams += @(
|
||||
'--predicate'
|
||||
"processID == $LogPid"
|
||||
)
|
||||
}
|
||||
if ($After -ne $null)
|
||||
{
|
||||
[string] $startTime = $After.ToString("yyyy-MM-dd HH:mm:ss")
|
||||
Start-NativeExecution -command {log show --info --start "$startTime" --predicate "subsystem == 'com.microsoft.powershell'"}
|
||||
$extraParams += @(
|
||||
'--start'
|
||||
"$startTime"
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
Start-NativeExecution -command {log show --info --predicate "process == 'pwsh'"}
|
||||
else {
|
||||
$extraParams += @(
|
||||
'--predicate'
|
||||
"process == 'pwsh'"
|
||||
)
|
||||
}
|
||||
|
||||
Start-NativeExecution -command {log show --info @extraParams}
|
||||
}
|
||||
|
||||
<#
|
||||
|
|
Loading…
Reference in a new issue