Memory Violation Dynamically Appending to Methods at runtime - c#

Disclaimer: I'm doing this for learning purposes. This is not going to be used in code.
I'm trying to understand how method table are structure for generics, I want to dynamically appending to methods at runtime. I found a very useful stack overflow question reference for getting me started.
I have a simple controller which I'm using as a test to verify my methods are swapping:
public class ValuesController : ControllerBase
{
static ValuesController() {
var methodToReplace = typeof(ValuesController).GetMethod(nameof(ValuesController.Seven),
BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var methodToAppend = typeof(ValuesController).GetMethod(nameof(ValuesController.Eight),
BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
new Initializer(methodToReplace, methodToAppend);
}
[HttpGet("Seven")]
public int Seven(string id)
{
return 7;
}
[HttpGet("Eight")]
public int Eight(string id)
{
return 8;
}
}
I have a class Initializer which is in charge of handling appending to the method.
public class Initializer
{
public Initializer(MethodInfo methodToReplace, MethodInfo methodToAppend)
{
var dummyMethod = typeof(Initializer).GetMethod(nameof(Dummy),
BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var proxyMethod = typeof(Initializer).GetMethod(nameof(Proxy),
BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var appendedMethod = typeof(Initializer).GetMethod(nameof(Appended),
BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
dummyMethod.OneWayReplace(methodToReplace);
methodToReplace.OneWayReplace(proxyMethod);
appendedMethod.OneWayReplace(methodToAppend);
}
public int Proxy(string id)
{
Dummy(id);
return Appended(id);
}
public int Dummy(string id)
{
return 0;
}
public int Appended(string id)
{
return 0;
}
}
And then I have the Extensions which I've obtained from the original stackoverflow question:
public static class InjectionExtensions
{
// Note: This method replaces methodToReplace with methodToInject
// Note: methodToInject will still remain pointing to the same location
public static unsafe MethodReplacementState OneWayReplace(this MethodInfo methodToReplace, MethodInfo methodToInject)
{
//#if DEBUG
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
//#endif
MethodReplacementState state;
IntPtr tar = methodToReplace.MethodHandle.Value;
var inj = methodToInject.MethodHandle.Value + 8;
if (!methodToReplace.IsVirtual)
tar += 8;
else
{
var index = (int)(((*(long*)tar) >> 32) & 0xFF);
var classStart = *(IntPtr*)(methodToReplace.DeclaringType.TypeHandle.Value + (IntPtr.Size == 4 ? 40 : 64));
tar = classStart + IntPtr.Size * index;
}
#if DEBUG
tar = *(IntPtr*)tar + 1;
inj = *(IntPtr*)inj + 1;
state.Location = tar;
state.OriginalValue = new IntPtr(*(int*)tar);
*(int*)tar = *(int*)inj + (int)(long)inj - (int)(long)tar;
return state;
#else
state.Location = tar;
state.OriginalValue = *(IntPtr*)tar;
* (IntPtr*)tar = *(IntPtr*)inj;
return state;
#endif
}
}
Note: Using the current setup everything works fine. However, the second I change the Initializer class to be a generic class Initializer<T> I get a memory violation:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
My guess is that either the methodToReplace.DeclaringType.TypeHandle.Value calculation differs for generics, Or since the compiler is the one who generates the generic class it written to protected memory?
Edit
I've found more information I need to prepare the method properly when using generic parameters e.g:
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle, new[] { typeof(T).TypeHandle });
However there are still a few more pieces to the puzzle to get this working.
Edit
There are a few open source project's such as harmony that do similar things, However it looks like their emitting their own assemblies. While I've considered the option, I would still prefer to understand how I method tables work with generics
How can I append to methods that reside in generic classes?

I suppose you have already seen: Dynamically replace the contents of a C# method?
I have adapted some of those methods in my own project # https://github.com/juliusfriedman/net7mma_core/blob/master/Concepts/Classes/MethodHelper.cs
I think the problem is that if your are running with the Debugger Attached then you need to also handle the portion of the logic which is currently defined by IFDEF at compilation time and replace that with an System.Diagnostics.Debugger.IsAttached although the offsets calculations (to jump over the debugger injected code) will probably have to change depending on various things like the version of the framework in use.
See https://github.com/juliusfriedman/net7mma_core/blob/master/Concepts/Classes/MethodHelper.cs#L35
This works for me in .Net Core 3.1 when the debugger IS NOT attached and I am running in Release mode, when running in Debug mode with or without the debugger attached or in Release mode with the debugger attached I receive different exceptions. (In debug I receive Arithmetic Overflow, while in release I receive Execution Engine Exception).
Furthermore this only works until the JIT Tiering kicks in, if I run the method a 2nd time without the debugger attached I am getting a Internal CLR Error.
I believe this has to do with the code injected by the debugger when attached and to be honest I am not up to do date on exactly what the debugger is injecting when attached.
I would make a simplified repo of the problem and ask a question # https://github.com/dotnet/runtime if you need this to work with the debugger attached and I am sure someone there will guide you in the right direction.

Related

WPF application is double typing when 'EnablePointerSupport is set to true in app.config with 'DisableWPFTabletSupport'

I am trying to enable PointerSupport in my C#/WPF application.
After crawling through the web, I found a solution from MSDN,
which suggested adding the below line to the app.config' runtime section.
<AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
But in my application, I disabled the support for TabletDevices using the method **DisableWPFTabletSupport **from the below link.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/33828e1b-224a-4b73-86b5-9af949f07508/installing-net-452-breaks-microsofts-recommended-disablewpftabletsupport-method-for-disabling?forum=wpf
My project was working until i added the "EnablePointerSupport=true" line, but now the solution is throwing an exception at line 'devicesType.InvokeMember("HandleTabletRemoved",...)' in method DisableWPFTabletSupport below, saying HandleTabletRemoved is not available.
Exact exception details from VisualStudio:
System.MissingMethodException: 'Method 'System.Windows.Input.StylusPointer.PointerTabletDeviceCollection.HandleTabletRemoved' not found.
Code part to disable TabletSupport:
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the device class.
Type devicesType = devices.GetType();
// Loop until there are no more devices to remove.
int count = devices.Count + 1;
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
devicesType.InvokeMember("HandleTabletRemoved", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, null, devices, new object[] { (uint)0 });
count--;
if (devices.Count != count)
{
throw new Win32Exception("Unable to remove real-time stylus support.");
}
}
}
}
}
Problem statement:
When disabled "EnablePointerSupport=false" everything is working as it is getting input deviceType as '{System.Windows.Input.WispTabletDevice(LGD AIT Touch Controller)(LGD AIT Touch Controller)}'
and deleting all the deviceTypes without any issue.
But when enabled "EnablePointerSupport=true" [WHICH IS MY PRIMARY REQUIREMENT] it is getting input deviceType as '{System.Windows.Input.StylusPointer.PointerTabletDevice(LGD AIT Touch Controller))'
and getting the exception mentioned above which is.
System.MissingMethodException: 'Method 'System.Windows.Input.StylusPointer.PointerTabletDeviceCollection.HandleTabletRemoved' not found.'
Can anyone suggest how to solve this issue, as I cannot find or relate with any other articles with 'EnablePointerSupport' in WPF?
Possible solutions tried:
1. Updated .Net framework to <v4.5.2 (ex: v4.5.1), but the solution is failing as it has other dependencies
2. Updated .Net framework to >v4.5.2 (ex: v4.6), but getting the same exception with method not found.

How To Modify .Net Assembly At Runtime And Keep These Changes

Hello,
I just ask if there is a way in C#.Net to modify assembly at runtime,
What I mean
if I have a This class
public static class TimesTracker
{
public static int Rest = 3;
}
Now, I need at runtime to change Rest to 2 but keep those changes.
So, next time I Open my program I find Rest=2.
I know, I can use configuration file, DB, ... but I just ask about this possibility
Background
I know about Replacing methods implementation at run time, Also about Invoking/compiling string code With Roslyn at runtime
Interesting. However I can't think of any use case.
I used Mono.Cecil before in a MSBuild target to modify assemblies on the fly and save back to disk.
Here is an example how what you asked could be done:
var filePath = "Assembly path";
var updatedFilePath = "Updated assembly path";
// Read assembly
using (var assembly = AssemblyDefinition.ReadAssembly(filePath))
{
// Find type TimesTracker. This example was done in LINQPad, so TimesTracker is nested type inside UserQuery
var type = assembly.MainModule.Types.SelectMany(t => t.NestedTypes).First(td => td.Name == "TimesTracker");
// Find static constructor
var cctor = type.Methods.First(md => md.Name == ".cctor");
// Get IL
var il = cctor.Body.GetILProcessor();
// The IL of Rest = 3 is:
// IL_0000: ldc.i4.3
// IL_0001: stsfld int32 UserQuery / TimesTracker::Rest
var op = il.Body.Instructions.First(i => i.OpCode == OpCodes.Ldc_I4_3);
// Replace 3 with 7
var newOp = il.Create(OpCodes.Ldc_I4_7);
il.Replace(op, newOp);
// Write updated to another assembly file
assembly.Write(updatedFilePath);
}
// Load updated assembly into AppDomain
var updatedAssembly = Assembly.LoadFile(updatedFilePath);
// Use reflection to get value of Rest
var updatedType = updatedAssembly.DefinedTypes.First(t => t.Name.Contains("TimesTracker"));
var field = updatedType.GetField("Rest", BindingFlags.Public | BindingFlags.Static);
// value is now 7
var value = (int)field.GetValue(null);
Note the above code can only modify:
public class TimesTracker
{
public static int Rest = 3;
}
However, because C# doesn't allow to reload assemblies unless unload entire AppDomain, using/loading the updated assembly would be a challenge.

Selenium with .net core: performance impact, multiple threads in IWebElement?

I've been using Selenium for writing an end to end tests using the .net framework 4.6.
For a new project I'm using Selenium to do some web crawling but I'm experiencing enormous lag on very simple Selenium tasks.
Please look at the screenshot below:
The code itself is here:
public IList<Category> ListAllParentCategories()
{
var categories = new List<Category>();
var liItems = _driver.FindElements(By.CssSelector(".nav__branch.branch ul.tree li"));
foreach(var liItem in liItems)
{
var innerLink = liItem.FindElement(By.TagName("a"));
var c = new Category();
c.Id = long.Parse(liItem.GetAttribute("id"));
c.Link = innerLink.GetAttribute("href");
c.Name = innerLink.Text;
c.Parent = null;
categories.Add(c);
}
return categories;
}
From my experience, this should not take minutes to complete. Basically, we're just looking for a list of LI elements and then we query for some more info related to that element, which does not require interaction from the browser as it's already contained in the WebElement.
Yet this procedure (for 22 categories) takes at least an entire minute. Fetching the innerlink.GetAttribute("id") takes an entire second.
Now while trying to figure out why this is happening, I've been removing all thread related stuff and right now this code runs from a Console app. There's no improvement at all.
A curious thing is that when I open the innerLink in the debugger, I can see that most properties are using another thread?! I assume this is what is causing the long delays?
My setup is as follows:
- Console app running .NET Core 2.0
Dependencies:
- Selenium.Chrome.WebDriver 2.32.00
- Selenium.WebDriver 3.6.0
Update: This problem is definitely related to the .NET core variant of Selenium Webdriver. After converting the project to a regular .NET Framework 4.6 Console app, everything is 10 times faster.
There is a dirty fix for the problem for now.
//this is in my Dependency Register method
string driverPath = $#"{AppDomain.CurrentDomain.BaseDirectory}";
var service = FirefoxDriverService.CreateDefaultService(driverPath);
container.RegisterInstance<IWebDriver>(new FirefoxDriver(service), new PerThreadLifetimeManager());
FixDriverCommandExecutionDelay(container.Resolve<IWebDriver>());
and the method looks something like this:
//to be deleted when https://github.com/dotnet/corefx/issues/24104 is fixed
//in .net core 2.0
public static void FixDriverCommandExecutionDelay(IWebDriver driver)
{
PropertyInfo commandExecutorProperty = typeof(RemoteWebDriver).GetProperty("CommandExecutor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty);
ICommandExecutor commandExecutor = (ICommandExecutor)commandExecutorProperty.GetValue(driver);
FieldInfo remoteServerUriField = commandExecutor.GetType().GetField("remoteServerUri", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField);
if (remoteServerUriField == null)
{
FieldInfo internalExecutorField = commandExecutor.GetType().GetField("internalExecutor", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
commandExecutor = (ICommandExecutor)internalExecutorField.GetValue(commandExecutor);
remoteServerUriField = commandExecutor.GetType().GetField("remoteServerUri", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField);
}
if (remoteServerUriField != null)
{
string remoteServerUri = remoteServerUriField.GetValue(commandExecutor).ToString();
string localhostUriPrefix = "http://localhost";
if (remoteServerUri.StartsWith(localhostUriPrefix))
{
remoteServerUri = remoteServerUri.Replace(localhostUriPrefix, "http://127.0.0.1");
remoteServerUriField.SetValue(commandExecutor, new Uri(remoteServerUri));
}
}
the answer to the problem is explained fully in this thread: https://github.com/dotnet/corefx/issues/24104
Answer taken from there also, credits given to the good folks!
It works for me on FF driver v0.19.1, Selenium v3.8

How to switch on/off statistics panel in editor while playing?

I want to switch this panel on/off by C# script while playing.
Is this possible? Haven't found any Editor API functions for this.
You can do it with reflection. Modified similar answer I made long ago. Below is a working set/get stats function. Tested with Unity 5.4.0f1. I put the Unity version so that people won't complain when it stops working. Unity's update can break this anytime if they rename any of the variables.
GameView = A class that is used to represent Unity GameView tab in
the Editor.
GetMainGameView = static function that returns current GameView
instance.
m_Stats = a boolean variable that is used to determine if stats
should be displayed or not.
Code:
//Show/Hide stats
void showStats(bool enableStats)
{
Assembly asm = Assembly.GetAssembly(typeof(Editor));
Type type = asm.GetType("UnityEditor.GameView");
if (type != null)
{
MethodInfo gameViewFunction = type.GetMethod("GetMainGameView", BindingFlags.Static |
BindingFlags.NonPublic);
object gameViewInstance = gameViewFunction.Invoke(null, null);
FieldInfo getFieldInfo = type.GetField("m_Stats", BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public);
getFieldInfo.SetValue(gameViewInstance, enableStats);
}
}
//Returns true if stats is enabled
bool statsIsEnabled()
{
Assembly asm = Assembly.GetAssembly(typeof(Editor));
Type type = asm.GetType("UnityEditor.GameView");
if (type != null)
{
MethodInfo gameViewFunction = type.GetMethod("GetMainGameView", BindingFlags.Static |
BindingFlags.NonPublic);
object gameViewInstance = gameViewFunction.Invoke(null, null);
FieldInfo getFieldInfo = type.GetField("m_Stats", BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public);
return (bool)getFieldInfo.GetValue(gameViewInstance);
}
return false;
}
Usage:
//Show stats
showStats(true);
//Hide stats
showStats(false);
//Read stats
bool stats = statsIsEnabled();
No it's not possible, unless you are a persistent hacker. GameView is an internal class, not accessible for editor scripting. But hey, there always is an option for good ol' reflection. This question will set you on the right track:
http://answers.unity3d.com/questions/179775/game-window-size-from-editor-window-in-editor-mode.html

HttpModule to add headers to request

This seems like a simple operation.
We have a need in our development environment (running on XP/IIS 5) to add some headers into each HttpRequest arriving at our application. (This is to simulate a production environment that we don't have available in dev). At first blush, this seemed like a simple HttpModule, along the lines of:
public class Dev_Sim: IHttpModule
{
public void Init(HttpApplication app)
{
app.BeginRequest += delegate { app.Context.Request.Headers.Add("UserName", "XYZZY"); };
}
public void Dispose(){}
}
But on trying to do that, I find that the Headers collection of the Request is read-only, and the Add method fails with an OperationNotSupported exception.
Spending a couple hours researching this on Google, I've come up with no easy answer to what should be a relatively straight-forward problem.
Does anyone have any pointers?
Okay, with the assistance of a co-worker and some experimentation, I found that this can be done with the assistance of some protected properties and methods accessed through reflection:
var headers = app.Context.Request.Headers;
Type hdr = headers.GetType();
PropertyInfo ro = hdr.GetProperty("IsReadOnly",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
// Remove the ReadOnly property
ro.SetValue(headers, false, null);
// Invoke the protected InvalidateCachedArrays method
hdr.InvokeMember("InvalidateCachedArrays",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, headers, null);
// Now invoke the protected "BaseAdd" method of the base class to add the
// headers you need. The header content needs to be an ArrayList or the
// the web application will choke on it.
hdr.InvokeMember("BaseAdd",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, headers,
new object[] { "CustomHeaderKey", new ArrayList {"CustomHeaderContent"}} );
// repeat BaseAdd invocation for any other headers to be added
// Then set the collection back to ReadOnly
ro.SetValue(headers, true, null);
This works for me, at least.
You can add to the Header this way. This is a way to add credential information to the request before it enter the authentication sequence.
string cred = "UN:PW";
System.Web.HttpContext.Current.Request.Headers.Add("Authorization", "Basic " +Convert.ToBase64String(Encoding.ASCII.GetBytes(cred)));

Categories

Resources