MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4namespace System.Management.Automation.Internal5{6 using System;7 using System.Diagnostics.CodeAnalysis;8 using System.Globalization;9 using System.IO;10 using System.Management.Automation;11 using System.Reflection;12 13 /// <summary>14 /// Helper to access Microsoft.PowerShell.GraphicalHost.dll (which references on WPF) using reflection, since15 /// we do not want System.Management.Automation.dll or Microsoft.PowerShell.Commands.Utility.dll to reference WPF.16 /// Microsoft.PowerShell.GraphicalHost.dll contains:17 /// 1) out-gridview window implementation (the actual cmdlet is in Microsoft.PowerShell.Commands.Utility.dll)18 /// 2) show-command window implementation (the actual cmdlet is in Microsoft.PowerShell.Commands.Utility.dll)19 /// 3) the help window used in the System.Management.Automation.dll's get-help cmdlet when -ShowWindow is specified.20 /// </summary>21 internal sealed class GraphicalHostReflectionWrapper22 {23 /// <summary>24 /// Initialized in GetGraphicalHostReflectionWrapper with the Microsoft.PowerShell.GraphicalHost.dll assembly.25 /// </summary>26 private Assembly _graphicalHostAssembly;27 28 /// <summary>29 /// A type in Microsoft.PowerShell.GraphicalHost.dll we want to invoke members on.30 /// </summary>31 private Type _graphicalHostHelperType;32 33 /// <summary>34 /// An object in Microsoft.PowerShell.GraphicalHost.dll of type graphicalHostHelperType.35 /// </summary>36 private object _graphicalHostHelperObject;37 38 /// <summary>39 /// Prevents a default instance of the GraphicalHostReflectionWrapper class from being created.40 /// </summary>41 private GraphicalHostReflectionWrapper()42 {43 }44 45 /// <summary>46 /// Retrieves a wrapper used to invoke members of the type with name <paramref name="graphicalHostHelperTypeName"/>47 /// in Microsoft.PowerShell.GraphicalHost.dll.48 /// </summary>49 /// <param name="parentCmdlet">The cmdlet requesting the wrapper (used to throw terminating errors).</param>50 /// <param name="graphicalHostHelperTypeName">The type name we want to invoke members from.</param>51 /// <returns>52 /// wrapper used to invoke members of the type with name <paramref name="graphicalHostHelperTypeName"/>53 /// in Microsoft.PowerShell.GraphicalHost.dll54 /// </returns>55 /// <exception cref="RuntimeException">When it was not possible to load Microsoft.PowerShell.GraphicalHost.dlly.</exception>56 internal static GraphicalHostReflectionWrapper GetGraphicalHostReflectionWrapper(PSCmdlet parentCmdlet, string graphicalHostHelperTypeName)57 {58 return GetGraphicalHostReflectionWrapper(parentCmdlet, graphicalHostHelperTypeName, parentCmdlet.CommandInfo.Name);59 }60 61 /// <summary>62 /// Retrieves a wrapper used to invoke members of the type with name <paramref name="graphicalHostHelperTypeName"/>63 /// in Microsoft.PowerShell.GraphicalHost.dll.64 /// </summary>65 /// <param name="parentCmdlet">The cmdlet requesting the wrapper (used to throw terminating errors).</param>66 /// <param name="graphicalHostHelperTypeName">The type name we want to invoke members from.</param>67 /// <param name="featureName">Used for error messages.</param>68 /// <returns>69 /// wrapper used to invoke members of the type with name <paramref name="graphicalHostHelperTypeName"/>70 /// in Microsoft.PowerShell.GraphicalHost.dll71 /// </returns>72 /// <exception cref="RuntimeException">When it was not possible to load Microsoft.PowerShell.GraphicalHost.dlly.</exception>73 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Assembly.Load has been found to throw unadvertised exceptions")]74 internal static GraphicalHostReflectionWrapper GetGraphicalHostReflectionWrapper(PSCmdlet parentCmdlet, string graphicalHostHelperTypeName, string featureName)75 {76 GraphicalHostReflectionWrapper returnValue = new();77 78 if (IsInputFromRemoting(parentCmdlet))79 {80 ErrorRecord error = new ErrorRecord(81 new NotSupportedException(StringUtil.Format(HelpErrors.RemotingNotSupportedForFeature, featureName)),82 "RemotingNotSupported",83 ErrorCategory.InvalidOperation,84 parentCmdlet);85 86 parentCmdlet.ThrowTerminatingError(error);87 }88 89 // Prepare the full assembly name.90 AssemblyName smaAssemblyName = typeof(PSObject).Assembly.GetName();91 AssemblyName graphicalHostAssemblyName = new();92 graphicalHostAssemblyName.Name = "Microsoft.PowerShell.GraphicalHost";93 graphicalHostAssemblyName.Version = smaAssemblyName.Version;94 graphicalHostAssemblyName.CultureInfo = new CultureInfo(string.Empty); // Neutral culture95 graphicalHostAssemblyName.SetPublicKeyToken(new byte[] { 0x31, 0xbf, 0x38, 0x56, 0xad, 0x36, 0x4e, 0x35 });96 97 try98 {99 returnValue._graphicalHostAssembly = Assembly.Load(graphicalHostAssemblyName);100 }101 catch (FileNotFoundException fileNotFoundEx)102 {103 // This exception is thrown if the Microsoft.PowerShell.GraphicalHost.dll could not be found (was not installed).104 string errorMessage = StringUtil.Format(105 HelpErrors.GraphicalHostAssemblyIsNotFound,106 featureName,107 fileNotFoundEx.Message);108 109 parentCmdlet.ThrowTerminatingError(110 new ErrorRecord(111 new NotSupportedException(errorMessage, fileNotFoundEx),112 "ErrorLoadingAssembly",113 ErrorCategory.ObjectNotFound,114 graphicalHostAssemblyName));115 }116 catch (Exception e)117 {118 parentCmdlet.ThrowTerminatingError(119 new ErrorRecord(120 e,121 "ErrorLoadingAssembly",122 ErrorCategory.ObjectNotFound,123 graphicalHostAssemblyName));124 }125 126 returnValue._graphicalHostHelperType = returnValue._graphicalHostAssembly.GetType(graphicalHostHelperTypeName);127 128 Diagnostics.Assert(returnValue._graphicalHostHelperType != null, "the type should exist in Microsoft.PowerShell.GraphicalHost");129 ConstructorInfo constructor = returnValue._graphicalHostHelperType.GetConstructor(130 BindingFlags.NonPublic | BindingFlags.Instance,131 null,132 Array.Empty<Type>(),133 null);134 135 if (constructor != null)136 {137 returnValue._graphicalHostHelperObject = constructor.Invoke(Array.Empty<object>());138 Diagnostics.Assert(returnValue._graphicalHostHelperObject != null, "the constructor does not throw anything");139 }140 141 return returnValue;142 }143 144 /// <summary>145 /// Used to escape characters that are not friendly to WPF binding.146 /// </summary>147 /// <param name="propertyName">Property name to be used in binding.</param>148 /// <returns>String with escaped characters.</returns>149 internal static string EscapeBinding(string propertyName)150 {151 return propertyName.Replace("/", " ").Replace(".", " ");152 }153 154 /// <summary>155 /// Calls an instance method with name <paramref name="methodName"/> passing the <paramref name="arguments"/>156 /// </summary>157 /// <param name="methodName">Name of the method to call.</param>158 /// <param name="arguments">Arguments to call the method with.</param>159 /// <returns>The method return value.</returns>160 internal object CallMethod(string methodName, params object[] arguments)161 {162 Diagnostics.Assert(_graphicalHostHelperObject != null, "there should be a constructor in order to call an instance method");163 MethodInfo method = _graphicalHostHelperType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);164 Diagnostics.Assert(method != null, "method " + methodName + " exists in graphicalHostHelperType is verified by caller");165 return method.Invoke(_graphicalHostHelperObject, arguments);166 }167 168 /// <summary>169 /// Calls a static method with name <paramref name="methodName"/> passing the <paramref name="arguments"/>170 /// </summary>171 /// <param name="methodName">Name of the method to call.</param>172 /// <param name="arguments">Arguments to call the method with.</param>173 /// <returns>The method return value.</returns>174 internal object CallStaticMethod(string methodName, params object[] arguments)175 {176 MethodInfo method = _graphicalHostHelperType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);177 Diagnostics.Assert(method != null, "method " + methodName + " exists in graphicalHostHelperType is verified by caller");178 return method.Invoke(null, arguments);179 }180 181 /// <summary>182 /// Gets the value of an instance property with name <paramref name="propertyName"/>183 /// </summary>184 /// <param name="propertyName">Name of the instance property to get the value from.</param>185 /// <returns>The value of an instance property with name <paramref name="propertyName"/></returns>186 internal object GetPropertyValue(string propertyName)187 {188 Diagnostics.Assert(_graphicalHostHelperObject != null, "there should be a constructor in order to get an instance property value");189 PropertyInfo property = _graphicalHostHelperType.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);190 Diagnostics.Assert(property != null, "property " + propertyName + " exists in graphicalHostHelperType is verified by caller");191 return property.GetValue(_graphicalHostHelperObject, Array.Empty<object>());192 }193 194 /// <summary>195 /// Gets the value of a static property with name <paramref name="propertyName"/>196 /// </summary>197 /// <param name="propertyName">Name of the static property to get the value from.</param>198 /// <returns>The value of a static property with name <paramref name="propertyName"/></returns>199 internal object GetStaticPropertyValue(string propertyName)200 {201 PropertyInfo property = _graphicalHostHelperType.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Static);202 Diagnostics.Assert(property != null, "property " + propertyName + " exists in graphicalHostHelperType is verified by caller");203 return property.GetValue(null, Array.Empty<object>());204 }205 206 /// <summary>207 /// Returns true if the <paramref name="parentCmdlet"/> is being run remotely.208 /// </summary>209 /// <param name="parentCmdlet">Cmdlet we want to see if is running remotely.</param>210 /// <returns>True if the <paramref name="parentCmdlet"/> is being run remotely.</returns>211 private static bool IsInputFromRemoting(PSCmdlet parentCmdlet)212 {213 Diagnostics.Assert(parentCmdlet.SessionState != null, "SessionState should always be available.");214 215 PSVariable senderInfo = parentCmdlet.SessionState.PSVariable.Get("PSSenderInfo");216 return senderInfo != null;217 }218 }219}220 