// // 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 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 /// current 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 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 identifier of the host or shell used in profile file names. /// The commands used to set $profile. internal 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 /// The commands used to set $profile. 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 regisrty 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; } } }