mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 04:36:39 +00:00
Merge pull request #1721 from PowerShell/dongbo/module-path
Address the side-by-side module path for OPS
This commit is contained in:
commit
539c59cc35
23 files changed
+506
-292
No files matched your search
@@ -79,12 +79,13 @@ sudo installer -pkg powershell-6.0.0-alpha.8-osx.10.11-x64.pkg -target /
|
|||||||
Paths
|
Paths
|
||||||
=====
|
=====
|
||||||
|
|
||||||
* User profiles will be read from `~/.config/powershell/profile.ps1`.
|
|
||||||
* User modules will be read from `~/.local/share/powershell/Modules`
|
|
||||||
* PSReadLine history will be recorded to `~/.local/share/powershell/PSReadLine/ConsoleHost_history.txt`
|
|
||||||
* `$PSHOME` is `/opt/microsoft/powershell/6.0.0-alpha.8/`
|
* `$PSHOME` is `/opt/microsoft/powershell/6.0.0-alpha.8/`
|
||||||
* Default profiles will be read from `$PSHOME/profile.ps1`.
|
* User profiles will be read from `~/.config/powershell/profile.ps1`
|
||||||
|
* Default profiles will be read from `$PSHOME/profile.ps1`
|
||||||
|
* User modules will be read from `~/.local/share/powershell/Modules`
|
||||||
|
* Shared modules will be read from `/usr/local/share/powershell/Modules`
|
||||||
* Default modules will be read from `$PSHOME/Modules`
|
* Default modules will be read from `$PSHOME/Modules`
|
||||||
|
* PSReadLine history will be recorded to `~/.local/share/powershell/PSReadLine/ConsoleHost_history.txt`
|
||||||
|
|
||||||
The profiles respect PowerShell's per-host configuration,
|
The profiles respect PowerShell's per-host configuration,
|
||||||
so the default host-specific profiles exists at `Microsoft.PowerShell_profile.ps1` in the same locations.
|
so the default host-specific profiles exists at `Microsoft.PowerShell_profile.ps1` in the same locations.
|
||||||
|
|||||||
@@ -179,21 +179,17 @@ namespace Microsoft.PowerShell
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
string profileDir;
|
string profileDir;
|
||||||
if (Platform.IsWindows)
|
#if UNIX
|
||||||
{
|
profileDir = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE);
|
||||||
profileDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) +
|
#else
|
||||||
@"\Microsoft\Windows\PowerShell";
|
profileDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) +
|
||||||
|
@"\Microsoft\Windows\PowerShell";
|
||||||
|
|
||||||
if (!Directory.Exists(profileDir))
|
if (!Directory.Exists(profileDir))
|
||||||
{
|
|
||||||
Directory.CreateDirectory(profileDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
profileDir = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE);
|
Directory.CreateDirectory(profileDir);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ClrFacade.SetProfileOptimizationRoot(profileDir);
|
ClrFacade.SetProfileOptimizationRoot(profileDir);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|||||||
@@ -741,6 +741,7 @@ namespace System.Management.Automation
|
|||||||
#endregion Reflection and Type related extensions
|
#endregion Reflection and Type related extensions
|
||||||
|
|
||||||
#region Environment Extensions
|
#region Environment Extensions
|
||||||
|
|
||||||
// TODO:CORECLR - Environment Extensions need serious work to refine.
|
// TODO:CORECLR - Environment Extensions need serious work to refine.
|
||||||
internal enum EnvironmentVariableTarget
|
internal enum EnvironmentVariableTarget
|
||||||
{
|
{
|
||||||
@@ -824,37 +825,7 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
public static string GetEnvironmentVariable(string variable)
|
public static string GetEnvironmentVariable(string variable)
|
||||||
{
|
{
|
||||||
string value = System.Environment.GetEnvironmentVariable(variable);
|
return System.Environment.GetEnvironmentVariable(variable);
|
||||||
|
|
||||||
// Porting note: if not otherwise defined, map Windows environment
|
|
||||||
// variables to their corresponding Linux counterparts
|
|
||||||
if (!Platform.IsWindows && String.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
switch (variable)
|
|
||||||
{
|
|
||||||
case "OS":
|
|
||||||
return "Linux";
|
|
||||||
|
|
||||||
case "COMPUTERNAME":
|
|
||||||
return System.Environment.GetEnvironmentVariable("HOSTNAME");
|
|
||||||
|
|
||||||
case "USERNAME":
|
|
||||||
return System.Environment.GetEnvironmentVariable("USER");
|
|
||||||
|
|
||||||
case "HOMEPATH":
|
|
||||||
case "USERPROFILE":
|
|
||||||
return System.Environment.GetEnvironmentVariable("HOME");
|
|
||||||
|
|
||||||
case "TMP":
|
|
||||||
case "TEMP":
|
|
||||||
return System.Environment.GetEnvironmentVariable("TMPDIR");
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDictionary GetEnvironmentVariables()
|
public static IDictionary GetEnvironmentVariables()
|
||||||
@@ -896,7 +867,6 @@ namespace System.Management.Automation
|
|||||||
#if UNIX
|
#if UNIX
|
||||||
return null;
|
return null;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if( target == EnvironmentVariableTarget.Machine)
|
if( target == EnvironmentVariableTarget.Machine)
|
||||||
{
|
{
|
||||||
using (RegistryKey environmentKey =
|
using (RegistryKey environmentKey =
|
||||||
@@ -957,7 +927,6 @@ namespace System.Management.Automation
|
|||||||
#if UNIX
|
#if UNIX
|
||||||
return null;
|
return null;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (target == EnvironmentVariableTarget.Machine)
|
if (target == EnvironmentVariableTarget.Machine)
|
||||||
{
|
{
|
||||||
using (RegistryKey environmentKey =
|
using (RegistryKey environmentKey =
|
||||||
@@ -986,31 +955,6 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
#region Property_Extensions
|
#region Property_Extensions
|
||||||
|
|
||||||
internal static string WinGetUserDomainName()
|
|
||||||
{
|
|
||||||
StringBuilder domainName = new StringBuilder(1024);
|
|
||||||
uint domainNameLen = (uint)domainName.Capacity;
|
|
||||||
|
|
||||||
byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
|
|
||||||
if (ret == 1)
|
|
||||||
{
|
|
||||||
string samName = domainName.ToString();
|
|
||||||
int index = samName.IndexOf('\\');
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
return samName.Substring(0, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int errorCode = Marshal.GetLastWin32Error();
|
|
||||||
throw new InvalidOperationException(Win32Native.GetMessage(errorCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cannot use LookupAccountNameW to get DomainName because 'GetUserName' is not available in CSS and thus we cannot get the account.
|
|
||||||
throw new InvalidOperationException(CoreClrStubResources.CannotGetDomainName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UserDomainName
|
/// UserDomainName
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1018,15 +962,11 @@ namespace System.Management.Automation
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Platform.IsWindows)
|
#if UNIX
|
||||||
{
|
return Platform.NonWindowsGetDomainName();
|
||||||
return WinGetUserDomainName();
|
#else
|
||||||
}
|
return WinGetUserDomainName();
|
||||||
else
|
#endif
|
||||||
{
|
|
||||||
return Platform.NonWindowsGetDomainName();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,20 +980,7 @@ namespace System.Management.Automation
|
|||||||
#if UNIX
|
#if UNIX
|
||||||
return Platform.Unix.UserName;
|
return Platform.Unix.UserName;
|
||||||
#else
|
#else
|
||||||
StringBuilder domainName = new StringBuilder(1024);
|
return WinGetUserName();
|
||||||
uint domainNameLen = (uint)domainName.Capacity;
|
|
||||||
|
|
||||||
byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
|
|
||||||
if (ret == 1)
|
|
||||||
{
|
|
||||||
string samName = domainName.ToString();
|
|
||||||
int index = samName.IndexOf('\\');
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
return samName.Substring(index + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1078,45 +1005,19 @@ namespace System.Management.Automation
|
|||||||
{
|
{
|
||||||
if (s_os == null)
|
if (s_os == null)
|
||||||
{
|
{
|
||||||
if (Platform.IsWindows)
|
#if UNIX
|
||||||
{
|
// TODO:PSL use P/Invoke to provide proper version
|
||||||
s_os = WinOSVersion;
|
// OSVersion will be back in CoreCLR 1.1
|
||||||
}
|
s_os = new Environment.OperatingSystem(new Version(1, 0, 0, 0), "");
|
||||||
else
|
#else
|
||||||
{
|
s_os = WinGetOSVersion();
|
||||||
// TODO:PSL use P/Invoke to provide proper version
|
#endif
|
||||||
|
|
||||||
// Porting note: cannot put this in CorePsPlatform since
|
|
||||||
// System.Management.Automation.Environment only exists in CoreCLR
|
|
||||||
// builds of monad.
|
|
||||||
s_os = new Environment.OperatingSystem(new Version(1, 0, 0, 0), "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return s_os;
|
return s_os;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static volatile OperatingSystem s_os;
|
private static volatile OperatingSystem s_os;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Windows OSVersion implementation
|
|
||||||
/// </summary>
|
|
||||||
private static OperatingSystem WinOSVersion
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Win32Native.OSVERSIONINFOEX osviex = new Win32Native.OSVERSIONINFOEX();
|
|
||||||
osviex.OSVersionInfoSize = Marshal.SizeOf(osviex);
|
|
||||||
if (!Win32Native.GetVersionEx(ref osviex))
|
|
||||||
{
|
|
||||||
int errorCode = Marshal.GetLastWin32Error();
|
|
||||||
throw new Win32Exception(errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Version v = new Version(osviex.MajorVersion, osviex.MinorVersion, osviex.BuildNumber, (osviex.ServicePackMajor << 16) | osviex.ServicePackMinor);
|
|
||||||
return new OperatingSystem(v, osviex.CSDVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Property_Extensions
|
#endregion Property_Extensions
|
||||||
|
|
||||||
#region SpecialFolder_Extensions
|
#region SpecialFolder_Extensions
|
||||||
@@ -1242,13 +1143,79 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
#endregion SpecialFolder_Extensions
|
#endregion SpecialFolder_Extensions
|
||||||
|
|
||||||
#region NativeMethods
|
#region WinPlatform_Specific_Methods
|
||||||
|
#if !UNIX
|
||||||
|
/// <summary>
|
||||||
|
/// Windows UserDomainName implementation
|
||||||
|
/// </summary>
|
||||||
|
private static string WinGetUserDomainName()
|
||||||
|
{
|
||||||
|
StringBuilder domainName = new StringBuilder(1024);
|
||||||
|
uint domainNameLen = (uint)domainName.Capacity;
|
||||||
|
|
||||||
|
byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
|
string samName = domainName.ToString();
|
||||||
|
int index = samName.IndexOf('\\');
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
return samName.Substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int errorCode = Marshal.GetLastWin32Error();
|
||||||
|
throw new InvalidOperationException(Win32Native.GetMessage(errorCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot use LookupAccountNameW to get DomainName because 'GetUserName' is not available in CSS and thus we cannot get the account.
|
||||||
|
throw new InvalidOperationException(CoreClrStubResources.CannotGetDomainName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Windows UserName implementation
|
||||||
|
/// </summary>
|
||||||
|
private static string WinGetUserName()
|
||||||
|
{
|
||||||
|
StringBuilder domainName = new StringBuilder(1024);
|
||||||
|
uint domainNameLen = (uint)domainName.Capacity;
|
||||||
|
|
||||||
|
byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
|
string samName = domainName.ToString();
|
||||||
|
int index = samName.IndexOf('\\');
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
return samName.Substring(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Windows OSVersion implementation
|
||||||
|
/// </summary>
|
||||||
|
private static OperatingSystem WinGetOSVersion()
|
||||||
|
{
|
||||||
|
Win32Native.OSVERSIONINFOEX osviex = new Win32Native.OSVERSIONINFOEX();
|
||||||
|
osviex.OSVersionInfoSize = Marshal.SizeOf(osviex);
|
||||||
|
if (!Win32Native.GetVersionEx(ref osviex))
|
||||||
|
{
|
||||||
|
int errorCode = Marshal.GetLastWin32Error();
|
||||||
|
throw new Win32Exception(errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Version v = new Version(osviex.MajorVersion, osviex.MinorVersion, osviex.BuildNumber, (osviex.ServicePackMajor << 16) | osviex.ServicePackMinor);
|
||||||
|
return new OperatingSystem(v, osviex.CSDVersion);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DllImport uses the ApiSet dll that is available on CSS, since this code
|
/// DllImport uses the ApiSet dll that is available on CSS, since this code
|
||||||
/// will only be included when building targeting CoreCLR.
|
/// will only be included when building targeting CoreCLR.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class Win32Native
|
private static class Win32Native
|
||||||
{
|
{
|
||||||
internal const int NameSamCompatible = 2; // EXTENDED_NAME_FORMAT - NameSamCompatible
|
internal const int NameSamCompatible = 2; // EXTENDED_NAME_FORMAT - NameSamCompatible
|
||||||
|
|
||||||
@@ -1307,8 +1274,8 @@ namespace System.Management.Automation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion NativeMethods
|
#endregion WinPlatform_Specific_Methods
|
||||||
|
|
||||||
#region NestedTypes
|
#region NestedTypes
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,7 @@
|
|||||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
--********************************************************************/
|
--********************************************************************/
|
||||||
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
@@ -81,6 +75,105 @@ namespace System.Management.Automation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the underlying system is NanoServer.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsNanoServer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if !CORECLR
|
||||||
|
return false;
|
||||||
|
#elif UNIX
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (_isNanoServer.HasValue) { return _isNanoServer.Value; }
|
||||||
|
|
||||||
|
_isNanoServer = false;
|
||||||
|
using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"))
|
||||||
|
{
|
||||||
|
if (regKey != null)
|
||||||
|
{
|
||||||
|
object value = regKey.GetValue("NanoServer");
|
||||||
|
if (value != null && regKey.GetValueKind("NanoServer") == RegistryValueKind.DWord)
|
||||||
|
{
|
||||||
|
_isNanoServer = (int)value == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _isNanoServer.Value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the underlying system is IoT.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsIoT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if !CORECLR
|
||||||
|
return false;
|
||||||
|
#elif UNIX
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (_isIoT.HasValue) { return _isIoT.Value; }
|
||||||
|
|
||||||
|
_isIoT = false;
|
||||||
|
using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
|
||||||
|
{
|
||||||
|
if (regKey != null)
|
||||||
|
{
|
||||||
|
object value = regKey.GetValue("ProductName");
|
||||||
|
if (value != null && regKey.GetValueKind("ProductName") == RegistryValueKind.String)
|
||||||
|
{
|
||||||
|
_isIoT = string.Equals("IoTUAP", (string)value, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _isIoT.Value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CORECLR
|
||||||
|
/// <summary>
|
||||||
|
/// True if it is the inbox powershell for NanoServer or IoT.
|
||||||
|
/// </summary>
|
||||||
|
internal static bool IsInbox
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if UNIX
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (_isInbox.HasValue) { return _isInbox.Value; }
|
||||||
|
|
||||||
|
_isInbox = false;
|
||||||
|
if (IsNanoServer || IsIoT)
|
||||||
|
{
|
||||||
|
_isInbox = string.Equals(
|
||||||
|
Utils.GetApplicationBase(Utils.DefaultPowerShellShellID),
|
||||||
|
Utils.GetApplicationBaseFromRegistry(Utils.DefaultPowerShellShellID),
|
||||||
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _isInbox.Value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !UNIX
|
||||||
|
private static bool? _isNanoServer = null;
|
||||||
|
private static bool? _isIoT = null;
|
||||||
|
private static bool? _isInbox = null;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// format files
|
// format files
|
||||||
internal static List<string> FormatFileNames = new List<string>
|
internal static List<string> FormatFileNames = new List<string>
|
||||||
{
|
{
|
||||||
@@ -97,6 +190,20 @@ namespace System.Management.Automation
|
|||||||
"WSMan.format.ps1xml"
|
"WSMan.format.ps1xml"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Some common environment variables used in PS have different
|
||||||
|
/// names in different OS platforms
|
||||||
|
/// </summary>
|
||||||
|
internal static class CommonEnvVariableNames
|
||||||
|
{
|
||||||
|
#if UNIX
|
||||||
|
internal const string Home = "HOME";
|
||||||
|
#else
|
||||||
|
internal const string Home = "USERPROFILE";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNIX
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// X Desktop Group configuration type enum.
|
/// X Desktop Group configuration type enum.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -109,7 +216,9 @@ namespace System.Management.Automation
|
|||||||
/// <summary> XDG_DATA_HOME/powershell </summary>
|
/// <summary> XDG_DATA_HOME/powershell </summary>
|
||||||
DATA,
|
DATA,
|
||||||
/// <summary> XDG_DATA_HOME/powershell/Modules </summary>
|
/// <summary> XDG_DATA_HOME/powershell/Modules </summary>
|
||||||
MODULES,
|
USER_MODULES,
|
||||||
|
/// <summary> /usr/local/share/powershell/Modules </summary>
|
||||||
|
SHARED_MODULES,
|
||||||
/// <summary> XDG_CONFIG_HOME/powershell </summary>
|
/// <summary> XDG_CONFIG_HOME/powershell </summary>
|
||||||
DEFAULT
|
DEFAULT
|
||||||
}
|
}
|
||||||
@@ -160,7 +269,7 @@ namespace System.Management.Automation
|
|||||||
return Path.Combine(xdgdatahome, "powershell");
|
return Path.Combine(xdgdatahome, "powershell");
|
||||||
}
|
}
|
||||||
|
|
||||||
case Platform.XDG_Type.MODULES:
|
case Platform.XDG_Type.USER_MODULES:
|
||||||
//the user has set XDG_DATA_HOME corresponding to module path
|
//the user has set XDG_DATA_HOME corresponding to module path
|
||||||
if (String.IsNullOrEmpty(xdgdatahome))
|
if (String.IsNullOrEmpty(xdgdatahome))
|
||||||
{
|
{
|
||||||
@@ -176,6 +285,9 @@ namespace System.Management.Automation
|
|||||||
return Path.Combine(xdgdatahome, "powershell", "Modules");
|
return Path.Combine(xdgdatahome, "powershell", "Modules");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Platform.XDG_Type.SHARED_MODULES:
|
||||||
|
return "/usr/local/share/powershell/Modules";
|
||||||
|
|
||||||
case Platform.XDG_Type.CACHE:
|
case Platform.XDG_Type.CACHE:
|
||||||
//the user has set XDG_CACHE_HOME
|
//the user has set XDG_CACHE_HOME
|
||||||
if (String.IsNullOrEmpty(xdgcachehome))
|
if (String.IsNullOrEmpty(xdgcachehome))
|
||||||
@@ -221,6 +333,7 @@ namespace System.Management.Automation
|
|||||||
return xdgConfigHomeDefault;
|
return xdgConfigHomeDefault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Platform methods prefixed NonWindows are:
|
// Platform methods prefixed NonWindows are:
|
||||||
// - non-windows by the definition of the IsWindows method above
|
// - non-windows by the definition of the IsWindows method above
|
||||||
|
|||||||
@@ -1548,7 +1548,7 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
if (_pathCacheKey != null)
|
if (_pathCacheKey != null)
|
||||||
{
|
{
|
||||||
string[] tokenizedPath = _pathCacheKey.Split(new char[] { System.IO.Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);
|
string[] tokenizedPath = _pathCacheKey.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||||
_cachedPath = new Collection<string>();
|
_cachedPath = new Collection<string>();
|
||||||
|
|
||||||
foreach (string directory in tokenizedPath)
|
foreach (string directory in tokenizedPath)
|
||||||
@@ -1633,7 +1633,7 @@ namespace System.Management.Automation
|
|||||||
lock (s_lockObject)
|
lock (s_lockObject)
|
||||||
{
|
{
|
||||||
s_cachedPathExtCollection = pathExt != null
|
s_cachedPathExtCollection = pathExt != null
|
||||||
? pathExt.Split(new char[] { System.IO.Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)
|
? pathExt.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries)
|
||||||
: Utils.EmptyArray<string>();
|
: Utils.EmptyArray<string>();
|
||||||
s_cachedPathExtCollectionWithPs1 = new string[s_cachedPathExtCollection.Length + 1];
|
s_cachedPathExtCollectionWithPs1 = new string[s_cachedPathExtCollection.Length + 1];
|
||||||
s_cachedPathExtCollectionWithPs1[0] = StringLiterals.PowerShellScriptFileExtension;
|
s_cachedPathExtCollectionWithPs1[0] = StringLiterals.PowerShellScriptFileExtension;
|
||||||
|
|||||||
@@ -1027,10 +1027,11 @@ namespace System.Management.Automation
|
|||||||
{
|
{
|
||||||
s_cacheStoreLocation =
|
s_cacheStoreLocation =
|
||||||
Environment.GetEnvironmentVariable("PSModuleAnalysisCachePath") ??
|
Environment.GetEnvironmentVariable("PSModuleAnalysisCachePath") ??
|
||||||
(Platform.IsWindows
|
#if UNIX
|
||||||
? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
Path.Combine(Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE), "ModuleAnalysisCache");
|
||||||
@"Microsoft\Windows\PowerShell\ModuleAnalysisCache")
|
#else
|
||||||
: Path.Combine(Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE), "ModuleAnalysisCache"));
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\PowerShell\ModuleAnalysisCache");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Management.Automation.Internal;
|
|||||||
using System.Management.Automation.Language;
|
using System.Management.Automation.Language;
|
||||||
using Microsoft.PowerShell.Commands;
|
using Microsoft.PowerShell.Commands;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Dbg = System.Management.Automation.Diagnostics;
|
using Dbg = System.Management.Automation.Diagnostics;
|
||||||
|
|
||||||
@@ -529,26 +530,15 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the personal module path
|
/// Gets the personal module path
|
||||||
/// (i.e. C:\Users\lukasza\Documents\WindowsPowerShell\modules, or
|
|
||||||
/// ~/.powershell/Modules on Linux)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>personal module path</returns>
|
/// <returns>personal module path</returns>
|
||||||
internal static string GetPersonalModulePath()
|
internal static string GetPersonalModulePath()
|
||||||
{
|
{
|
||||||
if (Platform.IsWindows)
|
#if UNIX
|
||||||
{
|
return Platform.SelectProductNameForDirectory(Platform.XDG_Type.USER_MODULES);
|
||||||
string personalModuleRoot = Path.Combine(
|
#else
|
||||||
Path.Combine(
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Utils.ModuleDirectory);
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
#endif
|
||||||
Utils.ProductNameForDirectory),
|
|
||||||
Utils.ModuleDirectory);
|
|
||||||
return personalModuleRoot;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string personalModuleRoot = Platform.SelectProductNameForDirectory(Platform.XDG_Type.MODULES);
|
|
||||||
return personalModuleRoot;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -560,38 +550,25 @@ namespace System.Management.Automation
|
|||||||
if (s_systemWideModulePath != null)
|
if (s_systemWideModulePath != null)
|
||||||
return s_systemWideModulePath;
|
return s_systemWideModulePath;
|
||||||
|
|
||||||
// There is no runspace config so we use the default string
|
|
||||||
string shellId = Utils.DefaultPowerShellShellID;
|
|
||||||
|
|
||||||
// Now figure out what $PSHOME is.
|
|
||||||
// This depends on the shellId. If we cannot read the application base
|
|
||||||
// registry key, set the variable to empty string
|
|
||||||
string psHome = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
psHome = Utils.GetApplicationBase(shellId);
|
string psHome = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID);
|
||||||
}
|
if (!string.IsNullOrEmpty(psHome))
|
||||||
catch (System.Security.SecurityException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(psHome))
|
|
||||||
{
|
|
||||||
// Win8: 584267 Powershell Modules are listed twice in x86, and cannot be removed
|
|
||||||
// This happens because ModuleTable uses Path as the key and CBS installer
|
|
||||||
// expands the path to include "SysWOW64" (for
|
|
||||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\3\PowerShellEngine ApplicationBase).
|
|
||||||
// Because of this, the module that is getting loaded during startup (through LocalRunspace)
|
|
||||||
// is using "SysWow64" in the key. Later, when Import-Module is called, it loads the
|
|
||||||
// module using ""System32" in the key.
|
|
||||||
|
|
||||||
// Porting note: psHome cannot be lower-cased on case sensitive file systems
|
|
||||||
if (Platform.IsWindows)
|
|
||||||
{
|
{
|
||||||
|
// Win8: 584267 Powershell Modules are listed twice in x86, and cannot be removed
|
||||||
|
// This happens because ModuleTable uses Path as the key and CBS installer
|
||||||
|
// expands the path to include "SysWOW64" (for
|
||||||
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\3\PowerShellEngine ApplicationBase).
|
||||||
|
// Because of this, the module that is getting loaded during startup (through LocalRunspace)
|
||||||
|
// is using "SysWow64" in the key. Later, when Import-Module is called, it loads the
|
||||||
|
// module using ""System32" in the key.
|
||||||
|
#if !UNIX
|
||||||
psHome = psHome.ToLowerInvariant().Replace("\\syswow64\\", "\\system32\\");
|
psHome = psHome.ToLowerInvariant().Replace("\\syswow64\\", "\\system32\\");
|
||||||
|
#endif
|
||||||
|
Interlocked.CompareExchange(ref s_systemWideModulePath, Path.Combine(psHome, "Modules"), null);
|
||||||
}
|
}
|
||||||
Interlocked.CompareExchange(ref s_systemWideModulePath, Path.Combine(psHome, Utils.ModuleDirectory), null);
|
|
||||||
}
|
}
|
||||||
|
catch (System.Security.SecurityException) { }
|
||||||
|
|
||||||
return s_systemWideModulePath;
|
return s_systemWideModulePath;
|
||||||
}
|
}
|
||||||
@@ -604,18 +581,17 @@ namespace System.Management.Automation
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal static string GetDscModulePath()
|
internal static string GetDscModulePath()
|
||||||
{
|
{
|
||||||
if (!Platform.IsWindows)
|
#if UNIX
|
||||||
{
|
return Platform.SelectProductNameForDirectory(Platform.XDG_Type.SHARED_MODULES);
|
||||||
return string.Empty;
|
#else
|
||||||
}
|
|
||||||
|
|
||||||
string dscModulePath = null;
|
string dscModulePath = null;
|
||||||
string programFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
string programFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||||
if (!string.IsNullOrEmpty(programFilesPath))
|
if (!string.IsNullOrEmpty(programFilesPath))
|
||||||
{
|
{
|
||||||
dscModulePath = Path.Combine(programFilesPath, Utils.DscModuleDirectory);
|
dscModulePath = Path.Combine(programFilesPath, Utils.ModuleDirectory);
|
||||||
}
|
}
|
||||||
return dscModulePath;
|
return dscModulePath;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -625,17 +601,20 @@ namespace System.Management.Automation
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static string CombineSystemModulePaths()
|
private static string CombineSystemModulePaths()
|
||||||
{
|
{
|
||||||
string psSystemModulePath = GetSystemwideModulePath();
|
string systemModulePath = GetSystemwideModulePath();
|
||||||
string dscSystemModulePath = GetDscModulePath();
|
string commonModulePath = GetDscModulePath();
|
||||||
|
|
||||||
if (psSystemModulePath != null && dscSystemModulePath != null)
|
bool isSystemPathNullOrEmpty = string.IsNullOrEmpty(systemModulePath);
|
||||||
|
bool isCommonPathNullOrEmpty = string.IsNullOrEmpty(commonModulePath);
|
||||||
|
|
||||||
|
if (!isSystemPathNullOrEmpty && !isCommonPathNullOrEmpty)
|
||||||
{
|
{
|
||||||
return (dscSystemModulePath + ";" + psSystemModulePath);
|
return (commonModulePath + Path.PathSeparator + systemModulePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psSystemModulePath != null || dscSystemModulePath != null)
|
if (!isSystemPathNullOrEmpty || !isCommonPathNullOrEmpty)
|
||||||
{
|
{
|
||||||
return (psSystemModulePath ?? dscSystemModulePath);
|
return isSystemPathNullOrEmpty ? commonModulePath : systemModulePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -664,11 +643,11 @@ namespace System.Management.Automation
|
|||||||
Diagnostics.Assert(pathToLookFor != null, "pathToLookFor should not be null according to contract of the function");
|
Diagnostics.Assert(pathToLookFor != null, "pathToLookFor should not be null according to contract of the function");
|
||||||
|
|
||||||
int pos = 0; // position of the current substring in pathToScan
|
int pos = 0; // position of the current substring in pathToScan
|
||||||
string[] substrings = pathToScan.Split(new char[] { ';' }, StringSplitOptions.None); // we want to process empty entries
|
string[] substrings = pathToScan.Split(Utils.Separators.PathSeparator, StringSplitOptions.None); // we want to process empty entries
|
||||||
string goodPathToLookFor = pathToLookFor.Trim().TrimEnd('\\'); // trailing backslashes and white-spaces will mess up equality comparison
|
string goodPathToLookFor = pathToLookFor.Trim().TrimEnd(Path.DirectorySeparatorChar); // trailing backslashes and white-spaces will mess up equality comparison
|
||||||
foreach (string substring in substrings)
|
foreach (string substring in substrings)
|
||||||
{
|
{
|
||||||
string goodSubstring = substring.Trim().TrimEnd('\\'); // trailing backslashes and white-spaces will mess up equality comparison
|
string goodSubstring = substring.Trim().TrimEnd(Path.DirectorySeparatorChar); // trailing backslashes and white-spaces will mess up equality comparison
|
||||||
|
|
||||||
// We have to use equality comparison on individual substrings (as opposed to simple 'string.IndexOf' or 'string.Contains')
|
// We have to use equality comparison on individual substrings (as opposed to simple 'string.IndexOf' or 'string.Contains')
|
||||||
// because of cases like { pathToScan="C:\Temp\MyDir\MyModuleDir", pathToLookFor="C:\Temp" }
|
// because of cases like { pathToScan="C:\Temp\MyDir\MyModuleDir", pathToLookFor="C:\Temp" }
|
||||||
@@ -698,29 +677,28 @@ namespace System.Management.Automation
|
|||||||
Diagnostics.Assert(basePath != null, "basePath should not be null according to contract of the function");
|
Diagnostics.Assert(basePath != null, "basePath should not be null according to contract of the function");
|
||||||
Diagnostics.Assert(pathToAdd != null, "pathToAdd should not be null according to contract of the function");
|
Diagnostics.Assert(pathToAdd != null, "pathToAdd should not be null according to contract of the function");
|
||||||
|
|
||||||
System.Text.StringBuilder result = new System.Text.StringBuilder(basePath);
|
StringBuilder result = new StringBuilder(basePath);
|
||||||
|
|
||||||
char[] semicolonSeparator = new char[] { ';' };
|
|
||||||
if (!string.IsNullOrEmpty(pathToAdd)) // we don't want to append empty paths
|
if (!string.IsNullOrEmpty(pathToAdd)) // we don't want to append empty paths
|
||||||
{
|
{
|
||||||
foreach (string subPathToAdd in pathToAdd.Split(semicolonSeparator, StringSplitOptions.RemoveEmptyEntries)) // in case pathToAdd is a 'combined path' (semicolon-separated)
|
foreach (string subPathToAdd in pathToAdd.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries)) // in case pathToAdd is a 'combined path' (semicolon-separated)
|
||||||
{
|
{
|
||||||
int position = PathContainsSubstring(result.ToString(), subPathToAdd); // searching in effective 'result' value ensures that possible duplicates in pathsToAdd are handled correctly
|
int position = PathContainsSubstring(result.ToString(), subPathToAdd); // searching in effective 'result' value ensures that possible duplicates in pathsToAdd are handled correctly
|
||||||
if (-1 == position) // subPathToAdd not found - add it
|
if (-1 == position) // subPathToAdd not found - add it
|
||||||
{
|
{
|
||||||
if (-1 == insertPosition) // append subPathToAdd to the end
|
if (-1 == insertPosition) // append subPathToAdd to the end
|
||||||
{
|
{
|
||||||
bool resultHasEndingSemicolon = false;
|
bool endsWithPathSeparator = false;
|
||||||
if (result.Length > 0) resultHasEndingSemicolon = (result[result.Length - 1] == ';');
|
if (result.Length > 0) endsWithPathSeparator = (result[result.Length - 1] == Path.PathSeparator);
|
||||||
|
|
||||||
if (resultHasEndingSemicolon)
|
if (endsWithPathSeparator)
|
||||||
result.Append(subPathToAdd);
|
result.Append(subPathToAdd);
|
||||||
else
|
else
|
||||||
result.Append(";" + subPathToAdd);
|
result.Append(Path.PathSeparator + subPathToAdd);
|
||||||
}
|
}
|
||||||
else // insert at the requested location (this is used by DSC (<Program Files> location) and by 'user-specific location' (SpecialFolder.MyDocuments or EVT.User))
|
else // insert at the requested location (this is used by DSC (<Program Files> location) and by 'user-specific location' (SpecialFolder.MyDocuments or EVT.User))
|
||||||
{
|
{
|
||||||
result.Insert(insertPosition, subPathToAdd + ";");
|
result.Insert(insertPosition, subPathToAdd + Path.PathSeparator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,6 +707,94 @@ namespace System.Management.Automation
|
|||||||
return result.ToString();
|
return result.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the current powershell is likely running in following scenarios:
|
||||||
|
/// - sxs ps started on windows [machine-wide env:psmodulepath will influence]
|
||||||
|
/// - sxs ps started from full ps
|
||||||
|
/// - sxs ps started from inbox nano/iot ps
|
||||||
|
/// - full ps started from sxs ps
|
||||||
|
/// - inbox nano/iot ps started from sxs ps
|
||||||
|
/// If it's likely one of them, then we need to clear the current process module path.
|
||||||
|
/// </summary>
|
||||||
|
private static bool NeedToClearProcessModulePath(string currentProcessModulePath, string personalModulePath, string programFilesModulePath, bool runningSxS)
|
||||||
|
{
|
||||||
|
#if UNIX
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
Dbg.Assert(!string.IsNullOrEmpty(personalModulePath), "caller makes sure it's not null or empty");
|
||||||
|
Dbg.Assert(!string.IsNullOrEmpty(programFilesModulePath), "caller makes sure it's not null or empty");
|
||||||
|
|
||||||
|
const string winSxSModuleDirectory = @"PowerShell\Modules";
|
||||||
|
const string winLegacyModuleDirectory = @"WindowsPowerShell\Modules";
|
||||||
|
|
||||||
|
if (runningSxS)
|
||||||
|
{
|
||||||
|
// The machine-wide and user-wide environment variables are only meaningful for full ps,
|
||||||
|
// so if the current process module path contains any of them, it's likely that the sxs
|
||||||
|
// ps was started directly on windows, or from full ps. The same goes for the legacy personal
|
||||||
|
// and shared module paths.
|
||||||
|
string hklmModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.Machine);
|
||||||
|
string hkcuModulePath = GetExpandedEnvironmentVariable("PSMODULEPATH", EnvironmentVariableTarget.User);
|
||||||
|
string legacyPersonalModulePath = personalModulePath.Replace(winSxSModuleDirectory, winLegacyModuleDirectory);
|
||||||
|
string legacyProgramFilesModulePath = programFilesModulePath.Replace(winSxSModuleDirectory, winLegacyModuleDirectory);
|
||||||
|
|
||||||
|
return (!string.IsNullOrEmpty(hklmModulePath) && currentProcessModulePath.IndexOf(hklmModulePath, StringComparison.OrdinalIgnoreCase) != -1) ||
|
||||||
|
(!string.IsNullOrEmpty(hkcuModulePath) && currentProcessModulePath.IndexOf(hkcuModulePath, StringComparison.OrdinalIgnoreCase) != -1) ||
|
||||||
|
currentProcessModulePath.IndexOf(legacyPersonalModulePath, StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
|
currentProcessModulePath.IndexOf(legacyProgramFilesModulePath, StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sxs personal and shared module paths are only meaningful for sxs ps, so if they appear
|
||||||
|
// in the current process module path, it's likely the running ps was started from a sxs ps.
|
||||||
|
string sxsPersonalModulePath = personalModulePath.Replace(winLegacyModuleDirectory, winSxSModuleDirectory);
|
||||||
|
string sxsProgramFilesModulePath = programFilesModulePath.Replace(winLegacyModuleDirectory, winSxSModuleDirectory);
|
||||||
|
|
||||||
|
return currentProcessModulePath.IndexOf(sxsPersonalModulePath, StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
|
currentProcessModulePath.IndexOf(sxsProgramFilesModulePath, StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When sxs ps instance B got started from sxs ps instance A, A's pshome module path might
|
||||||
|
/// show up in current process module path. It doesn't make sense for B to load modules from
|
||||||
|
/// A's pshome module path, so remove it in such case.
|
||||||
|
/// </summary>
|
||||||
|
private static string RemoveSxSPsHomeModulePath(string currentProcessModulePath)
|
||||||
|
{
|
||||||
|
#if UNIX
|
||||||
|
const string powershellExeName = "powershell";
|
||||||
|
#else
|
||||||
|
const string powershellExeName = "powershell.exe";
|
||||||
|
#endif
|
||||||
|
StringBuilder modulePathString = new StringBuilder(currentProcessModulePath.Length);
|
||||||
|
char[] invalidPathChars = Path.GetInvalidPathChars();
|
||||||
|
|
||||||
|
foreach (var path in currentProcessModulePath.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
string trimedPath = path.Trim().TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
if (trimedPath == string.Empty || trimedPath.IndexOfAny(invalidPathChars) != -1)
|
||||||
|
{
|
||||||
|
// Path contains invalid characters. Ignore it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string psExePath = Path.Combine(Path.GetDirectoryName(trimedPath), powershellExeName);
|
||||||
|
if (File.Exists(psExePath))
|
||||||
|
{
|
||||||
|
// Path is a PSHome module path. Ignore it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modulePathString.Length > 0)
|
||||||
|
{
|
||||||
|
modulePathString.Append(Path.PathSeparator);
|
||||||
|
}
|
||||||
|
modulePathString.Append(trimedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return modulePathString.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks the various PSModulePath environment string and returns PSModulePath string as appropriate. Note - because these
|
/// Checks the various PSModulePath environment string and returns PSModulePath string as appropriate. Note - because these
|
||||||
/// strings go through the provider, we need to escape any wildcards before passing them
|
/// strings go through the provider, we need to escape any wildcards before passing them
|
||||||
@@ -736,23 +802,42 @@ namespace System.Management.Automation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetModulePath(string currentProcessModulePath, string hklmMachineModulePath, string hkcuUserModulePath)
|
public static string GetModulePath(string currentProcessModulePath, string hklmMachineModulePath, string hkcuUserModulePath)
|
||||||
{
|
{
|
||||||
|
string personalModulePath = GetPersonalModulePath();
|
||||||
string programFilesModulePath = GetDscModulePath(); // aka <Program Files> location
|
string programFilesModulePath = GetDscModulePath(); // aka <Program Files> location
|
||||||
string psHomeModulePath = Environment.ExpandEnvironmentVariables(GetSystemwideModulePath()); // $PSHome\Modules location
|
string psHomeModulePath = GetSystemwideModulePath(); // $PSHome\Modules location
|
||||||
|
|
||||||
|
#if CORECLR
|
||||||
|
bool runningSxS = Platform.IsInbox ? false : true;
|
||||||
|
#else
|
||||||
|
bool runningSxS = false;
|
||||||
|
#endif
|
||||||
|
if (!string.IsNullOrEmpty(currentProcessModulePath) &&
|
||||||
|
NeedToClearProcessModulePath(currentProcessModulePath, personalModulePath, programFilesModulePath, runningSxS))
|
||||||
|
{
|
||||||
|
// Clear the current process module path in the following cases
|
||||||
|
// - start sxs ps on windows [machine-wide env:psmodulepath will influence]
|
||||||
|
// - start sxs ps from full ps
|
||||||
|
// - start sxs ps from inbox nano/iot ps
|
||||||
|
// - start full ps from sxs ps
|
||||||
|
// - start inbox nano/iot ps from sxs ps
|
||||||
|
currentProcessModulePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
// If the variable isn't set, then set it to the default value
|
// If the variable isn't set, then set it to the default value
|
||||||
if (currentProcessModulePath == null) // EVT.Process does Not exist - really corner case
|
if (currentProcessModulePath == null) // EVT.Process does Not exist - really corner case
|
||||||
{
|
{
|
||||||
// Handle the default case...
|
// Handle the default case...
|
||||||
if (String.IsNullOrEmpty(hkcuUserModulePath)) // EVT.User does Not exist -> set to <SpecialFolder.MyDocuments> location
|
if (string.IsNullOrEmpty(hkcuUserModulePath)) // EVT.User does Not exist -> set to <SpecialFolder.MyDocuments> location
|
||||||
{
|
{
|
||||||
currentProcessModulePath = GetPersonalModulePath(); // = SpecialFolder.MyDocuments + Utils.ProductNameForDirectory + Utils.ModuleDirectory
|
currentProcessModulePath = personalModulePath; // = SpecialFolder.MyDocuments + Utils.ProductNameForDirectory + Utils.ModuleDirectory
|
||||||
}
|
}
|
||||||
else // EVT.User exists -> set to EVT.User
|
else // EVT.User exists -> set to EVT.User
|
||||||
{
|
{
|
||||||
currentProcessModulePath = hkcuUserModulePath; // = EVT.User
|
currentProcessModulePath = hkcuUserModulePath; // = EVT.User
|
||||||
}
|
}
|
||||||
|
|
||||||
currentProcessModulePath += ';';
|
currentProcessModulePath += Path.PathSeparator;
|
||||||
if (String.IsNullOrEmpty(hklmMachineModulePath)) // EVT.Machine does Not exist
|
if (string.IsNullOrEmpty(hklmMachineModulePath)) // EVT.Machine does Not exist
|
||||||
{
|
{
|
||||||
currentProcessModulePath += CombineSystemModulePaths(); // += (DscModulePath + $PSHome\Modules)
|
currentProcessModulePath += CombineSystemModulePaths(); // += (DscModulePath + $PSHome\Modules)
|
||||||
}
|
}
|
||||||
@@ -761,18 +846,21 @@ namespace System.Management.Automation
|
|||||||
currentProcessModulePath += hklmMachineModulePath; // += EVT.Machine
|
currentProcessModulePath += hklmMachineModulePath; // += EVT.Machine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // EVT.Process exists
|
// EVT.Process exists
|
||||||
|
// Now handle the case where the environment variable is already set.
|
||||||
|
else if (runningSxS) // The running powershell is an SxS PS instance
|
||||||
{
|
{
|
||||||
// Now handle the case where the environment variable is already set.
|
// When SxS PS instance A starts SxS PS instance B, A's PSHome module path might be inherited by B. We need to remove that path from B
|
||||||
|
currentProcessModulePath = RemoveSxSPsHomeModulePath(currentProcessModulePath);
|
||||||
|
|
||||||
// CoreCLR PowerShell on Windows has a Modules folder in the the application base
|
string personalModulePathToUse = string.IsNullOrEmpty(hkcuUserModulePath) ? personalModulePath : hkcuUserModulePath;
|
||||||
// path which contains the built-in modules It must be in the front of the path no
|
string systemModulePathToUse = string.IsNullOrEmpty(hklmMachineModulePath) ? psHomeModulePath : hklmMachineModulePath;
|
||||||
// matter what, regardless of inherited path.
|
|
||||||
#if CORECLR && !UNIX
|
|
||||||
// TODO: #1184 will resolve this work-around
|
|
||||||
currentProcessModulePath = AddToPath(currentProcessModulePath, GetSystemwideModulePath(), 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
currentProcessModulePath = AddToPath(currentProcessModulePath, personalModulePathToUse, 0);
|
||||||
|
currentProcessModulePath = AddToPath(currentProcessModulePath, systemModulePathToUse, -1);
|
||||||
|
}
|
||||||
|
else // The running powershell is Full PS or inbox Core PS
|
||||||
|
{
|
||||||
// If there is no personal path key, then if the env variable doesn't match the system variable,
|
// If there is no personal path key, then if the env variable doesn't match the system variable,
|
||||||
// the user modified it somewhere, else prepend the default personel module path
|
// the user modified it somewhere, else prepend the default personel module path
|
||||||
if (hklmMachineModulePath != null) // EVT.Machine exists
|
if (hklmMachineModulePath != null) // EVT.Machine exists
|
||||||
@@ -789,8 +877,7 @@ namespace System.Management.Automation
|
|||||||
// for bug 6678623, if we are running wow64 process (x86 32-bit process on 64-bit (amd64) OS), then ensure that <SpecialFolder.MyDocuments> exists in currentProcessModulePath / return value
|
// for bug 6678623, if we are running wow64 process (x86 32-bit process on 64-bit (amd64) OS), then ensure that <SpecialFolder.MyDocuments> exists in currentProcessModulePath / return value
|
||||||
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
|
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
|
||||||
{
|
{
|
||||||
string userModulePath = GetPersonalModulePath();
|
currentProcessModulePath = AddToPath(currentProcessModulePath, personalModulePath, psHomePosition);
|
||||||
currentProcessModulePath = AddToPath(currentProcessModulePath, userModulePath, psHomePosition);
|
|
||||||
psHomePosition = PathContainsSubstring(currentProcessModulePath, psHomeModulePath);
|
psHomePosition = PathContainsSubstring(currentProcessModulePath, psHomeModulePath);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -799,12 +886,12 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
currentProcessModulePath = GetPersonalModulePath() + ';' + hklmMachineModulePath; // <SpecialFolder.MyDocuments> + EVT.Machine + inserted <ProgramFiles> later in this function
|
currentProcessModulePath = personalModulePath + Path.PathSeparator + hklmMachineModulePath; // <SpecialFolder.MyDocuments> + EVT.Machine + inserted <ProgramFiles> later in this function
|
||||||
}
|
}
|
||||||
else // EVT.User exists
|
else // EVT.User exists
|
||||||
{
|
{
|
||||||
// PSModulePath is designed to have behaviour like 'Path' var in a sense that EVT.User + EVT.Machine are merged to get final value of PSModulePath
|
// PSModulePath is designed to have behaviour like 'Path' var in a sense that EVT.User + EVT.Machine are merged to get final value of PSModulePath
|
||||||
string combined = string.Concat(hkcuUserModulePath, ';', hklmMachineModulePath); // EVT.User + EVT.Machine
|
string combined = string.Concat(hkcuUserModulePath, Path.PathSeparator, hklmMachineModulePath); // EVT.User + EVT.Machine
|
||||||
if (!((combined).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase) ||
|
if (!((combined).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase) ||
|
||||||
(hklmMachineModulePath).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase) ||
|
(hklmMachineModulePath).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase) ||
|
||||||
(hkcuUserModulePath).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase)))
|
(hkcuUserModulePath).Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase)))
|
||||||
@@ -829,7 +916,7 @@ namespace System.Management.Automation
|
|||||||
{
|
{
|
||||||
if (hkcuUserModulePath.Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase))
|
if (hkcuUserModulePath.Equals(currentProcessModulePath, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
currentProcessModulePath = hkcuUserModulePath + ';' + CombineSystemModulePaths(); // = EVT.User + (DscModulePath + $PSHome\Modules)
|
currentProcessModulePath = hkcuUserModulePath + Path.PathSeparator + CombineSystemModulePaths(); // = EVT.User + (DscModulePath + $PSHome\Modules)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -923,13 +1010,13 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(modulePathString))
|
if (!string.IsNullOrWhiteSpace(modulePathString))
|
||||||
{
|
{
|
||||||
foreach (string envPath in modulePathString.Split(Utils.Separators.Semicolon, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string envPath in modulePathString.Split(Utils.Separators.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
var processedPath = ProcessOneModulePath(context, envPath, processedPathSet);
|
var processedPath = ProcessOneModulePath(context, envPath, processedPathSet);
|
||||||
if (processedPath != null)
|
if (processedPath != null)
|
||||||
yield return processedPath;
|
yield return processedPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeSystemModulePath)
|
if (includeSystemModulePath)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,17 +36,9 @@ namespace System.Management.Automation
|
|||||||
static ConfigPropertyAccessor()
|
static ConfigPropertyAccessor()
|
||||||
{
|
{
|
||||||
#if CORECLR
|
#if CORECLR
|
||||||
// TODO: Update this for #1184
|
Instance = Platform.IsInbox
|
||||||
//if (Platform.IsInbox())
|
? (ConfigPropertyAccessor) new RegistryAccessor()
|
||||||
//{
|
: new JsonConfigFileAccessor();
|
||||||
// Instance = new RegistryAccessor();
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// Instance = new JsonConfigFileAccessor();
|
|
||||||
//}
|
|
||||||
// Remove this following line:
|
|
||||||
Instance = new JsonConfigFileAccessor();
|
|
||||||
#else
|
#else
|
||||||
Instance = new RegistryAccessor();
|
Instance = new RegistryAccessor();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -303,8 +303,10 @@ namespace System.Management.Automation
|
|||||||
RunspaceInit.PSHostDescription);
|
RunspaceInit.PSHostDescription);
|
||||||
this.GlobalScope.SetVariable(v.Name, v, false, true, this, CommandOrigin.Internal, fastPath: true);
|
this.GlobalScope.SetVariable(v.Name, v, false, true, this, CommandOrigin.Internal, fastPath: true);
|
||||||
|
|
||||||
// $HOME = %USERPROFILE% - indicate where a user's home directory is located in the file system.
|
// $HOME - indicate where a user's home directory is located in the file system.
|
||||||
string home = Environment.GetEnvironmentVariable("USERPROFILE") ?? string.Empty;
|
// -- %USERPROFILE% on windows
|
||||||
|
// -- %HOME% on unix
|
||||||
|
string home = Environment.GetEnvironmentVariable(Platform.CommonEnvVariableNames.Home) ?? string.Empty;
|
||||||
v = new PSVariable(SpecialVariables.Home,
|
v = new PSVariable(SpecialVariables.Home,
|
||||||
home,
|
home,
|
||||||
ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope,
|
ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope,
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ namespace System.Management.Automation
|
|||||||
if (engineKey != null)
|
if (engineKey != null)
|
||||||
{
|
{
|
||||||
var result = engineKey.GetValue(RegistryStrings.MonadEngine_ApplicationBase) as string;
|
var result = engineKey.GetValue(RegistryStrings.MonadEngine_ApplicationBase) as string;
|
||||||
|
result = Environment.ExpandEnvironmentVariables(result);
|
||||||
if (wantPsHome)
|
if (wantPsHome)
|
||||||
Interlocked.CompareExchange(ref s_pshome, null, result);
|
Interlocked.CompareExchange(ref s_pshome, null, result);
|
||||||
|
|
||||||
@@ -584,25 +585,22 @@ namespace System.Management.Automation
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// String representing the Default shellID.
|
/// String representing the Default shellID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string DefaultPowerShellShellID = "Microsoft.PowerShell";
|
internal const string DefaultPowerShellShellID = "Microsoft.PowerShell";
|
||||||
/// <summary>
|
|
||||||
/// String used to control directory location for PowerShell
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Profile uses this to control profile loading.
|
|
||||||
/// </remarks>
|
|
||||||
internal static string ProductNameForDirectory =
|
|
||||||
Platform.IsWindows ? "WindowsPowerShell" : Platform.SelectProductNameForDirectory(Platform.XDG_Type.CONFIG);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the subdirectory that contains packages.
|
/// This is used to construct the profile path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ModuleDirectory = "Modules";
|
#if CORECLR
|
||||||
|
internal static string ProductNameForDirectory = Platform.IsInbox ? "WindowsPowerShell" : "PowerShell";
|
||||||
|
#else
|
||||||
|
internal const string ProductNameForDirectory = "WindowsPowerShell";
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The partial path to the DSC module directory
|
/// The subdirectory of module paths
|
||||||
|
/// e.g. ~\Documents\WindowsPowerShell\Modules and %ProgramFiles%\WindowsPowerShell\Modules
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string DscModuleDirectory = Path.Combine("WindowsPowerShell", "Modules");
|
internal static string ModuleDirectory = Path.Combine(ProductNameForDirectory, "Modules");
|
||||||
|
|
||||||
internal static string GetRegistryConfigurationPrefix()
|
internal static string GetRegistryConfigurationPrefix()
|
||||||
{
|
{
|
||||||
@@ -1519,6 +1517,7 @@ namespace System.Management.Automation
|
|||||||
internal static readonly char[] Semicolon = new char[] { ';' };
|
internal static readonly char[] Semicolon = new char[] { ';' };
|
||||||
internal static readonly char[] StarOrQuestion = new char[] { '*', '?' };
|
internal static readonly char[] StarOrQuestion = new char[] { '*', '?' };
|
||||||
internal static readonly char[] ColonOrBackslash = new char[] { '\\', ':' };
|
internal static readonly char[] ColonOrBackslash = new char[] { '\\', ':' };
|
||||||
|
internal static readonly char[] PathSeparator = new char[] { Path.PathSeparator };
|
||||||
|
|
||||||
internal static readonly char[] QuoteChars = new char[] { '\'', '"' };
|
internal static readonly char[] QuoteChars = new char[] { '\'', '"' };
|
||||||
internal static readonly char[] Space = new char[] { ' ' };
|
internal static readonly char[] Space = new char[] { ' ' };
|
||||||
|
|||||||
@@ -182,8 +182,12 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
if (forCurrentUser)
|
if (forCurrentUser)
|
||||||
{
|
{
|
||||||
|
#if UNIX
|
||||||
|
basePath = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CONFIG);
|
||||||
|
#else
|
||||||
basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
||||||
basePath = IO.Path.Combine(basePath, Utils.ProductNameForDirectory);
|
basePath = IO.Path.Combine(basePath, Utils.ProductNameForDirectory);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1891,7 +1891,7 @@ namespace System.Management.Automation.Remoting
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Go through each directory in the module path
|
// Go through each directory in the module path
|
||||||
string[] modulePaths = ModuleIntrinsics.GetModulePath().Split(Utils.Separators.Semicolon);
|
string[] modulePaths = ModuleIntrinsics.GetModulePath().Split(Utils.Separators.PathSeparator);
|
||||||
foreach (string path in modulePaths)
|
foreach (string path in modulePaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
if (providerInfo != null && string.IsNullOrEmpty(providerInfo.Home))
|
if (providerInfo != null && string.IsNullOrEmpty(providerInfo.Home))
|
||||||
{
|
{
|
||||||
// %USERPROFILE% - indicate where a user's home directory is located in the file system.
|
// %USERPROFILE% - indicate where a user's home directory is located in the file system.
|
||||||
string homeDirectory = Environment.GetEnvironmentVariable("USERPROFILE");
|
string homeDirectory = Environment.GetEnvironmentVariable(Platform.CommonEnvVariableNames.Home);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(homeDirectory))
|
if (!string.IsNullOrEmpty(homeDirectory))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -211,9 +211,9 @@ namespace System.Management.Automation.Internal
|
|||||||
private static void CleanKeyParents(RegistryKey baseKey, string keyPath)
|
private static void CleanKeyParents(RegistryKey baseKey, string keyPath)
|
||||||
{
|
{
|
||||||
#if CORECLR
|
#if CORECLR
|
||||||
// if ( ! Platform.Inbox) // Modify this to support registry checks for inbox CoreCLR
|
if (!Platform.IsInbox)
|
||||||
return;
|
return;
|
||||||
#else // Windows && FullCLR
|
#endif
|
||||||
using (RegistryKey key = baseKey.OpenSubKey(keyPath, true))
|
using (RegistryKey key = baseKey.OpenSubKey(keyPath, true))
|
||||||
{
|
{
|
||||||
// Verify the child key has no children
|
// Verify the child key has no children
|
||||||
@@ -248,7 +248,6 @@ namespace System.Management.Automation.Internal
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ExecutionPolicy GetExecutionPolicy(string shellId)
|
internal static ExecutionPolicy GetExecutionPolicy(string shellId)
|
||||||
|
|||||||
@@ -10,9 +10,14 @@ Describe "Configuration file locations" -tags "CI","Slow" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
|
|
||||||
if ($IsWindows) {
|
if ($IsWindows) {
|
||||||
|
$ProductName = "WindowsPowerShell"
|
||||||
|
if ($IsCoreCLR -and ($PSHOME -notlike "*Windows\System32\WindowsPowerShell\v1.0"))
|
||||||
|
{
|
||||||
|
$ProductName = "PowerShell"
|
||||||
|
}
|
||||||
$expectedCache = [IO.Path]::Combine($env:LOCALAPPDATA, "Microsoft", "Windows", "PowerShell", "StartupProfileData-NonInteractive")
|
$expectedCache = [IO.Path]::Combine($env:LOCALAPPDATA, "Microsoft", "Windows", "PowerShell", "StartupProfileData-NonInteractive")
|
||||||
$expectedModule = [IO.Path]::Combine($env:USERPROFILE, "Documents", "WindowsPowerShell", "Modules")
|
$expectedModule = [IO.Path]::Combine($env:USERPROFILE, "Documents", $ProductName, "Modules")
|
||||||
$expectedProfile = [io.path]::Combine($env:USERPROFILE, "Documents","WindowsPowerShell",$profileName)
|
$expectedProfile = [io.path]::Combine($env:USERPROFILE, "Documents", $ProductName, $profileName)
|
||||||
$expectedReadline = [IO.Path]::Combine($env:AppData, "Microsoft", "Windows", "PowerShell", "PSReadline", "ConsoleHost_history.txt")
|
$expectedReadline = [IO.Path]::Combine($env:AppData, "Microsoft", "Windows", "PowerShell", "PSReadline", "ConsoleHost_history.txt")
|
||||||
} else {
|
} else {
|
||||||
$expectedCache = [IO.Path]::Combine($env:HOME, ".cache", "powershell", "StartupProfileData-NonInteractive")
|
$expectedCache = [IO.Path]::Combine($env:HOME, ".cache", "powershell", "StartupProfileData-NonInteractive")
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Describe 'use of a module from two runspaces' -Tags "CI" {
|
|||||||
|
|
||||||
$resolvedTestDrivePath = Split-Path ((get-childitem TestDrive:\)[0].FullName)
|
$resolvedTestDrivePath = Split-Path ((get-childitem TestDrive:\)[0].FullName)
|
||||||
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
||||||
$env:PSMODULEPATH += ";$resolvedTestDrivePath"
|
$env:PSMODULEPATH += "$([System.IO.Path]::PathSeparator)$resolvedTestDrivePath"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Describe 'NestedModules' -Tags "CI" {
|
|||||||
|
|
||||||
$resolvedTestDrivePath = Split-Path ((get-childitem TestDrive:\)[0].FullName)
|
$resolvedTestDrivePath = Split-Path ((get-childitem TestDrive:\)[0].FullName)
|
||||||
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
||||||
$env:PSMODULEPATH += ";$resolvedTestDrivePath"
|
$env:PSMODULEPATH += "$([System.IO.Path]::PathSeparator)$resolvedTestDrivePath"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Describe 'using module' -Tags "CI" {
|
|||||||
|
|
||||||
$resolvedTestDrivePath = Split-Path ((get-childitem "${TestDrive}\$ModulePathPrefix")[0].FullName)
|
$resolvedTestDrivePath = Split-Path ((get-childitem "${TestDrive}\$ModulePathPrefix")[0].FullName)
|
||||||
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
if (-not ($env:PSMODULEPATH -like "*$resolvedTestDrivePath*")) {
|
||||||
$env:PSMODULEPATH += ";$resolvedTestDrivePath"
|
$env:PSMODULEPATH += "$([System.IO.Path]::PathSeparator)$resolvedTestDrivePath"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Describe "Export-Csv" -Tags "CI" {
|
Describe "Export-Csv" -Tags "CI" {
|
||||||
$testObject = @("test","object","array")
|
$testObject = @("test","object","array")
|
||||||
$testCsv = "output.csv"
|
$testCsv = Join-Path -Path $TestDrive -ChildPath "output.csv"
|
||||||
|
|
||||||
AfterEach {
|
AfterEach {
|
||||||
Remove-Item $testCsv -Force -ErrorAction SilentlyContinue
|
Remove-Item $testCsv -Force -ErrorAction SilentlyContinue
|
||||||
@@ -51,7 +51,7 @@ Describe "Export-Csv" -Tags "CI" {
|
|||||||
It "Should have the same information when using the alias vs the cmdlet" {
|
It "Should have the same information when using the alias vs the cmdlet" {
|
||||||
$testObject | Export-Csv -Path $testCsv
|
$testObject | Export-Csv -Path $testCsv
|
||||||
|
|
||||||
$aliasObject = "alias.csv"
|
$aliasObject = Join-Path -Path $TestDrive -ChildPath "alias.csv"
|
||||||
|
|
||||||
$testObject | epcsv -Path $aliasObject
|
$testObject | epcsv -Path $aliasObject
|
||||||
|
|
||||||
|
|||||||
@@ -16,26 +16,29 @@ Describe "Export-FormatData DRT Unit Tests" -Tags "CI" {
|
|||||||
|
|
||||||
Describe "Export-FormatData" -Tags "CI" {
|
Describe "Export-FormatData" -Tags "CI" {
|
||||||
|
|
||||||
|
$testOutput = Join-Path -Path $TestDrive -ChildPath "outputfile"
|
||||||
|
|
||||||
|
AfterEach {
|
||||||
|
Remove-Item $testOutput -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
Context "Check Export-FormatData can be called validly." {
|
Context "Check Export-FormatData can be called validly." {
|
||||||
It "Should be able to be called without error" {
|
It "Should be able to be called without error" {
|
||||||
{ Get-FormatData | Export-FormatData -Path "outputfile" } | Should Not Throw
|
{ Get-FormatData | Export-FormatData -Path $testOutput } | Should Not Throw
|
||||||
Remove-Item "outputfile" -Force -ErrorAction SilentlyContinue
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "Check that the output is in the correct format" {
|
Context "Check that the output is in the correct format" {
|
||||||
It "Should not return an empty xml file" {
|
It "Should not return an empty xml file" {
|
||||||
Get-FormatData | Export-FormatData -Path "outputfile"
|
Get-FormatData | Export-FormatData -Path $testOutput
|
||||||
$piped = Get-Content "outputfile"
|
$piped = Get-Content $testOutput
|
||||||
$piped | Should Not Be ""
|
$piped | Should Not Be ""
|
||||||
Remove-Item "outputfile" -Force -ErrorAction SilentlyContinue
|
}
|
||||||
}
|
|
||||||
|
|
||||||
It "Should have a valid xml tag at the start of the file" {
|
It "Should have a valid xml tag at the start of the file" {
|
||||||
Get-FormatData | Export-FormatData -Path "outputfile"
|
Get-FormatData | Export-FormatData -Path $testOutput
|
||||||
$piped = Get-Content "outputfile"
|
$piped = Get-Content $testOutput
|
||||||
$piped[0] | Should Be "<"
|
$piped[0] | Should Be "<"
|
||||||
Remove-Item "outputfile" -Force -ErrorAction SilentlyContinue
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
Describe "Out-File DRT Unit Tests" -Tags "CI" {
|
Describe "Out-File DRT Unit Tests" -Tags "CI" {
|
||||||
It "Should be able to write the contens into a file with -pspath" {
|
It "Should be able to write the contens into a file with -pspath" {
|
||||||
$tempFile = "ExposeBug928965"
|
$tempFile = Join-Path -Path $TestDrive -ChildPath "ExposeBug928965"
|
||||||
{ 1 | Out-File -PSPath $tempFile } | Should Not Throw
|
{ 1 | Out-File -PSPath $tempFile } | Should Not Throw
|
||||||
$fileContents = Get-Content $tempFile
|
$fileContents = Get-Content $tempFile
|
||||||
$fileContents | Should be 1
|
$fileContents | Should be 1
|
||||||
@@ -8,7 +8,7 @@ Describe "Out-File DRT Unit Tests" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
It "Should be able to write the contens into a file with -pspath" {
|
It "Should be able to write the contens into a file with -pspath" {
|
||||||
$tempFile = "outfileAppendTest.txt"
|
$tempFile = Join-Path -Path $TestDrive -ChildPath "outfileAppendTest.txt"
|
||||||
{ 'This is first line.' | out-file $tempFile } | Should Not Throw
|
{ 'This is first line.' | out-file $tempFile } | Should Not Throw
|
||||||
{ 'This is second line.' | out-file -append $tempFile } | Should Not Throw
|
{ 'This is second line.' | out-file -append $tempFile } | Should Not Throw
|
||||||
$tempFile |Should Contain "first"
|
$tempFile |Should Contain "first"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Describe "Stream writer tests" -Tags "CI" {
|
Describe "Stream writer tests" -Tags "CI" {
|
||||||
$targetfile = "writeoutput.txt"
|
$targetfile = Join-Path -Path $TestDrive -ChildPath "writeoutput.txt"
|
||||||
|
|
||||||
# A custom function is defined here do handle the debug stream dealing with the confirm prompt
|
# A custom function is defined here do handle the debug stream dealing with the confirm prompt
|
||||||
# that would normally
|
# that would normally
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
Describe "SxS Module Path Basic Tests" -tags "CI" {
|
||||||
|
|
||||||
|
BeforeAll {
|
||||||
|
|
||||||
|
if ($IsWindows)
|
||||||
|
{
|
||||||
|
$powershell = "$PSHOME\powershell.exe"
|
||||||
|
$ProductName = "WindowsPowerShell"
|
||||||
|
if ($IsCoreCLR -and ($PSHOME -notlike "*Windows\System32\WindowsPowerShell\v1.0"))
|
||||||
|
{
|
||||||
|
$ProductName = "PowerShell"
|
||||||
|
}
|
||||||
|
$expectedUserPath = Join-Path -Path $HOME -ChildPath "Documents\$ProductName\Modules"
|
||||||
|
$expectedSharedPath = Join-Path -Path $env:ProgramFiles -ChildPath "$ProductName\Modules"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$powershell = "$PSHOME/powershell"
|
||||||
|
$expectedUserPath = [System.Management.Automation.Platform]::SelectProductNameForDirectory("USER_MODULES")
|
||||||
|
$expectedSharedPath = [System.Management.Automation.Platform]::SelectProductNameForDirectory("SHARED_MODULES")
|
||||||
|
}
|
||||||
|
$expectedSystemPath = Join-Path -Path $PSHOME -ChildPath 'Modules'
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeEach {
|
||||||
|
$originalModulePath = $env:PSMODULEPATH
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterEach {
|
||||||
|
$env:PSMODULEPATH = $originalModulePath
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validate sxs module path" {
|
||||||
|
|
||||||
|
$env:PSMODULEPATH = ""
|
||||||
|
$defaultModulePath = & $powershell -nopro -c '$env:PSMODULEPATH'
|
||||||
|
|
||||||
|
$paths = $defaultModulePath -split [System.IO.Path]::PathSeparator
|
||||||
|
|
||||||
|
$paths.Count | Should Be 3
|
||||||
|
$paths[0] | Should Be $expectedUserPath
|
||||||
|
$paths[1] | Should Be $expectedSharedPath
|
||||||
|
$paths[2] | Should Be $expectedSystemPath
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user