//
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
//
// DISCLAIMER OF WARRANTY: The software is licensed “as-is.” You
// bear the risk of using it. Microsoft gives no express warranties,
// guarantees or conditions. You may have additional consumer rights
// under your local laws which this agreement cannot change. To the extent
// permitted under your local laws, Microsoft excludes the implied warranties
// of merchantability, fitness for a particular purpose and non-infringement.
namespace Microsoft.Samples.PowerShell.Host
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Management.Automation;
using System.Reflection;
using Microsoft.Win32;
///
/// Helper functions for setting $profile.
///
public class HostUtilities
{
///
/// Root registry key for Windows PowerShell.
///
internal const string PowerShellRootKeyPath = "Software\\Microsoft\\PowerShell";
///
/// Engine registry key.
///
internal const string PowerShellEngineKey = "PowerShellEngine";
///
/// Registry key used to determine the directory where Windows
/// PowerShell is installed.
///
internal const string PowerShellEngineApplicationBase = "ApplicationBase";
///
/// The path to the Windows PowerShell version registry key.
///
internal const string RegistryVersionKey = "1";
///
/// Gets a PSObject whose base object is currentUserCurrentHost and with notes for the other 4 parameters.
///
/// The profile file name for all users and all hosts.
/// The profile file name for all users and current host.
/// The profile file name for cuurrent user and all hosts.
/// The profile name for cuurrent user and current host.
/// A PSObject whose base object is currentUserCurrentHost and with notes for the other 4 parameters.
internal static PSObject GetDollarProfile(string allUsersAllHosts, string allUsersCurrentHost, string currentUserAllHosts, string currentUserCurrentHost)
{
PSObject returnValue = new PSObject(currentUserCurrentHost);
returnValue.Properties.Add(new PSNoteProperty("AllUsersAllHosts", allUsersAllHosts));
returnValue.Properties.Add(new PSNoteProperty("AllUsersCurrentHost", allUsersCurrentHost));
returnValue.Properties.Add(new PSNoteProperty("CurrentUserAllHosts", currentUserAllHosts));
returnValue.Properties.Add(new PSNoteProperty("CurrentUserCurrentHost", currentUserCurrentHost));
return returnValue;
}
///
/// Gets an array of commands that can be run sequentially to set $profile and run the profile commands.
///
/// The id identifying the host or shell used in profile file names.
/// An array of commands.
public static PSCommand[] GetProfileCommands(string shellId)
{
return HostUtilities.GetProfileCommands(shellId, false);
}
///
/// Gets an array of commands that can be run sequentially to set $profile and run the profile commands.
///
/// The id identifying the host or shell used in profile file names.
/// used from test not to overwrite the profile file names from development boxes
/// An array of commands.
internal static PSCommand[] GetProfileCommands(string shellId, bool useTestProfile)
{
List commands = new List();
string allUsersAllHosts = HostUtilities.GetFullProfileFileName(null, false, useTestProfile);
string allUsersCurrentHost = HostUtilities.GetFullProfileFileName(shellId, false, useTestProfile);
string currentUserAllHosts = HostUtilities.GetFullProfileFileName(null, true, useTestProfile);
string currentUserCurrentHost = HostUtilities.GetFullProfileFileName(shellId, true, useTestProfile);
PSObject dollarProfile = HostUtilities.GetDollarProfile(allUsersAllHosts, allUsersCurrentHost, currentUserAllHosts, currentUserCurrentHost);
PSCommand command = new PSCommand();
command.AddCommand("set-variable");
command.AddParameter("Name", "profile");
command.AddParameter("Value", dollarProfile);
command.AddParameter("Option", ScopedItemOptions.None);
commands.Add(command);
string[] profilePaths = new string[] { allUsersAllHosts, allUsersCurrentHost, currentUserAllHosts, currentUserCurrentHost };
foreach (string profilePath in profilePaths)
{
if (!System.IO.File.Exists(profilePath))
{
continue;
}
command = new PSCommand();
command.AddCommand(profilePath, false);
commands.Add(command);
}
return commands.ToArray();
}
///
/// Used to get all profile file names for the current or all hosts and for the current or all users.
///
/// null for all hosts, not null for the specified host
/// false for all users, true for the current user.
/// The profile file name matching the parameters.
internal static string GetFullProfileFileName(string shellId, bool forCurrentUser)
{
return HostUtilities.GetFullProfileFileName(shellId, forCurrentUser, false);
}
///
/// Used to get all profile file names for the current or all hosts and for the current or all users.
///
/// null for all hosts, not null for the specified host
/// false for all users, true for the current user.
/// used from test not to overwrite the profile file names from development boxes
/// The profile file name matching the parameters.
internal static string GetFullProfileFileName(string shellId, bool forCurrentUser, bool useTestProfile)
{
string basePath = null;
if (forCurrentUser)
{
basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
basePath = System.IO.Path.Combine(basePath, "WindowsPowerShell");
}
else
{
basePath = GetAllUsersFolderPath(shellId);
if (string.IsNullOrEmpty(basePath))
{
return string.Empty;
}
}
string profileName = useTestProfile ? "profile_test.ps1" : "profile.ps1";
if (!string.IsNullOrEmpty(shellId))
{
profileName = shellId + "_" + profileName;
}
string fullPath = basePath = System.IO.Path.Combine(basePath, profileName);
return fullPath;
}
///
/// Used internally in GetFullProfileFileName to get the base path for all users profiles.
///
/// The shellId to use.
/// the base path for all users profiles.
private static string GetAllUsersFolderPath(string shellId)
{
string folderPath = string.Empty;
try
{
folderPath = GetApplicationBase(shellId);
}
catch (System.Security.SecurityException)
{
}
return folderPath;
}
///
/// Gets the registry key used to install Windows PowerShell.
///
/// The parameter is not used.
/// The regisrty key.
private static string GetApplicationBase(string shellId)
{
string engineKeyPath = PowerShellRootKeyPath + "\\" +
RegistryVersionKey + "\\" + PowerShellEngineKey;
using (RegistryKey engineKey = Registry.LocalMachine.OpenSubKey(engineKeyPath))
{
if (engineKey != null)
{
return engineKey.GetValue(PowerShellEngineApplicationBase) as string;
}
}
// 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();
if (assem != null)
{
// For minishells, we just return the executable path.
return Path.GetDirectoryName(assem.Location);
}
// For unmanaged host apps, look for the SMA dll, if it's not GAC'ed then
// use it's location as the application base...
assem = Assembly.GetAssembly(typeof(System.Management.Automation.PSObject));
if (assem != null)
{
// For for other hosts.
return Path.GetDirectoryName(assem.Location);
}
// Otherwise, just give up.
return string.Empty;
}
}
}