mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 04:36:39 +00:00
Merge pull request #1530 from PowerShell/mirichmo/file-based-registry-support
Mirichmo/file based registry support Fixes #1187
This commit is contained in:
commit
e6202a06e5
12 files changed
+853
-171
No files matched your search
+2
-2
@@ -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
|
||||
|
||||
+4
-2
@@ -267,11 +267,12 @@ function Start-PSBuild {
|
||||
Push-Location "$PSScriptRoot\src\powershell-native"
|
||||
|
||||
# Compile native resources
|
||||
$currentLocation = Get-Location
|
||||
@("nativemsh/pwrshplugin") | % {
|
||||
$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 "$currentLocation" "&" "$($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 +527,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 +539,7 @@ function Start-PSPester {
|
||||
|
||||
Write-Verbose "Import-Module '$moduleDir'; Invoke-Pester $tagString $Path"
|
||||
$powershellexe = get-psoutput
|
||||
& $powershell -noprofile -c "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"
|
||||
}
|
||||
|
||||
@@ -170,58 +170,33 @@ 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
|
||||
string PolicyKeyName = Utils.GetRegistryConfigurationPrefix();
|
||||
const string PromptValueName = "ConsolePrompting";
|
||||
bool promptUsingConsole = false;
|
||||
RegistryKey key;
|
||||
|
||||
// Open the registry key that holds the configuration setting
|
||||
try
|
||||
{
|
||||
key = Registry.LocalMachine.OpenSubKey(PolicyKeyName);
|
||||
}
|
||||
catch (System.Security.SecurityException)
|
||||
{
|
||||
s_tracer.TraceError("User doesn't have access to read CredUI registry key.");
|
||||
return promptUsingConsole;
|
||||
}
|
||||
|
||||
if (key == null)
|
||||
{
|
||||
return promptUsingConsole;
|
||||
}
|
||||
|
||||
// Get the configuration setting
|
||||
try
|
||||
{
|
||||
object consolePromptingKey = key.GetValue(PromptValueName);
|
||||
if (consolePromptingKey != null) { promptUsingConsole = Convert.ToBoolean(consolePromptingKey.ToString(), CultureInfo.InvariantCulture); }
|
||||
promptUsingConsole = ConfigPropertyAccessor.Instance.GetConsolePrompting();
|
||||
}
|
||||
catch (System.Security.SecurityException e)
|
||||
{
|
||||
s_tracer.TraceError("Could not read CredUI registry key: " + e.Message);
|
||||
if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR
|
||||
return promptUsingConsole;
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
s_tracer.TraceError("Could not parse CredUI registry key: " + e.Message);
|
||||
if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR
|
||||
return promptUsingConsole;
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
s_tracer.TraceError("Could not parse CredUI registry key: " + e.Message);
|
||||
if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR
|
||||
return promptUsingConsole;
|
||||
}
|
||||
|
||||
s_tracer.WriteLine("DetermineCredUIPolicy: policy == {0}", promptUsingConsole);
|
||||
|
||||
if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR
|
||||
return promptUsingConsole;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -390,6 +390,7 @@
|
||||
<Compile Include="engine\pipeline.cs" />
|
||||
<Compile Include="engine\PositionalCommandParameter.cs" />
|
||||
<Compile Include="engine\ProgressRecord.cs" />
|
||||
<Compile Include="engine\PropertyAccessor.cs" />
|
||||
<Compile Include="engine\PropertyCmdletProviderInterfaces.cs" />
|
||||
<Compile Include="engine\ProviderInterfaces.cs" />
|
||||
<Compile Include="engine\ProviderNames.cs" />
|
||||
|
||||
@@ -641,7 +641,7 @@ namespace System.Management.Automation
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetExpandedEnvironmentVariable(string name, EnvironmentVariableTarget target)
|
||||
internal static string GetExpandedEnvironmentVariable(string name, EnvironmentVariableTarget target)
|
||||
{
|
||||
string result = Environment.GetEnvironmentVariable(name, target);
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
@@ -886,8 +886,8 @@ namespace System.Management.Automation
|
||||
internal static string SetModulePath()
|
||||
{
|
||||
string currentModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Process);
|
||||
string systemWideModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Machine);
|
||||
string personalModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.User);
|
||||
string systemWideModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.SystemWide);
|
||||
string personalModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.CurrentUser);
|
||||
|
||||
string newModulePathString = GetModulePath(currentModulePath, systemWideModulePath, personalModulePath);
|
||||
|
||||
|
||||
@@ -0,0 +1,797 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
using System.Management.Automation;
|
||||
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;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
#endif
|
||||
|
||||
namespace System.Management.Automation
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
internal abstract class ConfigPropertyAccessor
|
||||
{
|
||||
#region Statics
|
||||
/// <summary>
|
||||
/// Static constructor to instantiate an instance
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
/// <summary>
|
||||
/// The instance of the ConfigPropertyAccessor to use to iteract with properties.
|
||||
/// Derived classes should not be directly instantiated.
|
||||
/// </summary>
|
||||
internal static readonly ConfigPropertyAccessor Instance;
|
||||
|
||||
#endregion // Statics
|
||||
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Describes the scope of the property query.
|
||||
/// SystemWide properties apply to all users.
|
||||
/// CurrentUser properties apply to the current user that is impersonated.
|
||||
/// </summary>
|
||||
internal enum PropertyScope
|
||||
{
|
||||
SystemWide = 0,
|
||||
CurrentUser = 1
|
||||
}
|
||||
|
||||
#endregion // Enums
|
||||
|
||||
#region Interface Methods
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
|
||||
/// Proposed value = %ProgramFiles%\PowerShell\Modules by default
|
||||
///
|
||||
/// Note: There is no setter because this value is immutable.
|
||||
/// </summary>
|
||||
/// <returns>Module path values from the config file.</returns>
|
||||
internal abstract string GetModulePath(PropertyScope scope);
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKCU and HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
|
||||
/// Proposed value = Existing default execution policy if not already specified
|
||||
/// </summary>
|
||||
/// <param name="scope">Where it should check for the value.</param>
|
||||
/// <param name="shellId">The shell associated with this policy. Typically, it is "Microsoft.PowerShell"</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
|
||||
/// Proposed value = existing default. Probably "1"
|
||||
/// </summary>
|
||||
/// <returns>Whether console prompting should happen.</returns>
|
||||
internal abstract bool GetConsolePrompting();
|
||||
internal abstract void SetConsolePrompting(bool shouldPrompt);
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
|
||||
/// Proposed value = Existing default. Probably "0"
|
||||
/// </summary>
|
||||
/// <returns>Boolean indicating whether Update-Help should prompt</returns>
|
||||
internal abstract bool GetDisablePromptToUpdateHelp();
|
||||
internal abstract void SetDisablePromptToUpdateHelp(bool prompt);
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
|
||||
/// Proposed value = blank.This should be supported though
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal abstract string GetDefaultSourcePath();
|
||||
internal abstract void SetDefaultSourcePath(string defaultPath);
|
||||
|
||||
#endregion // Interface Methods
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
/// <summary>
|
||||
/// JSON configuration file accessor
|
||||
///
|
||||
/// Reads from and writes to configuration files. The values stored were
|
||||
/// originally stored in the Windows registry.
|
||||
/// </summary>
|
||||
internal class JsonConfigFileAccessor : ConfigPropertyAccessor
|
||||
{
|
||||
private string psHomeConfigDirectory;
|
||||
private string appDataConfigDirectory;
|
||||
private const string configDirectoryName = "Configuration";
|
||||
private const string configFileName = "PowerShellProperties.json";
|
||||
|
||||
/// <summary>
|
||||
/// 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 proceses.
|
||||
/// </summary>
|
||||
private ReaderWriterLockSlim fileLock = new ReaderWriterLockSlim();
|
||||
|
||||
internal JsonConfigFileAccessor()
|
||||
{
|
||||
//
|
||||
// Initialize (and create if necessary) the system-wide configuration directory
|
||||
//
|
||||
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
|
||||
psHomeConfigDirectory = Path.Combine(Path.GetDirectoryName(assembly.Location), configDirectoryName);
|
||||
|
||||
if (!Directory.Exists(psHomeConfigDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(psHomeConfigDirectory);
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize (and create if necessary) the per-user configuration directory
|
||||
//
|
||||
appDataConfigDirectory = Path.Combine(Utils.GetUserSettingsDirectory(), configDirectoryName);
|
||||
|
||||
if (!Directory.Exists(appDataConfigDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(appDataConfigDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This value is not writable via the API and must be set using a text editor.
|
||||
/// </summary>
|
||||
/// <param name="scope"></param>
|
||||
/// <returns>Value if found, null otherwise. The behavior matches ModuleIntrinsics.GetExpandedEnvironmentVariable().</returns>
|
||||
internal override string GetModulePath(PropertyScope scope)
|
||||
{
|
||||
string scopeDirectory = psHomeConfigDirectory;
|
||||
|
||||
// Defaults to system wide.
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopeDirectory = appDataConfigDirectory;
|
||||
}
|
||||
|
||||
string fileName = Path.Combine(scopeDirectory, configFileName);
|
||||
|
||||
string modulePath = ReadValueFromFile<string>(fileName, "PsModulePath");
|
||||
if (!string.IsNullOrEmpty(modulePath))
|
||||
{
|
||||
modulePath = Environment.ExpandEnvironmentVariables(modulePath);
|
||||
}
|
||||
return modulePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKCU and HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
|
||||
/// Proposed value = Existing default execution policy if not already specified
|
||||
///
|
||||
/// Schema:
|
||||
/// {
|
||||
/// "shell ID string","ExecutionPolicy" : "execution policy string"
|
||||
/// }
|
||||
///
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="scope">Whether this is a system-wide or per-user setting.</param>
|
||||
/// <param name="shellId">The shell associated with this policy. Typically, it is "Microsoft.PowerShell"</param>
|
||||
/// <returns>The execution policy if found. Null otherwise.</returns>
|
||||
internal override string GetExecutionPolicy(PropertyScope scope, string shellId)
|
||||
{
|
||||
string execPolicy = null;
|
||||
string scopeDirectory = psHomeConfigDirectory;
|
||||
|
||||
// Defaults to system wide.
|
||||
if(PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopeDirectory = appDataConfigDirectory;
|
||||
}
|
||||
|
||||
string fileName = Path.Combine(scopeDirectory, configFileName);
|
||||
string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
|
||||
string rawExecPolicy = ReadValueFromFile<string>(fileName, valueName);
|
||||
|
||||
if (!String.IsNullOrEmpty(rawExecPolicy))
|
||||
{
|
||||
execPolicy = rawExecPolicy;
|
||||
}
|
||||
return execPolicy;
|
||||
}
|
||||
|
||||
internal override void RemoveExecutionPolicy(PropertyScope scope, string shellId)
|
||||
{
|
||||
string scopeDirectory = psHomeConfigDirectory;
|
||||
|
||||
// Defaults to system wide.
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopeDirectory = appDataConfigDirectory;
|
||||
}
|
||||
|
||||
string fileName = Path.Combine(scopeDirectory, configFileName);
|
||||
string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
|
||||
RemoveValueFromFile<string>(fileName, valueName);
|
||||
}
|
||||
|
||||
internal override void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
|
||||
{
|
||||
string scopeDirectory = psHomeConfigDirectory;
|
||||
|
||||
// Defaults to system wide.
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopeDirectory = appDataConfigDirectory;
|
||||
}
|
||||
|
||||
string fileName = Path.Combine(scopeDirectory, configFileName);
|
||||
string valueName = string.Concat(shellId, ":", "ExecutionPolicy");
|
||||
WriteValueToFile<string>(fileName, valueName, executionPolicy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
|
||||
/// Proposed value = existing default. Probably "1"
|
||||
///
|
||||
/// Schema:
|
||||
/// {
|
||||
/// "ConsolePrompting" : bool
|
||||
/// }
|
||||
/// </summary>
|
||||
/// <returns>Whether console prompting should happen. If the value cannot be read it defaults to false.</returns>
|
||||
internal override bool GetConsolePrompting()
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
return ReadValueFromFile<bool>(fileName, "ConsolePrompting");
|
||||
}
|
||||
|
||||
internal override void SetConsolePrompting(bool shouldPrompt)
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
WriteValueToFile<bool>(fileName, "ConsolePrompting", shouldPrompt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
|
||||
/// Proposed value = Existing default. Probably "0"
|
||||
///
|
||||
/// Schema:
|
||||
/// {
|
||||
/// "DisablePromptToUpdateHelp" : bool
|
||||
/// }
|
||||
/// </summary>
|
||||
/// <returns>Boolean indicating whether Update-Help should prompt. If the value cannot be read, it defaults to false.</returns>
|
||||
internal override bool GetDisablePromptToUpdateHelp()
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
return ReadValueFromFile<bool>(fileName, "DisablePromptToUpdateHelp");
|
||||
}
|
||||
|
||||
internal override void SetDisablePromptToUpdateHelp(bool prompt)
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
WriteValueToFile<bool>(fileName, "DisablePromptToUpdateHelp", prompt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
|
||||
/// Proposed value = blank.This should be supported though
|
||||
///
|
||||
/// Schema:
|
||||
/// {
|
||||
/// "DefaultSourcePath" : "path to local updatable help location"
|
||||
/// }
|
||||
/// </summary>
|
||||
/// <returns>The source path if found, null otherwise.</returns>
|
||||
internal override string GetDefaultSourcePath()
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
|
||||
string rawExecPolicy = ReadValueFromFile<string>(fileName, "DefaultSourcePath");
|
||||
|
||||
if (!String.IsNullOrEmpty(rawExecPolicy))
|
||||
{
|
||||
return rawExecPolicy;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal override void SetDefaultSourcePath(string defaultPath)
|
||||
{
|
||||
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
|
||||
|
||||
WriteValueToFile<string>(fileName, "DefaultSourcePath", defaultPath);
|
||||
}
|
||||
|
||||
private T ReadValueFromFile<T>(string fileName, string key)
|
||||
{
|
||||
fileLock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
// Open file for reading, but allow multiple readers
|
||||
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (StreamReader streamRdr = new StreamReader(fs))
|
||||
using (JsonTextReader jsonReader = new JsonTextReader(streamRdr))
|
||||
{
|
||||
JObject jsonObject = (JObject) JToken.ReadFrom(jsonReader);
|
||||
JToken value = jsonObject.GetValue(key);
|
||||
if (null != value)
|
||||
{
|
||||
return value.ToObject<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// The file doesn't exist. Treat this the same way as if the
|
||||
// key was not present in the file.
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Should this return success fail or throw?
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="addValue">Whether the key-value pair should be added to or removed from the file</param>
|
||||
private void UpdateValueInFile<T>(string fileName, string key, T value, bool addValue)
|
||||
{
|
||||
fileLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
// 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. It also locks out readers during write
|
||||
// operations.
|
||||
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
JObject jsonObject = null;
|
||||
|
||||
// UTF8, BOM detection, and bufferSize are the same as the basic stream constructor.
|
||||
// The most important parameter here is the last one, which keeps the StreamReader
|
||||
// (and FileStream) open during Dispose so that it can be reused for the write
|
||||
// operation.
|
||||
using (StreamReader streamRdr = new StreamReader(fs, Encoding.UTF8, true, 1024, true))
|
||||
using (JsonTextReader jsonReader = new JsonTextReader(streamRdr))
|
||||
{
|
||||
// Safely determines whether there is content to read from the file
|
||||
bool isReadSuccess = jsonReader.Read();
|
||||
if (isReadSuccess)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
{
|
||||
propertyToModify.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file doesn't already exist and we want to write to it
|
||||
// or it 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)
|
||||
{
|
||||
jsonObject = new JObject(new JProperty(key, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Should this return success, fail, or throw?
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
private void WriteValueToFile<T>(string fileName, string key, T value)
|
||||
{
|
||||
UpdateValueInFile<T>(fileName, key, value, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Should this return success, fail, or throw?
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="key"></param>
|
||||
private void RemoveValueFromFile<T>(string fileName, string key)
|
||||
{
|
||||
UpdateValueInFile<T>(fileName, key, default(T), false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CORECLR
|
||||
|
||||
internal class RegistryAccessor : ConfigPropertyAccessor
|
||||
{
|
||||
private const string DisablePromptToUpdateHelpRegPath = "Software\\Microsoft\\PowerShell";
|
||||
private const string DisablePromptToUpdateHelpRegPath32 = "Software\\Wow6432Node\\Microsoft\\PowerShell";
|
||||
private const string DisablePromptToUpdateHelpRegKey = "DisablePromptToUpdateHelp";
|
||||
private const string DefaultSourcePathRegPath = "Software\\Policies\\Microsoft\\Windows\\PowerShell\\UpdatableHelp";
|
||||
private const string DefaultSourcePathRegKey = "DefaultSourcePath";
|
||||
|
||||
internal RegistryAccessor()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified module path from the appropriate Environment entry in the registry.
|
||||
/// </summary>
|
||||
/// <param name="scope"></param>
|
||||
/// <returns>The specified module path. Null if not present.</returns>
|
||||
internal override string GetModulePath(PropertyScope scope)
|
||||
{
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
return ModuleIntrinsics.GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.User);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ModuleIntrinsics.GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Machine);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="scope"></param>
|
||||
/// <param name="shellId"></param>
|
||||
/// <returns>The execution policy string if found, otherwise null.</returns>
|
||||
internal override string GetExecutionPolicy(PropertyScope scope, string shellId)
|
||||
{
|
||||
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
|
||||
RegistryKey scopedKey = Registry.LocalMachine;
|
||||
|
||||
// Override if set to another value;
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopedKey = Registry.CurrentUser;
|
||||
}
|
||||
|
||||
return GetRegistryString(scopedKey, regKeyName, "ExecutionPolicy");
|
||||
}
|
||||
|
||||
internal override void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
|
||||
{
|
||||
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
|
||||
RegistryKey scopedKey = Registry.LocalMachine;
|
||||
|
||||
// Override if set to another value;
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopedKey = Registry.CurrentUser;
|
||||
}
|
||||
|
||||
using (RegistryKey key = scopedKey.CreateSubKey(regKeyName))
|
||||
{
|
||||
if (null != key)
|
||||
{
|
||||
key.SetValue("ExecutionPolicy", executionPolicy, RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void RemoveExecutionPolicy(PropertyScope scope, string shellId)
|
||||
{
|
||||
string regKeyName = Utils.GetRegistryConfigurationPath(shellId);
|
||||
RegistryKey scopedKey = Registry.LocalMachine;
|
||||
|
||||
// Override if set to another value;
|
||||
if (PropertyScope.CurrentUser == scope)
|
||||
{
|
||||
scopedKey = Registry.CurrentUser;
|
||||
}
|
||||
|
||||
using (RegistryKey key = scopedKey.OpenSubKey(regKeyName, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
if (key.GetValue("ExecutionPolicy") != null)
|
||||
key.DeleteValue("ExecutionPolicy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
|
||||
/// Proposed value = existing default. Probably "1"
|
||||
/// </summary>
|
||||
/// <returns>Whether console prompting should happen.</returns>
|
||||
internal override bool GetConsolePrompting()
|
||||
{
|
||||
string policyKeyName = Utils.GetRegistryConfigurationPrefix();
|
||||
string tempPrompt = GetRegistryString(Registry.LocalMachine, policyKeyName, "ConsolePrompting");
|
||||
|
||||
if (null != tempPrompt)
|
||||
{
|
||||
return Convert.ToBoolean(tempPrompt, CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void SetConsolePrompting(bool shouldPrompt)
|
||||
{
|
||||
string policyKeyName = Utils.GetRegistryConfigurationPrefix();
|
||||
SetRegistryString(Registry.LocalMachine, policyKeyName, "ConsolePrompting", shouldPrompt.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
|
||||
/// Proposed value = Existing default. Probably "0"
|
||||
/// </summary>
|
||||
/// <returns>Boolean indicating whether Update-Help should prompt</returns>
|
||||
internal override bool GetDisablePromptToUpdateHelp()
|
||||
{
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
object disablePromptToUpdateHelp = hklm.GetValue(DisablePromptToUpdateHelpRegKey, null, RegistryValueOptions.None);
|
||||
|
||||
if (disablePromptToUpdateHelp == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int result;
|
||||
|
||||
if (LanguagePrimitives.TryConvertTo<int>(disablePromptToUpdateHelp, out result))
|
||||
{
|
||||
return (result != 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void SetDisablePromptToUpdateHelp(bool prompt)
|
||||
{
|
||||
int valueToSet = prompt ? 1 : 0;
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath, true))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
hklm.SetValue(DisablePromptToUpdateHelpRegKey, valueToSet, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath32, true))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
hklm.SetValue(DisablePromptToUpdateHelpRegKey, valueToSet, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
|
||||
/// Proposed value = blank.This should be supported though
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal override string GetDefaultSourcePath()
|
||||
{
|
||||
return GetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey);
|
||||
}
|
||||
|
||||
internal override void SetDefaultSourcePath(string defaultPath)
|
||||
{
|
||||
SetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey, defaultPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a DWORD from the Registry. Excpetions are intentionally allowed to pass through to
|
||||
/// the caller because different classes and methods within the code base handle Registry
|
||||
/// exceptions differently. Some suppress exceptions and others pass them to the user.
|
||||
/// </summary>
|
||||
/// <param name="rootKey"></param>
|
||||
/// <param name="pathToKey"></param>
|
||||
/// <param name="valueName"></param>
|
||||
/// <returns></returns>
|
||||
private int? GetRegistryDword(RegistryKey rootKey, string pathToKey, string valueName)
|
||||
{
|
||||
using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey))
|
||||
{
|
||||
if (null == regKey)
|
||||
{
|
||||
// Key not found
|
||||
return null;
|
||||
}
|
||||
|
||||
// verify the value kind as a string
|
||||
RegistryValueKind kind = regKey.GetValueKind(valueName);
|
||||
|
||||
if (kind == RegistryValueKind.DWord)
|
||||
{
|
||||
return regKey.GetValue(valueName) as int?;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The function expected a DWORD, but got another type. This is a coding error or a registry key typing error.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excpetions are intentionally allowed to pass through to
|
||||
/// the caller because different classes and methods within the code base handle Registry
|
||||
/// exceptions differently. Some suppress exceptions and others pass them to the user.
|
||||
/// </summary>
|
||||
/// <param name="rootKey"></param>
|
||||
/// <param name="pathToKey"></param>
|
||||
/// <param name="valueName"></param>
|
||||
/// <param name="value"></param>
|
||||
private void SetRegistryDword(RegistryKey rootKey, string pathToKey, string valueName, int value)
|
||||
{
|
||||
using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey))
|
||||
{
|
||||
if (null != regKey)
|
||||
{
|
||||
regKey.SetValue(valueName, value, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excpetions are intentionally allowed to pass through to
|
||||
/// the caller because different classes and methods within the code base handle Registry
|
||||
/// exceptions differently. Some suppress exceptions and others pass them to the user.
|
||||
/// </summary>
|
||||
/// <param name="rootKey"></param>
|
||||
/// <param name="pathToKey"></param>
|
||||
/// <param name="valueName"></param>
|
||||
/// <returns></returns>
|
||||
private string GetRegistryString(RegistryKey rootKey, string pathToKey, string valueName)
|
||||
{
|
||||
using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey))
|
||||
{
|
||||
if (null == regKey)
|
||||
{
|
||||
// Key not found
|
||||
return null;
|
||||
}
|
||||
|
||||
object regValue = regKey.GetValue(valueName);
|
||||
if (null != regValue)
|
||||
{
|
||||
// verify the value kind as a string
|
||||
RegistryValueKind kind = regKey.GetValueKind(valueName);
|
||||
|
||||
if (kind == RegistryValueKind.ExpandString ||
|
||||
kind == RegistryValueKind.String)
|
||||
{
|
||||
return regValue as string;
|
||||
}
|
||||
}
|
||||
|
||||
// The function expected a string, but got another type or the value doesn't exist.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excpetions are intentionally allowed to pass through to
|
||||
/// the caller because different classes and methods within the code base handle Registry
|
||||
/// exceptions differently. Some suppress exceptions and others pass them to the user.
|
||||
/// </summary>
|
||||
/// <param name="rootKey"></param>
|
||||
/// <param name="pathToKey"></param>
|
||||
/// <param name="valueName"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
private void SetRegistryString(RegistryKey rootKey, string pathToKey, string valueName, string value)
|
||||
{
|
||||
using (RegistryKey key = rootKey.CreateSubKey(pathToKey))
|
||||
{
|
||||
if (null != key)
|
||||
{
|
||||
key.SetValue(valueName, value, RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Namespace System.Management.Automation
|
||||
|
||||
@@ -237,24 +237,22 @@ namespace System.Management.Automation
|
||||
/// </exception>
|
||||
internal static string GetApplicationBase(string shellId)
|
||||
{
|
||||
// TODO: #1184 will resolve this work-around
|
||||
// The application base cannot be resolved from the registry for side-by-side versions
|
||||
// of PowerShell.
|
||||
#if !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
|
||||
// This code path applies to Windows FullCLR inbox deployments. All CoreCLR
|
||||
// implementations should use the location of SMA.dll since it must reside in PSHOME.
|
||||
//
|
||||
// try to get the path from the registry first
|
||||
string result = GetApplicationBaseFromRegistry(shellId);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if CORECLR // Use the location of SMA.dll as the application base
|
||||
// Assembly.GetEntryAssembly is not in CoreCLR. GAC is not in CoreCLR.
|
||||
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
|
||||
return Path.GetDirectoryName(assembly.Location);
|
||||
#else
|
||||
// The default keys aren't installed, so try and use the entry assembly to
|
||||
// get the application base. This works for managed apps like minishells...
|
||||
Assembly assem = Assembly.GetEntryAssembly();
|
||||
@@ -281,6 +279,20 @@ namespace System.Management.Automation
|
||||
|
||||
private static string[] s_productFolderDirectories;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the per-user configuration settings directory in a platform agnostic manner.
|
||||
/// Windows Ex:
|
||||
/// %LOCALAPPDATA%\PowerShell
|
||||
/// Non-Windows Ex:
|
||||
/// ~/.config/PowerShell
|
||||
/// </summary>
|
||||
/// <returns>The current user's configuration settings directory</returns>
|
||||
internal static string GetUserSettingsDirectory()
|
||||
{
|
||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
return Path.Combine(appDataPath, "PowerShell");
|
||||
}
|
||||
|
||||
private static string[] GetProductFolderDirectories()
|
||||
{
|
||||
if (s_productFolderDirectories == null)
|
||||
|
||||
@@ -238,12 +238,6 @@ namespace System.Management.Automation.Help
|
||||
/// </summary>
|
||||
internal class UpdatableHelpSystem : IDisposable
|
||||
{
|
||||
internal const string DisablePromptToUpdateHelpRegPath = "Software\\Microsoft\\PowerShell";
|
||||
internal const string DisablePromptToUpdateHelpRegPath32 = "Software\\Wow6432Node\\Microsoft\\PowerShell";
|
||||
internal const string DisablePromptToUpdateHelpRegKey = "DisablePromptToUpdateHelp";
|
||||
internal const string DefaultSourcePathRegPath = "Software\\Policies\\Microsoft\\Windows\\PowerShell\\UpdatableHelp";
|
||||
internal const string DefaultSourcePathRegKey = "DefaultSourcePath";
|
||||
|
||||
#if CORECLR
|
||||
private TimeSpan _defaultTimeout;
|
||||
#else
|
||||
@@ -1601,25 +1595,12 @@ namespace System.Management.Automation.Help
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DefaultSourcePathRegPath))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
object defaultSourcePath = hklm.GetValue(DefaultSourcePathRegKey, null, RegistryValueOptions.None);
|
||||
|
||||
if (defaultSourcePath != null)
|
||||
{
|
||||
return defaultSourcePath as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ConfigPropertyAccessor.Instance.GetDefaultSourcePath();
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1629,21 +1610,7 @@ namespace System.Management.Automation.Help
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath, true))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
hklm.SetValue(DisablePromptToUpdateHelpRegKey, 1, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath32, true))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
hklm.SetValue(DisablePromptToUpdateHelpRegKey, 1, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
ConfigPropertyAccessor.Instance.SetDisablePromptToUpdateHelp(true);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
@@ -1668,33 +1635,7 @@ namespace System.Management.Automation.Help
|
||||
return false;
|
||||
}
|
||||
|
||||
using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath))
|
||||
{
|
||||
if (hklm != null)
|
||||
{
|
||||
object disablePromptToUpdateHelp = hklm.GetValue(DisablePromptToUpdateHelpRegKey, null, RegistryValueOptions.None);
|
||||
|
||||
if (disablePromptToUpdateHelp == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int result;
|
||||
|
||||
if (LanguagePrimitives.TryConvertTo<int>(disablePromptToUpdateHelp, out result))
|
||||
{
|
||||
return (result != 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ConfigPropertyAccessor.Instance.GetDisablePromptToUpdateHelp();
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
|
||||
"Microsoft.CSharp": "4.0.1",
|
||||
"Microsoft.Win32.Registry.AccessControl": "4.0.0",
|
||||
"Newtonsoft.Json": "7.0.1",
|
||||
"System.Collections.Specialized": "4.0.1",
|
||||
"System.Collections.NonGeneric": "4.0.1",
|
||||
"System.ComponentModel.EventBasedAsync": "4.0.11",
|
||||
|
||||
@@ -146,7 +146,6 @@ namespace System.Management.Automation.Internal
|
||||
#else
|
||||
string executionPolicy = "Restricted";
|
||||
string preferenceKey = Utils.GetRegistryConfigurationPath(shellId);
|
||||
const string PolicyKeyValueName = "ExecutionPolicy";
|
||||
|
||||
switch (policy)
|
||||
{
|
||||
@@ -179,25 +178,13 @@ namespace System.Management.Automation.Internal
|
||||
// They want to remove it
|
||||
if (policy == ExecutionPolicy.Undefined)
|
||||
{
|
||||
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(preferenceKey, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
if (key.GetValue(PolicyKeyValueName) != null)
|
||||
key.DeleteValue(PolicyKeyValueName);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
|
||||
CleanKeyParents(Registry.CurrentUser, preferenceKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(preferenceKey))
|
||||
{
|
||||
key.SetValue(PolicyKeyValueName, executionPolicy, RegistryValueKind.String);
|
||||
ConfigPropertyAccessor.Instance.SetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId, executionPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -206,25 +193,13 @@ namespace System.Management.Automation.Internal
|
||||
// They want to remove it
|
||||
if (policy == ExecutionPolicy.Undefined)
|
||||
{
|
||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(preferenceKey, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
if (key.GetValue(PolicyKeyValueName) != null)
|
||||
key.DeleteValue(PolicyKeyValueName);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
|
||||
CleanKeyParents(Registry.LocalMachine, preferenceKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (RegistryKey key = Registry.LocalMachine.CreateSubKey(preferenceKey))
|
||||
{
|
||||
key.SetValue(PolicyKeyValueName, executionPolicy, RegistryValueKind.String);
|
||||
ConfigPropertyAccessor.Instance.SetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId, executionPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -235,6 +210,10 @@ namespace System.Management.Automation.Internal
|
||||
// contain at most a single child
|
||||
private static void CleanKeyParents(RegistryKey baseKey, string keyPath)
|
||||
{
|
||||
#if CORECLR
|
||||
// if ( ! Platform.Inbox) // Modify this to support registry checks for inbox CoreCLR
|
||||
return;
|
||||
#else // Windows && FullCLR
|
||||
using (RegistryKey key = baseKey.OpenSubKey(keyPath, true))
|
||||
{
|
||||
// Verify the child key has no children
|
||||
@@ -269,6 +248,7 @@ namespace System.Management.Automation.Internal
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static ExecutionPolicy GetExecutionPolicy(string shellId)
|
||||
@@ -311,6 +291,8 @@ namespace System.Management.Automation.Internal
|
||||
return ExecutionPolicy.Undefined;
|
||||
}
|
||||
|
||||
// TODO: Group Policy is only supported on Full systems, but !LINUX && CORECLR
|
||||
// will run there as well, so I don't think we should remove it.
|
||||
case ExecutionPolicyScope.UserPolicy:
|
||||
case ExecutionPolicyScope.MachinePolicy:
|
||||
{
|
||||
@@ -604,48 +586,21 @@ namespace System.Management.Automation.Internal
|
||||
/// <returns>NULL if it is not defined at this level</returns>
|
||||
private static string GetLocalPreferenceValue(string shellId, ExecutionPolicyScope scope)
|
||||
{
|
||||
const string PolicyValueName = "ExecutionPolicy";
|
||||
string LocalPreferenceKey = Utils.GetRegistryConfigurationPath(shellId);
|
||||
|
||||
switch (scope)
|
||||
{
|
||||
// 1: Look up the current-user preference
|
||||
case ExecutionPolicyScope.CurrentUser:
|
||||
{
|
||||
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(LocalPreferenceKey))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
object temp = key.GetValue(PolicyValueName);
|
||||
string policy = temp as string;
|
||||
key.Dispose();
|
||||
return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
|
||||
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
|
||||
// 1: Look up the system-wide preference
|
||||
// 2: Look up the system-wide preference
|
||||
case ExecutionPolicyScope.LocalMachine:
|
||||
{
|
||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(LocalPreferenceKey))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
object temp = key.GetValue(PolicyValueName);
|
||||
string policy = temp as string;
|
||||
key.Dispose();
|
||||
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion execution policy
|
||||
#endregion execution policy
|
||||
|
||||
/// <summary>
|
||||
/// throw if file does not exist
|
||||
|
||||
@@ -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 )
|
||||
|
||||
#
|
||||
|
||||
@@ -11,14 +11,12 @@ add_library(pwrshcommon
|
||||
target_include_directories(pwrshcommon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if (BUILD_ONECORE)
|
||||
message("Building OneCore version of pwrshcommon.lib")
|
||||
# Libraries to use when creating this binary for Windows on OneCore-based SKUs
|
||||
set(PWRSHCOMMON_WINDOWS_LIBS
|
||||
# onecore.lib
|
||||
)
|
||||
set_target_properties(pwrshcommon PROPERTIES COMPILE_DEFINITIONS "CORECLR")
|
||||
else () # NOT BUILD_ONECORE
|
||||
message("Building Full version of pwrshcommon.lib")
|
||||
# Libraries to use when creating this binary for Windows on full SKUs
|
||||
# Note: The appropriate libs get added automatically by VS
|
||||
set(PWRSHCOMMON_WINDOWS_LIBS
|
||||
|
||||
Reference in new issue
Block a user