diff --git a/appveyor.yml b/appveyor.yml
index f53c786d2..6caea8428 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -40,7 +40,7 @@ test_script:
$env:CoreOutput = Split-Path -Parent (Get-PSOutput -Options (New-PSOptions -Publish))
Write-Host -Foreground Green 'Run CoreCLR tests'
$testResultsFile = "$pwd\TestsResults.xml"
- & ("$env:CoreOutput\powershell.exe") -noprofile -noninteractive -c "Invoke-Pester test/powershell -Tag 'CI' -ExcludeTag 'Slow' -OutputFormat NUnitXml -OutputFile $testResultsFile"
+ & ("$env:CoreOutput\powershell.exe") -noprofile -noninteractive -c "Set-ExecutionPolicy -Scope Process Unrestricted; Invoke-Pester test/powershell -Tag 'CI' -ExcludeTag 'Slow' -OutputFormat NUnitXml -OutputFile $testResultsFile"
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile))
#
@@ -48,7 +48,7 @@ test_script:
$env:FullOutput = Split-Path -Parent (Get-PSOutput -Options (New-PSOptions -FullCLR))
Write-Host -Foreground Green 'Run FullCLR tests'
$testResultsFileFullCLR = "$pwd\TestsResults.FullCLR.xml"
- Start-DevPowerShell -FullCLR -NoNewWindow -ArgumentList '-noprofile', '-noninteractive' -Command "Invoke-Pester test/fullCLR -ExcludeTag 'Slow' -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
+ Start-DevPowerShell -FullCLR -NoNewWindow -ArgumentList '-noprofile', '-noninteractive' -Command "Set-ExecutionPolicy -Scope Process Unrestricted; Invoke-Pester test/fullCLR -ExcludeTag 'Slow' -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFileFullCLR))
#
# Fail the build, if tests failed
diff --git a/build.psm1 b/build.psm1
index b345f7617..89db96c77 100644
--- a/build.psm1
+++ b/build.psm1
@@ -271,7 +271,7 @@ function Start-PSBuild {
$nativeResourcesFolder = $_
Get-ChildItem $nativeResourcesFolder -Filter "*.mc" | % {
$command = @"
-cmd.exe /C cd /d "(Get-Location)" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeHostArch" "&" "$mcexe" -o -d -c -U $($_.FullName) -h "$nativeResourcesFolder" -r "$nativeResourcesFolder"
+cmd.exe /C cd /d "(Get-Location)" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeHostArch" "&" mc.exe -o -d -c -U $($_.FullName) -h "$nativeResourcesFolder" -r "$nativeResourcesFolder"
"@
log " Executing mc.exe Command: $command"
Start-NativeExecution { Invoke-Expression -Command:$command }
@@ -526,6 +526,7 @@ function Start-PSPester {
[string[]]$Tag = "CI",
[string]$Path = "$PSScriptRoot/test/powershell"
)
+
$tagString = "-outputFormat ${OutputFormat} -outputFile ${outputFile} "
if ( ! $DisableExit ) { $tagString += " -EnableExit" }
if ( $ExcludeTag -and ($ExcludeTag -ne "")) { $tagString += " -ExcludeTag @('" + (${ExcludeTag} -join "','") + "')" }
@@ -537,7 +538,7 @@ function Start-PSPester {
Write-Verbose "Import-Module '$moduleDir'; Invoke-Pester $tagString $Path"
$powershellexe = get-psoutput
- & $powershell -noprofile -c "Set-ExecutionPolicy Unrestricted; Import-Module '$moduleDir'; Invoke-Pester $tagString $Path"
+ & $powershell -noprofile -c "Set-ExecutionPolicy -Scope Process Unrestricted; Import-Module '$moduleDir'; Invoke-Pester $tagString $Path"
if ($LASTEXITCODE -ne 0) {
throw "$LASTEXITCODE Pester tests failed"
}
diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
index 15c63ce7a..c5c88d67d 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
+++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
@@ -170,12 +170,12 @@ namespace Microsoft.PowerShell
// APIs
private bool PromptUsingConsole()
{
-#if CORECLR // on Nano there is no other way to prompt except by using console
+#if CORECLR
+ // on Nano there is no other way to prompt except by using console
return true;
#else
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
Exception exception = null;
- bool promptUsingConsole = propertyAccessor.GetConsolePrompting(ref exception);
+ bool promptUsingConsole = ConfigPropertyAccessor.Instance.GetConsolePrompting(ref exception);
if (null != exception)
{
s_tracer.TraceError("Could not read CredUI registry key: " + exception.Message);
diff --git a/src/System.Management.Automation/engine/PropertyAccessor.cs b/src/System.Management.Automation/engine/PropertyAccessor.cs
index 10ca8c5fc..c83f737c8 100644
--- a/src/System.Management.Automation/engine/PropertyAccessor.cs
+++ b/src/System.Management.Automation/engine/PropertyAccessor.cs
@@ -9,20 +9,17 @@ using System.Globalization;
using System.Threading;
using System.Management.Automation;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Microsoft.Win32;
#if CORECLR
// Some APIs are missing from System.Environment. We use System.Management.Automation.Environment as a proxy type:
// - for missing APIs, System.Management.Automation.Environment has extension implementation.
// - for existing APIs, System.Management.Automation.Environment redirect the call to System.Environment.
using Environment = System.Management.Automation.Environment;
-#else
-//using Microsoft.Win32;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
#endif
-using Microsoft.Win32;
-
namespace System.Management.Automation
{
@@ -30,8 +27,40 @@ namespace System.Management.Automation
/// Leverages the strategy pattern to abstract away the details of gathering properties from outside sources.
/// Note: This is a class so that it can be internal.
///
- internal abstract class PropertyAccessor
+ internal abstract class ConfigPropertyAccessor
{
+ #region Statics
+ ///
+ /// Static constructor to instantiate an instance
+ ///
+ static ConfigPropertyAccessor()
+ {
+#if CORECLR
+ // TODO: Update this for #1184
+ //if (Platform.IsInbox())
+ //{
+ // Instance = new RegistryAccessor();
+ //}
+ //else
+ //{
+ // Instance = new JsonConfigFileAccessor();
+ //}
+ // Remove this following line:
+ Instance = new JsonConfigFileAccessor();
+#else
+ Instance = new RegistryAccessor();
+#endif
+ }
+ ///
+ /// The instance of the ConfigPropertyAccessor to use to iteract with properties.
+ /// Derived classes should not be directly instantiated.
+ ///
+ internal static readonly ConfigPropertyAccessor Instance;
+
+ #endregion // Statics
+
+ #region Enums
+
///
/// Describes the scope of the property query.
/// SystemWide properties apply to all users.
@@ -53,6 +82,10 @@ namespace System.Management.Automation
VersionSpecific = 2
}
+ #endregion // Enums
+
+ #region Interface Methods
+
///
/// Existing Key = HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
/// Proposed value = %ProgramFiles%\PowerShell\Modules by default
@@ -69,18 +102,9 @@ namespace System.Management.Automation
/// Where it should check for the value.
/// The shell associated with this policy. Typically, it is "Microsoft.PowerShell"
///
- internal abstract string GetMachineExecutionPolicy(PropertyScope scope, string shellId);
- internal abstract void RemoveMachineExecutionPolicy(PropertyScope scope, string shellId);
- internal abstract void SetMachineExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy);
-
- ///
- /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
- /// Proposed value = Existing value, otherwise 10.
- ///
- /// Max stack size in MB. If not set, defaults to 10 MB.
- internal abstract int GetPipeLineMaxStackSizeMb(int defaultValue);
-
- internal abstract void SetPipeLineMaxStackSizeMb(int maxStackSize);
+ internal abstract string GetExecutionPolicy(PropertyScope scope, string shellId);
+ internal abstract void RemoveExecutionPolicy(PropertyScope scope, string shellId);
+ internal abstract void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy);
///
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
@@ -105,30 +129,12 @@ namespace System.Management.Automation
///
internal abstract string GetDefaultSourcePath();
internal abstract void SetDefaultSourcePath(string defaultPath);
+
+ #endregion // Interface Methods
}
- internal class PropertyAccessorFactory
- {
- ///
- /// Template method to generate the appropriate accessor for a given environment.
- ///
- ///
- internal static PropertyAccessor GetPropertyAccessor()
- {
- if (null == _activePropertyAccessor)
- {
#if CORECLR
- // TODO: I must differentiate between inbox PS and side-by-side PS here eventually
- _activePropertyAccessor = new JsonConfigFileAccessor();
-#else
- _activePropertyAccessor = new RegistryAccessor();
-#endif
- }
- return _activePropertyAccessor;
- }
-
- private static PropertyAccessor _activePropertyAccessor;
- }
+ // TODO: JSON .Net should not be a required component for inbox PowerShell. We need to decide on the long term plan.
///
/// JSON configuration file accessor
@@ -136,24 +142,18 @@ namespace System.Management.Automation
/// Reads from and writes to configuration files. The values stored were
/// originally stored in the Windows registry.
///
- internal class JsonConfigFileAccessor : PropertyAccessor
+ internal class JsonConfigFileAccessor : ConfigPropertyAccessor
{
private string psHomeConfigDirectory;
private string appDataConfigDirectory;
private const string configDirectoryName = "Configuration";
- private const string modulePathFileName = "PSModulePath.json";
- private const string execPolicyFileName = "ExecutionPolicy.json";
- private const string maxStackSizeFileName = "PipeLineMaxStackSizeMB.json";
- private const string consolePromptingFileName = "ConsolePrompting.json";
- private const string updateHelpPromptFileName = "UpdateHelpPrompt.json";
- private const string updatableHelpSourcePathFileName = "UpdatableHelpDefaultSourcePath.json";
+ private const string configFileName = "PowerShellProperties.json";
internal JsonConfigFileAccessor()
{
//
// Initialize (and create if necessary) the system-wide configuration directory
//
- // TODO: Use Utils.GetApplicationBase("Microsoft.PowerShell") instead?
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
psHomeConfigDirectory = Path.Combine(Path.GetDirectoryName(assembly.Location), configDirectoryName);
@@ -174,25 +174,26 @@ namespace System.Management.Automation
}
///
- /// Note: This value is not writable, so it MUST be set during post-install configuration
+ /// Note: This value is not writable, so it MUST be set during post-install configuration.
+ /// Also, it will only be written to the $PSHOME configuration file (not the per-user file).
///
///
- ///
+ /// Value if found, null otherwise. The behavior matches Environment.GetEnvironmentVariable().
internal override string GetModulePath(ModulePathTarget target)
{
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
if (ModulePathTarget.CurrentUser == target)
{
// TODO: This feels unnecessary since it can be calculated based on the current user...
- return ReadValueFromFile(modulePathFileName, "UserModulePath");
+ return ReadValueFromFile(fileName, "UserModulePath");
}
else if (ModulePathTarget.SharedCommon == target)
{
- return ReadValueFromFile(modulePathFileName, "SharedCommonModulePath");
+ return ReadValueFromFile(fileName, "SharedCommonModulePath");
}
else
{
- // TODO: Is there a better way to handle this?
- throw new ArgumentException();
+ return null;
}
}
@@ -202,15 +203,15 @@ namespace System.Management.Automation
///
/// Schema:
/// {
- /// "shell ID string" : "execution policy string"
+ /// "shell ID string","ExecutionPolicy" : "execution policy string"
/// }
///
- /// Note: If we switch to a single config file, then this will need to be nested
+ /// TODO: In a single config file, it might be better to nest this. It is unnecessary complexity until a need arises for more nested values.
///
/// Whether this is a system-wide or per-user setting.
/// The shell associated with this policy. Typically, it is "Microsoft.PowerShell"
/// The execution policy if found. Null otherwise.
- internal override string GetMachineExecutionPolicy(PropertyScope scope, string shellId)
+ internal override string GetExecutionPolicy(PropertyScope scope, string shellId)
{
string execPolicy = null;
string scopeDirectory = psHomeConfigDirectory;
@@ -221,9 +222,9 @@ namespace System.Management.Automation
scopeDirectory = appDataConfigDirectory;
}
- string fileName = Path.Combine(scopeDirectory, execPolicyFileName);
-
- string rawExecPolicy = ReadValueFromFile(fileName, shellId);
+ string fileName = Path.Combine(scopeDirectory, configFileName);
+ string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
+ string rawExecPolicy = ReadValueFromFile(fileName, valueName);
if (!String.IsNullOrEmpty(rawExecPolicy))
{
@@ -232,7 +233,7 @@ namespace System.Management.Automation
return execPolicy;
}
- internal override void RemoveMachineExecutionPolicy(PropertyScope scope, string shellId)
+ internal override void RemoveExecutionPolicy(PropertyScope scope, string shellId)
{
string scopeDirectory = psHomeConfigDirectory;
@@ -242,12 +243,12 @@ namespace System.Management.Automation
scopeDirectory = appDataConfigDirectory;
}
- string fileName = Path.Combine(scopeDirectory, execPolicyFileName);
-
- RemoveValueFromFile(fileName, shellId);
+ string fileName = Path.Combine(scopeDirectory, configFileName);
+ string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
+ RemoveValueFromFile(fileName, valueName);
}
- internal override void SetMachineExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
+ internal override void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
{
string scopeDirectory = psHomeConfigDirectory;
@@ -257,39 +258,9 @@ namespace System.Management.Automation
scopeDirectory = appDataConfigDirectory;
}
- string fileName = Path.Combine(scopeDirectory, execPolicyFileName);
-
- WriteValueToFile(fileName, shellId, executionPolicy);
- }
-
- ///
- /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
- /// Proposed value = Existing value, otherwise 10.
- ///
- /// Schema:
- /// {
- /// "PipeLineMaxStackSizeMB" : int
- /// }
- ///
- /// Max stack size in MB. If not set, defaults to 10 MB.
- internal override int GetPipeLineMaxStackSizeMb(int defaultValue)
- {
- string fileName = Path.Combine(psHomeConfigDirectory, maxStackSizeFileName);
-
- int maxStackSize = defaultValue;
- int rawMaxStackSize = ReadValueFromFile(fileName, "PipeLineMaxStackSizeMB");
-
- if (0 != rawMaxStackSize)
- {
- maxStackSize = rawMaxStackSize;
- }
- return maxStackSize;
- }
-
- internal override void SetPipeLineMaxStackSizeMb(int maxStackSize)
- {
- string fileName = Path.Combine(psHomeConfigDirectory, maxStackSizeFileName);
- WriteValueToFile(fileName, "PipeLineMaxStackSizeMB", maxStackSize);
+ string fileName = Path.Combine(scopeDirectory, configFileName);
+ string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
+ WriteValueToFile(fileName, valueName, executionPolicy);
}
///
@@ -304,13 +275,13 @@ namespace System.Management.Automation
/// Whether console prompting should happen. If the value cannot be read it defaults to false.
internal override bool GetConsolePrompting(ref Exception exception)
{
- string fileName = Path.Combine(psHomeConfigDirectory, consolePromptingFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
return ReadValueFromFile(fileName, "ConsolePrompting");
}
internal override void SetConsolePrompting(bool shouldPrompt)
{
- string fileName = Path.Combine(psHomeConfigDirectory, consolePromptingFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile(fileName, "ConsolePrompting", shouldPrompt);
}
@@ -326,13 +297,13 @@ namespace System.Management.Automation
/// Boolean indicating whether Update-Help should prompt. If the value cannot be read, it defaults to false.
internal override bool GetDisablePromptToUpdateHelp()
{
- string fileName = Path.Combine(psHomeConfigDirectory, updateHelpPromptFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
return ReadValueFromFile(fileName, "DisablePromptToUpdateHelp");
}
internal override void SetDisablePromptToUpdateHelp(bool prompt)
{
- string fileName = Path.Combine(psHomeConfigDirectory, updateHelpPromptFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile(fileName, "DisablePromptToUpdateHelp", prompt);
}
@@ -348,7 +319,7 @@ namespace System.Management.Automation
/// The source path if found, null otherwise.
internal override string GetDefaultSourcePath()
{
- string fileName = Path.Combine(psHomeConfigDirectory, updatableHelpSourcePathFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string rawExecPolicy = ReadValueFromFile(fileName, "DefaultSourcePath");
@@ -361,7 +332,7 @@ namespace System.Management.Automation
internal override void SetDefaultSourcePath(string defaultPath)
{
- string fileName = Path.Combine(psHomeConfigDirectory, updatableHelpSourcePathFileName);
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile(fileName, "DefaultSourcePath", defaultPath);
}
@@ -383,15 +354,11 @@ namespace System.Management.Automation
}
}
catch (ArgumentException) { }
- //catch (ArgumentNullException) { }
catch (NotSupportedException) { }
catch (FileNotFoundException) { }
- catch (System.IO.IOException) { }
- //catch (DirectoryNotFoundException) { }
+ catch (IOException) { }
catch (System.Security.SecurityException) { }
catch (UnauthorizedAccessException) { }
- //catch (PathTooLongException) { }
- //catch (ArgumentOutOfRangeException) { }
return default(T);
}
@@ -403,71 +370,94 @@ namespace System.Management.Automation
///
///
///
- /// Whether the key-value pair should be added or removed from the file
+ /// Whether the key-value pair should be added to or removed from the file
private void UpdateValueInFile(string fileName, string key, T value, bool addValue)
{
try
{
- JObject objectToWrite = new JObject();
-
- if (File.Exists(fileName))
+ // Since multiple properties can be in a single file, replacement
+ // is required instead of overwrite if a file already exists.
+ // Handling the read and write operations within a single FileStream
+ // prevents other processes from reading or writing the file while
+ // the update is in progress.
+ using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
+ using (StreamReader streamRdr = new StreamReader(fs))
+ using (JsonTextReader jsonReader = new JsonTextReader(streamRdr))
{
- // Since multiple properties can be in a single file, replacement
- // is required instead of overwrite if a file already exists.
- using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
- using (StreamReader streamRdr = new StreamReader(fs))
- using (JsonTextReader jsonReader = new JsonTextReader(streamRdr))
+ JObject jsonObject = null;
+ bool isReadSuccess = jsonReader.Read(); // Safely determines whether there is content to read from the file
+
+ if ( ! isReadSuccess)
{
- JObject jsonObject = (JObject) JToken.ReadFrom(jsonReader);
- IEnumerable properties = jsonObject.Properties();
- foreach (JProperty property in properties)
+ // The file doesn't already exist and we want to write to it or
+ // exists with no content.
+ // A new file will be created that contains only this value.
+ // If the file doesn't exist and a we don't want to write to it, no
+ // action is necessary.
+ if (addValue)
{
- if (String.Equals(property.Name, key, StringComparison.OrdinalIgnoreCase))
+ jsonObject = new JObject(new JProperty(key, value));
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ // Read the stream into a root JObject for manipulation
+ jsonObject = (JObject) JToken.ReadFrom(jsonReader);
+ JProperty propertyToModify = jsonObject.Property(key);
+
+ if (null == propertyToModify)
+ {
+ // The property doesn't exist, so add it
+ if (addValue)
{
- if (addValue)
- {
- // Add the updated value to the output object instead
- // of the preexisting one
- objectToWrite.Add(new JProperty(key, value));
- }
- // else the value is skipped so it is removed from the file
+ jsonObject.Add(new JProperty(key, value));
+ }
+ // else the property doesn't exist so there is nothing to remove
+ }
+ // The property exists
+ else
+ {
+ if (addValue)
+ {
+ propertyToModify.Replace(new JProperty(key, value));
}
else
{
- // This preserves existing properties that do not
- // match the one to update
- objectToWrite.Add(new JProperty(property));
+ propertyToModify.Remove();
}
}
}
- }
- else
- {
- if (addValue)
+
+ // Reset the stream position to the beginning so that the
+ // changes to the file can be written to disk
+ fs.Seek(0, SeekOrigin.Begin);
+
+ // Update the file with new content
+ using (StreamWriter streamWriter = new StreamWriter(fs))
+ using (JsonTextWriter jsonWriter = new JsonTextWriter(streamWriter))
{
- // The file doesn't exist, so create it with the new property
- objectToWrite.Add(new JProperty(key, value));
+ // The entire document exists within the root JObject.
+ // I just need to write that object to produce the document.
+ jsonObject.WriteTo(jsonWriter);
+
+ // This trims the file if the file shrank. If the file grew,
+ // it is a no-op. The purpose is to trim extraneous characters
+ // from the file stream when the resultant JObject is smaller
+ // than the input JObject.
+ fs.SetLength(fs.Position);
}
}
-
- using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
- using (StreamWriter streamWriter = new StreamWriter(fs))
- using (JsonTextWriter jsonWriter = new JsonTextWriter(streamWriter))
- {
- objectToWrite.WriteTo(jsonWriter);
- }
-
}
catch (ArgumentException) { }
- //catch (ArgumentNullException) { }
catch (NotSupportedException) { }
catch (FileNotFoundException) { }
- catch (System.IO.IOException) { }
- //catch (DirectoryNotFoundException) { }
+ catch (IOException) { }
catch (System.Security.SecurityException) { }
catch (UnauthorizedAccessException) { }
- //catch (PathTooLongException) { }
- //catch (ArgumentOutOfRangeException) { }
}
///
@@ -494,7 +484,9 @@ namespace System.Management.Automation
}
}
- internal class RegistryAccessor : PropertyAccessor
+#endif // CORECLR
+
+ internal class RegistryAccessor : ConfigPropertyAccessor
{
private const string DisablePromptToUpdateHelpRegPath = "Software\\Microsoft\\PowerShell";
private const string DisablePromptToUpdateHelpRegPath32 = "Software\\Wow6432Node\\Microsoft\\PowerShell";
@@ -524,7 +516,7 @@ namespace System.Management.Automation
///
///
/// The execution policy string if found, otherwise null.
- internal override string GetMachineExecutionPolicy(PropertyScope scope, string shellId)
+ internal override string GetExecutionPolicy(PropertyScope scope, string shellId)
{
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
RegistryKey scopedKey = Registry.LocalMachine;
@@ -538,7 +530,7 @@ namespace System.Management.Automation
return GetRegistryString(scopedKey, regKeyName, "ExecutionPolicy");
}
- internal override void SetMachineExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
+ internal override void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
{
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
RegistryKey scopedKey = Registry.LocalMachine;
@@ -558,7 +550,7 @@ namespace System.Management.Automation
}
}
- internal override void RemoveMachineExecutionPolicy(PropertyScope scope, string shellId)
+ internal override void RemoveExecutionPolicy(PropertyScope scope, string shellId)
{
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
RegistryKey scopedKey = Registry.LocalMachine;
@@ -579,21 +571,6 @@ namespace System.Management.Automation
}
}
- internal override int GetPipeLineMaxStackSizeMb(int defaultValue)
- {
- string regKeyName = Utils.GetRegistryConfigurationPrefix();
-
- int? tempInt = GetRegistryDword(Registry.LocalMachine, regKeyName, "PipelineMaxStackSizeMB");
-
- return (tempInt.HasValue ? tempInt.Value : defaultValue);
- }
-
- internal override void SetPipeLineMaxStackSizeMb(int maxStackSize)
- {
- string regKeyName = Utils.GetRegistryConfigurationPrefix();
- SetRegistryDword(Registry.LocalMachine, regKeyName, "PipelineMaxStackSizeMB", maxStackSize);
- }
-
///
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
/// Proposed value = existing default. Probably "1"
@@ -727,7 +704,7 @@ namespace System.Management.Automation
catch (ObjectDisposedException) { }
catch (System.Security.SecurityException) { }
catch (ArgumentException) { }
- catch (System.IO.IOException) { }
+ catch (IOException) { }
catch (UnauthorizedAccessException) { }
catch (FormatException) { }
catch (OverflowException) { }
@@ -751,7 +728,7 @@ namespace System.Management.Automation
catch (ObjectDisposedException) { }
catch (System.Security.SecurityException) { }
catch (ArgumentException) { }
- catch (System.IO.IOException) { }
+ catch (IOException) { }
catch (UnauthorizedAccessException) { }
catch (FormatException) { }
catch (OverflowException) { }
@@ -794,7 +771,7 @@ namespace System.Management.Automation
catch (ObjectDisposedException e) { exception = e; }
catch (System.Security.SecurityException e) { exception = e; }
catch (ArgumentException e) { exception = e; }
- catch (System.IO.IOException e) { exception = e; }
+ catch (IOException e) { exception = e; }
catch (UnauthorizedAccessException e) { exception = e; }
catch (FormatException e) { exception = e; }
catch (OverflowException e) { exception = e; }
@@ -818,7 +795,7 @@ namespace System.Management.Automation
catch (ObjectDisposedException) { }
catch (System.Security.SecurityException) { }
catch (ArgumentException) { }
- catch (System.IO.IOException) { }
+ catch (IOException) { }
catch (UnauthorizedAccessException) { }
catch (FormatException) { }
catch (OverflowException) { }
diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs
index d79544da6..3ba32c7bf 100644
--- a/src/System.Management.Automation/engine/Utils.cs
+++ b/src/System.Management.Automation/engine/Utils.cs
@@ -237,8 +237,9 @@ namespace System.Management.Automation
///
internal static string GetApplicationBase(string shellId)
{
-#if CORECLR // Use the location of SMA.dll as the application base
- // Assembly.GetEntryAssembly is not in CoreCLR. GAC is not in CoreCLR.
+#if CORECLR
+ // Use the location of SMA.dll as the application base
+ // Assembly.GetEntryAssembly and GAC are not in CoreCLR.
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
return Path.GetDirectoryName(assembly.Location);
#else
@@ -280,14 +281,16 @@ namespace System.Management.Automation
///
/// Specifies the per-user configuration settings directory in a platform agnostic manner.
- /// Ex:
- /// %LOCALAPPDATA%\PowerShell\
+ /// Windows Ex:
+ /// %LOCALAPPDATA%\PowerShell
+ /// Non-Windows Ex:
+ /// ~/.config/PowerShell
///
/// The current user's configuration settings directory
internal static string GetUserSettingsDirectory()
{
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
- return Path.Combine(appDataPath, "PowerShell", PSVersionInfo.PSVersion.ToString()); // TODO: This should be the external version#, but I don't see it anywhere in the code
+ return Path.Combine(appDataPath, "PowerShell");
}
private static string[] GetProductFolderDirectories()
diff --git a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs
index 6ff6f7a1e..f2b305058 100644
--- a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs
+++ b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs
@@ -254,8 +254,7 @@ namespace System.Management.Automation.Runspaces
{
get
{
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
- int i = propertyAccessor.GetPipeLineMaxStackSizeMb(10);
+ int i = ReadRegistryInt("PipelineMaxStackSizeMB", 10);
if (i < 10)
i = 10; // minimum 10MB
@@ -533,6 +532,40 @@ namespace System.Management.Automation.Runspaces
return flowControlException;
}
+ // NTRAID#Windows Out Of Band Releases-915506-2005/09/09
+ // Removed HandleUnexpectedExceptions infrastructure
+
+ internal static int ReadRegistryInt(string policyValueName, int defaultValue)
+ {
+ RegistryKey key;
+ try
+ {
+ key = Registry.LocalMachine.OpenSubKey(Utils.GetRegistryConfigurationPrefix());
+ }
+ catch (System.Security.SecurityException)
+ {
+ return defaultValue;
+ }
+ if (null == key)
+ return defaultValue;
+
+ object temp;
+ try
+ {
+ temp = key.GetValue(policyValueName);
+ }
+ catch (System.Security.SecurityException)
+ {
+ return defaultValue;
+ }
+ if (!(temp is int))
+ {
+ return defaultValue;
+ }
+ int i = (int)temp;
+ return i;
+ }
+
// NTRAID#Windows Out Of Band Releases-915506-2005/09/09
// Removed HandleUnexpectedExceptions infrastructure
///
diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs
index 0776fb8a1..4d7b43016 100644
--- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs
+++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs
@@ -1593,8 +1593,7 @@ namespace System.Management.Automation.Help
///
internal string GetDefaultSourcePath()
{
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
- return propertyAccessor.GetDefaultSourcePath();
+ return ConfigPropertyAccessor.Instance.GetDefaultSourcePath();
}
///
@@ -1602,8 +1601,7 @@ namespace System.Management.Automation.Help
///
internal static void SetDisablePromptToUpdateHelp()
{
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
- propertyAccessor.SetDisablePromptToUpdateHelp(true);
+ ConfigPropertyAccessor.Instance.SetDisablePromptToUpdateHelp(true);
}
///
@@ -1619,8 +1617,7 @@ namespace System.Management.Automation.Help
return false;
}
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
- return propertyAccessor.GetDisablePromptToUpdateHelp();
+ return ConfigPropertyAccessor.Instance.GetDisablePromptToUpdateHelp();
}
catch (SecurityException)
{
diff --git a/src/System.Management.Automation/project.json b/src/System.Management.Automation/project.json
index f60feb16c..d692a01fe 100644
--- a/src/System.Management.Automation/project.json
+++ b/src/System.Management.Automation/project.json
@@ -197,6 +197,9 @@
"System.Management": "",
"System.Configuration": "",
"System.Configuration.Install": ""
+ },
+ "dependencies": {
+ "Newtonsoft.Json": "7.0.1"
}
}
}
diff --git a/src/System.Management.Automation/security/SecuritySupport.cs b/src/System.Management.Automation/security/SecuritySupport.cs
index f3b731745..17e6851ff 100644
--- a/src/System.Management.Automation/security/SecuritySupport.cs
+++ b/src/System.Management.Automation/security/SecuritySupport.cs
@@ -146,7 +146,6 @@ namespace System.Management.Automation.Internal
#else
string executionPolicy = "Restricted";
string preferenceKey = Utils.GetRegistryConfigurationPath(shellId);
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
switch (policy)
{
@@ -166,43 +165,47 @@ namespace System.Management.Automation.Internal
switch (scope)
{
case ExecutionPolicyScope.Process:
- {
- if (policy == ExecutionPolicy.Undefined)
- executionPolicy = null;
+ {
+ if (policy == ExecutionPolicy.Undefined)
+ executionPolicy = null;
- Environment.SetEnvironmentVariable("PSExecutionPolicyPreference", executionPolicy);
- break;
- }
+ Environment.SetEnvironmentVariable("PSExecutionPolicyPreference", executionPolicy);
+ break;
+ }
case ExecutionPolicyScope.CurrentUser:
+ {
+ // They want to remove it
+ if (policy == ExecutionPolicy.Undefined)
{
- // They want to remove it
- if (policy == ExecutionPolicy.Undefined)
- {
- propertyAccessor.RemoveMachineExecutionPolicy(PropertyAccessor.PropertyScope.CurrentUser, shellId);
- CleanKeyParents(Registry.CurrentUser, preferenceKey);
- }
- else
- {
- propertyAccessor.SetMachineExecutionPolicy(PropertyAccessor.PropertyScope.CurrentUser, shellId, executionPolicy);
- }
- break;
+ ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(
+ ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
+ CleanKeyParents(Registry.CurrentUser, preferenceKey);
}
+ else
+ {
+ ConfigPropertyAccessor.Instance.SetExecutionPolicy(
+ ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId, executionPolicy);
+ }
+ break;
+ }
case ExecutionPolicyScope.LocalMachine:
+ {
+ // They want to remove it
+ if (policy == ExecutionPolicy.Undefined)
{
- // They want to remove it
- if (policy == ExecutionPolicy.Undefined)
- {
- propertyAccessor.RemoveMachineExecutionPolicy(PropertyAccessor.PropertyScope.SystemWide, shellId);
- CleanKeyParents(Registry.LocalMachine, preferenceKey);
- }
- else
- {
- propertyAccessor.SetMachineExecutionPolicy(PropertyAccessor.PropertyScope.SystemWide, shellId, executionPolicy);
- }
- break;
+ ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(
+ ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
+ CleanKeyParents(Registry.LocalMachine, preferenceKey);
}
+ else
+ {
+ ConfigPropertyAccessor.Instance.SetExecutionPolicy(
+ ConfigPropertyAccessor.PropertyScope.SystemWide, shellId, executionPolicy);
+ }
+ break;
+ }
}
#endif
}
@@ -586,17 +589,15 @@ namespace System.Management.Automation.Internal
/// NULL if it is not defined at this level
private static string GetLocalPreferenceValue(string shellId, ExecutionPolicyScope scope)
{
- PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor();
-
switch (scope)
{
// 1: Look up the current-user preference
case ExecutionPolicyScope.CurrentUser:
- return propertyAccessor.GetMachineExecutionPolicy(PropertyAccessor.PropertyScope.CurrentUser, shellId);
+ return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
// 2: Look up the system-wide preference
case ExecutionPolicyScope.LocalMachine:
- return propertyAccessor.GetMachineExecutionPolicy(PropertyAccessor.PropertyScope.SystemWide, shellId);
+ return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
}
return null;
diff --git a/src/powershell-native/CMakeLists.txt b/src/powershell-native/CMakeLists.txt
index 7a7d72a53..dd039341f 100644
--- a/src/powershell-native/CMakeLists.txt
+++ b/src/powershell-native/CMakeLists.txt
@@ -40,7 +40,7 @@ endif (BUILD_ONECORE)
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${PROJECT_SOURCE_DIR}/Bin/${OUTPUTCONFIG}/${PWRSH_NATIVE_OUTPUT_DIRECTORY}")
- message(" Setting output directory for ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}}")
+ # message(" Setting output directory for ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}}")
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
#