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 ad44e0e92..dd850d1c8 100644
--- a/build.psm1
+++ b/build.psm1
@@ -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"
}
diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
index bff625594..1bf437fd4 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
+++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs
@@ -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
}
diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj
index bd8f4e67c..51ab6aaf7 100644
--- a/src/System.Management.Automation/System.Management.Automation.csproj
+++ b/src/System.Management.Automation/System.Management.Automation.csproj
@@ -390,6 +390,7 @@
+
diff --git a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
index a1a353766..5f205bce6 100644
--- a/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
+++ b/src/System.Management.Automation/engine/Modules/ModuleIntrinsics.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);
@@ -929,7 +929,7 @@ namespace System.Management.Automation
if (processedPath != null)
yield return processedPath;
}
- }
+ }
if (includeSystemModulePath)
{
diff --git a/src/System.Management.Automation/engine/PropertyAccessor.cs b/src/System.Management.Automation/engine/PropertyAccessor.cs
new file mode 100644
index 000000000..6a63302ad
--- /dev/null
+++ b/src/System.Management.Automation/engine/PropertyAccessor.cs
@@ -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
+{
+
+ ///
+ /// 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 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.
+ /// CurrentUser properties apply to the current user that is impersonated.
+ ///
+ internal enum PropertyScope
+ {
+ SystemWide = 0,
+ CurrentUser = 1
+ }
+
+ #endregion // Enums
+
+ #region Interface Methods
+
+ ///
+ /// 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.
+ ///
+ /// Module path values from the config file.
+ internal abstract string GetModulePath(PropertyScope scope);
+
+ ///
+ /// Existing Key = HKCU and HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
+ /// Proposed value = Existing default execution policy if not already specified
+ ///
+ /// Where it should check for the value.
+ /// The shell associated with this policy. Typically, it is "Microsoft.PowerShell"
+ ///
+ 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
+ /// Proposed value = existing default. Probably "1"
+ ///
+ /// Whether console prompting should happen.
+ internal abstract bool GetConsolePrompting();
+ internal abstract void SetConsolePrompting(bool shouldPrompt);
+
+ ///
+ /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
+ /// Proposed value = Existing default. Probably "0"
+ ///
+ /// Boolean indicating whether Update-Help should prompt
+ internal abstract bool GetDisablePromptToUpdateHelp();
+ internal abstract void SetDisablePromptToUpdateHelp(bool prompt);
+
+ ///
+ /// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
+ /// Proposed value = blank.This should be supported though
+ ///
+ ///
+ internal abstract string GetDefaultSourcePath();
+ internal abstract void SetDefaultSourcePath(string defaultPath);
+
+ #endregion // Interface Methods
+ }
+
+#if CORECLR
+ ///
+ /// JSON configuration file accessor
+ ///
+ /// Reads from and writes to configuration files. The values stored were
+ /// originally stored in the Windows registry.
+ ///
+ internal class JsonConfigFileAccessor : ConfigPropertyAccessor
+ {
+ private string psHomeConfigDirectory;
+ private string appDataConfigDirectory;
+ private const string configDirectoryName = "Configuration";
+ private const string configFileName = "PowerShellProperties.json";
+
+ ///
+ /// 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.
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// This value is not writable via the API and must be set using a text editor.
+ ///
+ ///
+ /// Value if found, null otherwise. The behavior matches ModuleIntrinsics.GetExpandedEnvironmentVariable().
+ 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(fileName, "PsModulePath");
+ if (!string.IsNullOrEmpty(modulePath))
+ {
+ modulePath = Environment.ExpandEnvironmentVariables(modulePath);
+ }
+ return modulePath;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// 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 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(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(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(fileName, valueName, executionPolicy);
+ }
+
+ ///
+ /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
+ /// Proposed value = existing default. Probably "1"
+ ///
+ /// Schema:
+ /// {
+ /// "ConsolePrompting" : bool
+ /// }
+ ///
+ /// Whether console prompting should happen. If the value cannot be read it defaults to false.
+ internal override bool GetConsolePrompting()
+ {
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
+ return ReadValueFromFile(fileName, "ConsolePrompting");
+ }
+
+ internal override void SetConsolePrompting(bool shouldPrompt)
+ {
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
+ WriteValueToFile(fileName, "ConsolePrompting", shouldPrompt);
+ }
+
+ ///
+ /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
+ /// Proposed value = Existing default. Probably "0"
+ ///
+ /// Schema:
+ /// {
+ /// "DisablePromptToUpdateHelp" : bool
+ /// }
+ ///
+ /// 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, configFileName);
+ return ReadValueFromFile(fileName, "DisablePromptToUpdateHelp");
+ }
+
+ internal override void SetDisablePromptToUpdateHelp(bool prompt)
+ {
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
+ WriteValueToFile(fileName, "DisablePromptToUpdateHelp", prompt);
+ }
+
+ ///
+ /// 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"
+ /// }
+ ///
+ /// The source path if found, null otherwise.
+ internal override string GetDefaultSourcePath()
+ {
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
+
+ string rawExecPolicy = ReadValueFromFile(fileName, "DefaultSourcePath");
+
+ if (!String.IsNullOrEmpty(rawExecPolicy))
+ {
+ return rawExecPolicy;
+ }
+ return null;
+ }
+
+ internal override void SetDefaultSourcePath(string defaultPath)
+ {
+ string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
+
+ WriteValueToFile(fileName, "DefaultSourcePath", defaultPath);
+ }
+
+ private T ReadValueFromFile(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();
+ }
+ }
+ }
+ 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);
+ }
+
+ ///
+ /// TODO: Should this return success fail or throw?
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 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)
+ {
+ 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();
+ }
+ }
+
+ ///
+ /// TODO: Should this return success, fail, or throw?
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void WriteValueToFile(string fileName, string key, T value)
+ {
+ UpdateValueInFile(fileName, key, value, true);
+ }
+
+ ///
+ /// TODO: Should this return success, fail, or throw?
+ ///
+ ///
+ ///
+ ///
+ private void RemoveValueFromFile(string fileName, string key)
+ {
+ UpdateValueInFile(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()
+ {
+ }
+
+ ///
+ /// Gets the specified module path from the appropriate Environment entry in the registry.
+ ///
+ ///
+ /// The specified module path. Null if not present.
+ internal override string GetModulePath(PropertyScope scope)
+ {
+ if (PropertyScope.CurrentUser == scope)
+ {
+ return ModuleIntrinsics.GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.User);
+ }
+ else
+ {
+ return ModuleIntrinsics.GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Machine);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// The execution policy string if found, otherwise null.
+ 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");
+ }
+ }
+ }
+
+ ///
+ /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
+ /// Proposed value = existing default. Probably "1"
+ ///
+ /// Whether console prompting should happen.
+ 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());
+ }
+
+ ///
+ /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
+ /// Proposed value = Existing default. Probably "0"
+ ///
+ /// Boolean indicating whether Update-Help should prompt
+ 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(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);
+ }
+ }
+ }
+
+ ///
+ /// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
+ /// Proposed value = blank.This should be supported though
+ ///
+ ///
+ internal override string GetDefaultSourcePath()
+ {
+ return GetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey);
+ }
+
+ internal override void SetDefaultSourcePath(string defaultPath)
+ {
+ SetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey, defaultPath);
+ }
+
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+ }
+ }
+
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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);
+ }
+ }
+ }
+
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+ }
+
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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
+
diff --git a/src/System.Management.Automation/engine/Utils.cs b/src/System.Management.Automation/engine/Utils.cs
index 8fb2d8b04..3ba32c7bf 100644
--- a/src/System.Management.Automation/engine/Utils.cs
+++ b/src/System.Management.Automation/engine/Utils.cs
@@ -237,24 +237,22 @@ namespace System.Management.Automation
///
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;
+ ///
+ /// Specifies the per-user configuration settings directory in a platform agnostic manner.
+ /// 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");
+ }
+
private static string[] GetProductFolderDirectories()
{
if (s_productFolderDirectories == null)
diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs
index fc7111cbc..ad7d4c866 100644
--- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs
+++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs
@@ -238,12 +238,6 @@ namespace System.Management.Automation.Help
///
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;
}
///
@@ -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(disablePromptToUpdateHelp, out result))
- {
- return (result != 1);
- }
-
- return true;
- }
- }
- else
- {
- return true;
- }
- }
+ return ConfigPropertyAccessor.Instance.GetDisablePromptToUpdateHelp();
}
catch (SecurityException)
{
diff --git a/src/System.Management.Automation/project.json b/src/System.Management.Automation/project.json
index 0d6ee12b6..f60feb16c 100644
--- a/src/System.Management.Automation/project.json
+++ b/src/System.Management.Automation/project.json
@@ -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",
diff --git a/src/System.Management.Automation/security/SecuritySupport.cs b/src/System.Management.Automation/security/SecuritySupport.cs
index 9da5da10e..f2ec5051a 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);
- const string PolicyKeyValueName = "ExecutionPolicy";
switch (policy)
{
@@ -166,67 +165,43 @@ 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)
- {
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey(preferenceKey, true))
- {
- if (key != null)
- {
- if (key.GetValue(PolicyKeyValueName) != null)
- key.DeleteValue(PolicyKeyValueName);
- }
- }
-
- CleanKeyParents(Registry.CurrentUser, preferenceKey);
- }
- else
- {
- using (RegistryKey key = Registry.CurrentUser.CreateSubKey(preferenceKey))
- {
- key.SetValue(PolicyKeyValueName, executionPolicy, RegistryValueKind.String);
- }
- }
-
- 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)
- {
- using (RegistryKey key = Registry.LocalMachine.OpenSubKey(preferenceKey, true))
- {
- if (key != null)
- {
- if (key.GetValue(PolicyKeyValueName) != null)
- key.DeleteValue(PolicyKeyValueName);
- }
- }
-
- CleanKeyParents(Registry.LocalMachine, preferenceKey);
- }
- else
- {
- using (RegistryKey key = Registry.LocalMachine.CreateSubKey(preferenceKey))
- {
- key.SetValue(PolicyKeyValueName, executionPolicy, RegistryValueKind.String);
- }
- }
-
- break;
+ ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
+ CleanKeyParents(Registry.LocalMachine, preferenceKey);
}
+ else
+ {
+ ConfigPropertyAccessor.Instance.SetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId, executionPolicy);
+ }
+ break;
+ }
}
#endif
}
@@ -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
/// NULL if it is not defined at this level
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
///
/// throw if file does not exist
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 )
#
diff --git a/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt b/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt
index 24fd4afe4..d8170fa41 100644
--- a/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt
+++ b/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt
@@ -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