How can I change field value with Mono Cecil? - c#

I have a C# program and it has a class:
public class Test
{
internal const string a = "some value";
private DateTime b = new DateTime();
}
How can I use Mono Cecil to change their initial value so that it looks like this:
public class Test
{
internal const string a = "test";
private DateTime b = DateTime.MaxValue;
}
Right now I only have the following skeleton code and I don't know how to modify the fields.
void Main()
{
var input = #"C:\my_projects\a.exe";
var asm = AssemblyDefinition.ReadAssembly(input);
foreach (ModuleDefinition module in asm.Modules)
{
foreach (TypeDefinition type in module.GetTypes())
{
foreach (var field in type.Fields)
{
if (field.Name == "a")
{
}
else if (field.Name == "b")
{
}
}
}
}
asm.Write(#"c:\my_projects\b.exe");
}

Disclaimer
Very brittle code ahead
For the constant it is a matter of setting fld.Constant property.
For instance/static fields the C# compiler will emit the initialization code in the constructor, so you'll need to find the instruction that is loading the value that will be stored in the field and replace it.
using System.IO;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace x
{
class Program
{
public const string ConstValue = "old";
public int instanceField = 1;
static void Main(string[] args)
{
var o = new Program();
if (o.instanceField == 1)
{
using var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var t = a.MainModule.Types.Single(ct => ct.Name == "Program");
var constant = t.Fields.First(f => f.Name == "ConstValue");
constant.Constant = "new value";
var ctor = t.Methods.Single(m => m.IsConstructor);
System.Console.WriteLine(ctor);
var il = ctor.Body.GetILProcessor();
var inst = il.Body.Instructions.First();
while (inst != null)
{
System.Console.WriteLine($"Checking {inst}");
if (inst.OpCode == OpCodes.Stfld && ((FieldReference) inst.Operand).Name == "instanceField")
{
// notice that this is very fragile. For this specific
// case I'd say it is safe but depending on how you
// initialize the field the instruction that loads
// the value to be assigned to the field may be located
// several instructions prior to the actual assignment
// but you can keep track of the stack state and figure
// out which instruction is pushing the value that
// will end up being poped into the field.
il.Replace(inst.Previous, il.Create(OpCodes.Ldc_I4, 42));
System.Console.WriteLine("Found");
break;
}
inst = inst.Next;
}
var p = typeof(Program).Assembly.Location;
var newBinaryPath = Path.Combine(Path.GetDirectoryName(p), Path.GetFileNameWithoutExtension(p) + "2" +Path.GetExtension(p));
a.Write(newBinaryPath);
System.Console.WriteLine($"New binary writen to {newBinaryPath}");
}
System.Console.WriteLine(o.instanceField);
// Notice that no matter what you do, this will always print the
// old value; that happens because the C# compiler will emit the
// constant at the call site (instead of referencing the field
// at runtime)
System.Console.WriteLine(ConstValue);
}
}
}

Related

Looking to check for one's or zeros in a Bitstring

Does anyone have an idea how to check for one's or zeros in a Bitstring? The below code checks for ones and zeros in a string, but I would like to add an extension bitstring that does the same thing. This way, I can use the method on the bitstring itself with out having to first evaluate the string.
Currently, I have to check before I entered the bitstring method.
string MustBeBitsInStringOnesOrZeros = "11001";
bool boTesting = Is1Or0(MustBeBitsInStringOnesOrZeros);
// I would like to add an extension to check for ones and zeros
// Example: MustBeBitsInStringOnesOrZeros.Is1Or0();
if (boTesting == true)
{
Bitstring a = new Bitstring(MustBeBitsInStringOnesOrZeros);
}
else
{
string b = MustBeBitsInStringOnesOrZeros;
}
private static bool Is1Or0(string stringBit)
{
// This function check each
// character in a string for "1"
// or "0".
bool results = false;
for (int i = 0; i < stringBit.Length; i++)
{
var x = stringBit[i];
if (x == '1' || x == '0')
{
results = true;
}
else
{
results = false;
break;
}
}
return results;
}
===
Modified to show results of Bassie's example from a sealed class.
Bassie,
Well, what I was trying to say was that I cannot place the method in the sealed class with the keyword 'this' in the method. So I created another class but, I have to use it a different way and I wanted to use it the way you call it.
//I have to use it this way:
Bitstring OnesAndZeroCheck = new Bitstring(); // Bitstring is in a sealed class
Boolean g = OnesAndZeroCheck.IsBitstring2("1100111100011100101010101010101101010101010"); // Is in the sealed class
//but want to call it this way:
var successInput = "1101";
successInput.Is1Or0(); // true
If I understand you correctly, you could define your extension method like this
public static class StringExtensions
{
public static bool Is1Or0(this string stringBit)
=> stringBit.All(c => c == '1' || c == '0');
}
And call with
var successInput = "1101";
successInput.Is1Or0(); // true
var failureInput = "1121"
failureInput.Is1Or0(); // false
From MSDN Enumerable.All:
Determines whether all elements of a sequence satisfy a condition.
This works because a string is actually just an IEnumerable of char - so when we call the IEnumerable.All() extension method, we check the condition against each individual char in the string
Note you will need to include using System.Linq; to your file that contains the extension method
tested in video.
https://youtu.be/CgMFYctc3Ak
public static bool isBitstring(string s)
{
foreach (char c in s)
{
if (!(c >= '0' && c <= '1')) {
return false;
}
}
return true;
}
string str = "100000011100101010010101";
if (isBitstring(str))
{
Console.WriteLine("is Bitstring");
}
else
{
Console.WriteLine("is not Bitstring");
}

Convert var into List<MapPdf>

I have a program that I used a variable of type List < MapPdf > that I will detach in variables when filling I would like to have the possibility to use it another time but I did not have the right to identify it again as
public static void Create(List<MapPdf> pps, Saison s, Agence agence)
{
foreach (var pelerins in grouped)
{
if (string.IsNullOrEmpty(pelerins.Key) || pelerins.Count() <= 0)
break;
if (writer.PageEvent == null)
{
writer.PageEvent = new Header_List()
{
travel = ctx.Travels.Include("Transport").First(v => v.UniqueId == pelerins.Key),
travelretour = ctx.Travels.Find(pelerins.First().UniqueIdRetour),
Agence = agence,
CountAllPelerin = pelerins.Count().ToString(),
CountFeminin = pelerins.Count(x => x.Sexe == PelerinSexe.Feminin).ToString(),
CountMasculin = pelerins.Count(x => x.Sexe == PelerinSexe.Masculin).ToString(),
NomGroupe = pelerins.First().Groupe,
NumeroDoc = writer.PageNumber
};
}
}
}
And i want to use pelerins as a List when i used in another function when it is of this declaration
I used List < MapPdf > pls = pelerins.ToList(); but it does not work
CreateFr(pls, false, cb, s);
If you are referring to var pelerins within the for-each loop and if I understand the problem, you are unable use it into another method , because var pelerins is a local variable encapsulated within the for-each loop -It does not exist outside it.
You could do the following:
//public property to retrieve pelerins
public List <MapPdf> pls new List<MapPdf>();
...
...
public static void Create(List<MapPdf> pps, Saison s, Agence agence)
{
foreach (var pelerins in grouped)
{
if (string.IsNullOrEmpty(pelerins.Key) || pelerins.Count() <= 0)
break;
if (writer.PageEvent == null)
{
//do logic
...
//store the one you are interested in, so you can use it later on
pls = pelerins.ToList();
}
}
}

Is there a way to check the data in advance of runtime if it's not the correct type?

I occasionally get data that is not completely clean, and during runtime I get error messages because the data doesn't match the expected type. For example, sometimes the data has a string where there should be an int, or an int where there should be a date.
Is there a way to scan the data first for bad data, so that I can fix it all at once instead of finding out during run-time and fixing it iteratively?
Here's my code which works:
class TestScore{
public string Name;
public int Age;
public DateTime Date;
public DateTime Time;
public double Score;
}
//read data
var Data = File.ReadLines(FilePath).Select(line => line.Split('\t')).ToArray();
//select data
var query = from x in Data
select new { Name = x[3], Age = x[1], Date = x[2], Time = x[5], Score = x[7] };
//create List and put data into List
List<TestScore> Results = new List<TestScore>();
for (int i = 0; i < query.Count; i++)
{
TestScore TS = new TestScore();
TS.Name = query[i].Name;
TS.Age = query[i].Age;
TS.Date = query[i].Date;
TS.Time = query[i].Time;
TS.Score = query[i].Score;
Results.Add(TS);
}
Is there a way to scan the data first for bad data, so that I can fix
it all at once instead of finding out during run-time and fixing it
iteratively?
Scanning is a runtime operation. However, it's fairly straightforward to implement a solution that gives you enough information to "fix it all at once".
The following code shows a pattern for validating the file in its entirety, and doesn't attempt to load any data unless it completely succeeds.
If it fails, a collection of all errors encountered is returned.
internal sealed class ParseStatus
{
internal bool IsSuccess;
internal IReadOnlyList<string> Messages;
}
private ParseStatus Load()
{
string filePath = "foo";
var data = File.ReadLines( filePath ).Select( line => line.Split( '\t' ) ).ToArray();
var results = from x in data
select new { Name = x[3], Age = x[1], Date = x[2], Time = x[5], Score = x[7] };
var errors = new List<string>();
int row = 0;
// first pass: look for errors by testing each value
foreach( var line in results )
{
row++;
int dummy;
if( !int.TryParse( line.Age, out dummy ) )
{
errors.Add( "Age couldn't be parsed as an int on line " + row );
}
// etc...use exception-free checks on each property
}
if( errors.Count > 0 )
{
// quit, and return errors list
return new ParseStatus { IsSuccess = false, Messages = errors };
}
// otherwise, it is safe to load all rows
// TODO: second pass: load the data
return new ParseStatus { IsSuccess = true };
}
For not finding out the errors during run-time, the best thing that I can think of would be to correct the data manually before your program runs ..
But as we are trying do things constructive, I think that using a static readonly field to indicate the data error would be helpful. The following is a simple example which doesn't take the failed items, you might want to modify it when you are going to do some advanced handling.
public partial class TestScore {
public static TestScore Parse(String plainText) {
var strings=plainText.Split('\t');
var result=new TestScore();
if(
strings.Length<5
||
!double.TryParse(strings[4], out result.Score)
||
!DateTime.TryParse(strings[3], out result.Time)
||
!DateTime.TryParse(strings[2], out result.Date)
||
!int.TryParse(strings[1], out result.Age)
)
return TestScore.Error;
result.Name=strings[0];
return result;
}
public String Name;
public int Age;
public DateTime Date;
public DateTime Time;
public double Score;
public static readonly TestScore Error=new TestScore();
}
public static partial class TestClass {
public static void TestMethod() {
var path=#"some tab splitted file";
var lines=File.ReadAllLines(path);
var format=""
+"Name: {0}; Age: {1}; "
+"Date: {2:yyyy:MM:dd}; Time {3:hh:mm}; "
+"Score: {4}";
var list=(
from line in lines
where String.Empty!=line
let result=TestScore.Parse(line)
where TestScore.Error!=result
select result).ToList();
foreach(var item in list) {
Console.WriteLine(
format,
item.Name, item.Age, item.Date, item.Time, item.Score
);
}
}
}

C#. Set a member object value using reflection

I need your help with the following code below. Basically I have a class called "Job" which has some public fields. I'm passing to my method "ApplyFilter" two parameters "job_in" and "job_filters". First parameter contains actual data, and the second one has instructions (if any). I need to iterate through "job_in" object, read it's data, apply any instructions by reading "job_filters", modify data (if needed) and return it in a new "job_out" object. Everything works fine till i need to store my data in "job_out" object:
public class Job
{
public string job_id = "";
public string description = "";
public string address = "";
public string details = "";
}
...
private Job ApplyFilters(Job job_in, Job job_filters)
{
Type type = typeof(Job);
Job job_out = new Job();
FieldInfo[] fields = type.GetFields();
// iterate through all fields of Job class
for (int i = 0; i < fields.Length; i++)
{
List<string> filterslist = new List<string>();
string filters = (string)fields[i].GetValue(job_filters);
// if job_filters contaisn magic word "$" for the field, then do something with a field, otherwise just copy it to job_out object
if (filters.Contains("$"))
{
filters = filters.Substring(filters.IndexOf("$") + 1, filters.Length - filters.IndexOf("$") - 1);
// MessageBox.Show(filters);
// do sothing useful...
}
else
{
// this is my current field value
var str_value = fields[i].GetValue(job_in);
// this is my current filed name
var field_name = fields[i].Name;
// I got stuck here :(
// I need to save (copy) data "str_value" from job_in.field_name to job_out.field_name
// HELP!!!
}
}
return job_out;
}
Please help. I've seen a few samples by using properties, but i'm pretty sure it is possible to do the same with fields as well. Thanks!
Try this
public static void MapAllFields(object source, object dst)
{
System.Reflection.FieldInfo[] ps = source.GetType().GetFields();
foreach (var item in ps)
{
var o = item.GetValue(source);
var p = dst.GetType().GetField(item.Name);
if (p != null)
{
Type t = Nullable.GetUnderlyingType(p.FieldType) ?? p.FieldType;
object safeValue = (o == null) ? null : Convert.ChangeType(o, t);
p.SetValue(dst, safeValue);
}
}
}
fields[i].SetValue(job_out, str_value);

Get types used inside a C# method body

Is there a way to get all types used inside C# method?
For example,
public int foo(string str)
{
Bar bar = new Bar();
string x = "test";
TEST t = bar.GetTEST();
}
would return: Bar, string and TEST.
All I can get now is the method body text using EnvDTE.CodeFunction. Maybe there is a better way to achieve it than trying to parse this code.
I'm going to take this opportunity to post up a proof of concept I did because somebody told me it couldn't be done - with a bit of tweaking here and there, it'd be relatively trivial to extend this to extract out all referenced Types in a method - apologies for the size of it and the lack of a preface, but it's somewhat commented:
void Main()
{
Func<int,int> addOne = i => i + 1;
Console.WriteLine(DumpMethod(addOne));
Func<int,string> stuff = i =>
{
var m = 10312;
var j = i + m;
var k = j * j + i;
var foo = "Bar";
var asStr = k.ToString();
return foo + asStr;
};
Console.WriteLine(DumpMethod(stuff));
Console.WriteLine(DumpMethod((Func<string>)Foo.GetFooName));
Console.WriteLine(DumpMethod((Action)Console.Beep));
}
public class Foo
{
public const string FooName = "Foo";
public static string GetFooName() { return typeof(Foo).Name + ":" + FooName; }
}
public static string DumpMethod(Delegate method)
{
// For aggregating our response
StringBuilder sb = new StringBuilder();
// First we need to extract out the raw IL
var mb = method.Method.GetMethodBody();
var il = mb.GetILAsByteArray();
// We'll also need a full set of the IL opcodes so we
// can remap them over our method body
var opCodes = typeof(System.Reflection.Emit.OpCodes)
.GetFields()
.Select(fi => (System.Reflection.Emit.OpCode)fi.GetValue(null));
//opCodes.Dump();
// For each byte in our method body, try to match it to an opcode
var mappedIL = il.Select(op =>
opCodes.FirstOrDefault(opCode => opCode.Value == op));
// OpCode/Operand parsing:
// Some opcodes have no operands, some use ints, etc.
// let's try to cover all cases
var ilWalker = mappedIL.GetEnumerator();
while(ilWalker.MoveNext())
{
var mappedOp = ilWalker.Current;
if(mappedOp.OperandType != OperandType.InlineNone)
{
// For operand inference:
// MOST operands are 32 bit,
// so we'll start there
var byteCount = 4;
long operand = 0;
string token = string.Empty;
// For metadata token resolution
var module = method.Method.Module;
Func<int, string> tokenResolver = tkn => string.Empty;
switch(mappedOp.OperandType)
{
// These are all 32bit metadata tokens
case OperandType.InlineMethod:
tokenResolver = tkn =>
{
var resMethod = module.SafeResolveMethod((int)tkn);
return string.Format("({0}())", resMethod == null ? "unknown" : resMethod.Name);
};
break;
case OperandType.InlineField:
tokenResolver = tkn =>
{
var field = module.SafeResolveField((int)tkn);
return string.Format("({0})", field == null ? "unknown" : field.Name);
};
break;
case OperandType.InlineSig:
tokenResolver = tkn =>
{
var sigBytes = module.SafeResolveSignature((int)tkn);
var catSig = string
.Join(",", sigBytes);
return string.Format("(SIG:{0})", catSig == null ? "unknown" : catSig);
};
break;
case OperandType.InlineString:
tokenResolver = tkn =>
{
var str = module.SafeResolveString((int)tkn);
return string.Format("('{0}')", str == null ? "unknown" : str);
};
break;
case OperandType.InlineType:
tokenResolver = tkn =>
{
var type = module.SafeResolveType((int)tkn);
return string.Format("(typeof({0}))", type == null ? "unknown" : type.Name);
};
break;
// These are plain old 32bit operands
case OperandType.InlineI:
case OperandType.InlineBrTarget:
case OperandType.InlineSwitch:
case OperandType.ShortInlineR:
break;
// These are 64bit operands
case OperandType.InlineI8:
case OperandType.InlineR:
byteCount = 8;
break;
// These are all 8bit values
case OperandType.ShortInlineBrTarget:
case OperandType.ShortInlineI:
case OperandType.ShortInlineVar:
byteCount = 1;
break;
}
// Based on byte count, pull out the full operand
for(int i=0; i < byteCount; i++)
{
ilWalker.MoveNext();
operand |= ((long)ilWalker.Current.Value) << (8 * i);
}
var resolved = tokenResolver((int)operand);
resolved = string.IsNullOrEmpty(resolved) ? operand.ToString() : resolved;
sb.AppendFormat("{0} {1}",
mappedOp.Name,
resolved)
.AppendLine();
}
else
{
sb.AppendLine(mappedOp.Name);
}
}
return sb.ToString();
}
public static class Ext
{
public static FieldInfo SafeResolveField(this Module m, int token)
{
FieldInfo fi;
m.TryResolveField(token, out fi);
return fi;
}
public static bool TryResolveField(this Module m, int token, out FieldInfo fi)
{
var ok = false;
try { fi = m.ResolveField(token); ok = true; }
catch { fi = null; }
return ok;
}
public static MethodBase SafeResolveMethod(this Module m, int token)
{
MethodBase fi;
m.TryResolveMethod(token, out fi);
return fi;
}
public static bool TryResolveMethod(this Module m, int token, out MethodBase fi)
{
var ok = false;
try { fi = m.ResolveMethod(token); ok = true; }
catch { fi = null; }
return ok;
}
public static string SafeResolveString(this Module m, int token)
{
string fi;
m.TryResolveString(token, out fi);
return fi;
}
public static bool TryResolveString(this Module m, int token, out string fi)
{
var ok = false;
try { fi = m.ResolveString(token); ok = true; }
catch { fi = null; }
return ok;
}
public static byte[] SafeResolveSignature(this Module m, int token)
{
byte[] fi;
m.TryResolveSignature(token, out fi);
return fi;
}
public static bool TryResolveSignature(this Module m, int token, out byte[] fi)
{
var ok = false;
try { fi = m.ResolveSignature(token); ok = true; }
catch { fi = null; }
return ok;
}
public static Type SafeResolveType(this Module m, int token)
{
Type fi;
m.TryResolveType(token, out fi);
return fi;
}
public static bool TryResolveType(this Module m, int token, out Type fi)
{
var ok = false;
try { fi = m.ResolveType(token); ok = true; }
catch { fi = null; }
return ok;
}
}
If you can access the IL for this method, you might be able to do something suitable. Perhaps look at the open source project ILSpy and see whether you can leverage any of their work.
As others have mentioned, if you had the DLL you could use something similar to what ILSpy does in its Analyze feature (iterating over all the IL instructions in the assembly to find references to a specific type).
Otherwise, there is no way to do it without parsing the text into a C# Abstract Syntax Tree, AND employing a Resolver - something that can understand the semantics of the code well enough to know if "Bar" in your example is indeed a name of a type that is accessible from that method (in its "using" scope), or perhaps the name of a method, member field, etc... SharpDevelop contains a C# parser (called "NRefactory") and also contains such a Resolver, you can look into pursuing that option by looking at this thread, but beware that it is a fair amount of work to set it up to work right.
I just posted an extensive example of how to use Mono.Cecil to do static code analysis like this.
I also show a CallTreeSearch enumerator class that can statically analyze call trees, looking for certain interesting things and generating results using a custom supplied selector function, so you can plug it with your 'payload' logic, e.g.
static IEnumerable<TypeUsage> SearchMessages(TypeDefinition uiType, bool onlyConstructions)
{
return uiType.SearchCallTree(IsBusinessCall,
(instruction, stack) => DetectTypeUsage(instruction, stack, onlyConstructions));
}
internal class TypeUsage : IEquatable<TypeUsage>
{
public TypeReference Type;
public Stack<MethodReference> Stack;
#region equality
// ... omitted for brevity ...
#endregion
}
private static TypeUsage DetectTypeUsage(
Instruction instruction, IEnumerable<MethodReference> stack, bool onlyConstructions)
{
TypeDefinition resolve = null;
{
TypeReference tr = null;
var methodReference = instruction.Operand as MethodReference;
if (methodReference != null)
tr = methodReference.DeclaringType;
tr = tr ?? instruction.Operand as TypeReference;
if ((tr == null) || !IsInterestingType(tr))
return null;
resolve = tr.GetOriginalType().TryResolve();
}
if (resolve == null)
throw new ApplicationException("Required assembly not loaded.");
if (resolve.IsSerializable)
if (!onlyConstructions || IsConstructorCall(instruction))
return new TypeUsage {Stack = new Stack<MethodReference>(stack.Reverse()), Type = resolve};
return null;
}
This leaves out a few details
implementation of IsBusinessCall, IsConstructorCall and TryResolve as these are trivial and serve as illustrative only
Hope that helps
The closest thing to that that I can think of are expression trees. Take a look at the documentation from Microsoft.
They are very limited however and only work on simple expressions and not full methods with statement bodies.
Edit: Since the intention of the poster was to find class couplings and used types, I would suggest using a commercial tool like NDepend to do the code analysis as an easy solution.
This definitely cannot be done from reflection (GetMethod(), Expression Trees, etc.). As you mentioned, using EnvDTE's CodeModel is an option since you get line-by-line C# there, but using it outside Visual Studio (that is, processing an already existing function, not in your editor window) is nigh-impossible, IMHO.
But I can recommend Mono.Cecil, which can process CIL code line-by-line (inside a method), and you can use it on any method from any assembly you have reference to. Then, you can check every line if it is a variable declaration (like string x = "test", or a methodCall, and you can get the types involved in those lines.
With reflection you can get the method. This returns a MethodInfo object, and with this object you cannot get the types which are used in the method. So I think the answer is that you cannot get this native in C#.

Categories