// // 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"; /// /// 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 /// current user and current host. /// A PSObject whose base object is currentUserCurrentHost /// and with notes for the other four 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. /// /// Identifies the host or shell used in /// the profile file names. /// 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. /// /// Identifies the host or shell used in /// the profile file names. /// Used from test not to overwrite /// the profile file names from development boxes. /// The profile 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; } // /// Gets the registry key used to install Windows PowerShell. /// /// The parameter is not used. /// The registry key. internal 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; } /// /// 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; } } }