C# dll using issue - c#

I am having an issue with compiling a C# dll from a piece of code I wrote. it compiles just fine with no errors, but when I try to include it to a visual studio 2010 C# application the namespace does not show up while trying to call it from the "using" command.
Here is the code of the .dll file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PAD_SCRIPT;
using System.Threading;
namespace PARKER_SCRIPT
{
class PScript
{
//LOAD_REF
private void loadCustomScripts()
{
}
//END_REF
PADScript p = new PADScript();
private void loadScripts()
{
}
public PScript()
{
}
public void runFile(string file)
{
if (file.ToLower().Contains(".pb"))
{
//file = file.Replace(".pb", "");
p.executeLuaWithThread(file);
Console.ReadLine();
}
else
{
Console.WriteLine("ERROR 1: must be .pb file");
Console.ReadLine();
}
}
Core cp = new Core();
public PADScript loadScipt(PADScript l)
{
loadScripts();
loadCustomScripts();
l.addLuaCommand("runFile", this);
return l;
}
//this will be dynamically be updated when custom cs code gets added
private string[] getPatchNotes()
{
string[] info = null;
try
{
info = System.IO.File.ReadAllLines("info\\patch_notes.txt");
return info;
}
catch (Exception i)
{
Console.WriteLine(i.Message);
return info;
}
}
private string getVersion()
{
string info = null;
try
{
info = System.IO.File.ReadAllLines("info\\version.txt")[0];
return info;
}
catch (Exception i)
{
Console.WriteLine(i.Message);
return info;
}
}
}
}
I don't think the functions in the .dll file is an issue, but by compiling it on the command line I think I am missing a key parameter or something. I know when I compile it in visual studio it works just fine implementing it to a new project. Thank you in advance.
edit: here is the command line I did:
C:\WINDOWS\Microsoft.Net\Framework\v4.0.30319\csc.exe /out:Release\ParkerScript.dll /target:library /platform:x86 /reference:core\LuaInterface.dll /reference:core\System.Speech.dll /reference:core\PAD_SCRIPT.dll /reference:core\lua51.dll core\Program_lib.cs core\AssemblyInfo.cs core\lib\*.cs

The class definition is internal, which will not show up when you reference it.
Define your class like this:
namespace PARKER_SCRIPT
{
public class PScript
{
//Code goes here...
}
}

Related

How to extract a complete method inside a class?

I'm trying to extract a complete method which is inside a cs file.
for instance.. suppose we have a class like this...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GetMethodNm
{
class MyClass
{
public int ComplexMethod(int param1, int myCustomValue)
{
if (param1 == myCustomValue)
{
return 54;
}
else
{
return 0;
}
}
public string ComplexMethodV(int param1, int myCustomValue)
{
if (param1 < myCustomValue)
{
return "300";
}
else
{
return "My custom value to return";
}
}
public bool ComplexMethodX(int param1, int myCustomValue)
{
if (param1 == myCustomValue)
{
return true;
}
else
{
return false;
}
}
}
}
Then I need to extract the method reading the cs file ComplexMethodV .. How can I do this? I have tried with reflection but I can only get the name and some things inside of it.. but I would need the literal method within.
Using Roslyn tasks like this are relitively easy. In a project add the NuGet package Microsoft.CodeAnalysis.CSharp, then just use the following code
using System;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SandboxConsole
{
class Program
{
public static void Main()
{
var text = File.ReadAllText("MyClass.cs");
var tree = CSharpSyntaxTree.ParseText(text);
var method = tree.GetRoot().DescendantNodes()
.OfType<MethodDeclarationSyntax>()
.First(x => x.Identifier.Text == "ComplexMethodV");
Console.WriteLine(method.ToFullString());
Console.ReadLine();
}
}
}
This outputs the text
public string ComplexMethodV(int param1, int myCustomValue)
{
if (param1 < myCustomValue)
{
return "300";
}
else
{
return "My custom value to return";
}
}
See the Wiki for more advanced tutorials on how to do things like parse entire solutions.

Replacing dll at runtime without pain

I have a basic WinForm Solution (MS VS2013, .Net framework 4.5) for test some methods included in a Dll, using Reflection. My goal is test the main application that it can run two methods of Dll (without referencing the dll in project), and later, run four methods (2 methods added) without stop the main application and run it again, using reflection.
Reflections works fine (if I stop the main application, replacing the dll file and run the main application again, all works fine), but I can't replace the dll at runtime.
The main application has a Timer control with an interval of 60 seconds. Every 60 seconds, a method is executed that checks if a DLL file is in a folder. If a DLL file exists in that folder, I want to use the new DLL in the main application (running) because the new DLL contains old methods (first DLL) and additional methods that the main application needs.
However, I am getting an error that the file is in use.
I have read several posts, questions, answers, MEF documentation, AppDomains related, but I have been unable to concatenate the information to be able to implement a solution.
Actually, I thought a lot before post this question, but I confess that I prefer to spend a moment of shame, knowing that you can give me a hand.
It would be for me a great help if you help me with code and specific instructions.
This is the code:
Main application:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace testDLLs
{
public partial class Principal : Form
{
public Principal()
{
InitializeComponent();
}
private void Principal_Load(object sender, EventArgs e)
{
labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
string[] aOperaciones = cListaOperaciones.Split('|');
comboBoxOperaciones.Items.Clear();
foreach (string cOperacion in aOperaciones)
{
comboBoxOperaciones.Items.Add(cOperacion);
}
timerForUpdate.Interval = 60000;
timerForUpdate.Enabled = true;
}
private void buttonRun_Click(object sender, EventArgs e)
{
int iOperador1, iOperador2;
string resultadoDesdeDll = null;
string cOperacionSeleccionada;
Int32.TryParse(textBoxOperador1.Text, out iOperador1);
Int32.TryParse(textBoxOperador2.Text, out iOperador2);
cOperacionSeleccionada = comboBoxOperaciones.GetItemText(comboBoxOperaciones.SelectedItem);
object[] parametersArray = new object[] { iOperador1, iOperador2 };
resultadoDesdeDll = metodosApoyo.RunDLLFunction(cOperacionSeleccionada, parametersArray);
textBoxResultado.Text = resultadoDesdeDll;
}
private void timerForUpdate_Tick(object sender, EventArgs e)
{
labelUpdateStatus.Text = "Checking updates ...";
notifyIconUpdate.Visible = true;
notifyIconUpdate.BalloonTipText = "Instalando nuevo DLL....";
notifyIconUpdate.BalloonTipTitle = "Info:";
notifyIconUpdate.ShowBalloonTip(5000);
if (File.Exists(#"C:\DLLsForCopy\OperacionesDLL.dll"))
{
File.Copy(#"C:\DLLsForCopy\OperacionesDLL.dll", #"D:\DLLs\OperacionesDLL.dll", true);
labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
string[] aOperaciones = cListaOperaciones.Split('|');
comboBoxOperaciones.Items.Clear();
foreach (string cOperacion in aOperaciones)
{
comboBoxOperaciones.Items.Add(cOperacion);
}
}
labelUpdateStatus.Text = "";
notifyIconUpdate.Visible = false;
}
}
}
Class in project, for some functions for Main application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace testDLLs
{
class metodosApoyo
{
public static string RunDLLFunction(string cMetodo, object[] aParametros = null)
{
string cRetornoGlobal = "";
Object resultado = null;
string cOperacionSeleccionada = cMetodo;
Assembly assembly = Assembly.LoadFile(#"D:\DLLs\OperacionesDLL.dll");
Type type = assembly.GetType("OperacionesDLL.Operaciones");
MethodInfo methodInfo = type.GetMethod(cOperacionSeleccionada);
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(type, null);
object[] parametersArray = null;
if (aParametros != null)
{
parametersArray = new object[aParametros.Length];
int i = 0;
foreach (object value in aParametros)
{
parametersArray[i] = aParametros[i];
i++;
}
}
resultado = methodInfo.Invoke(methodInfo, parametersArray);
cRetornoGlobal = (string)resultado;
return cRetornoGlobal;
}
}
}
DLL source (OperacionesDLL.dll):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OperacionesDLL
{
public class Operaciones
{
public static string VersionOperaciones()
{
string retorno;
retorno = "1.0701-16";
return retorno;
}
public static string ListaOperaciones()
{
string retorno;
retorno = "Suma|Resta|Multiplicación|División";
return retorno;
}
public static string Suma(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 + operador2;
retorno = resultado.ToString();
return retorno;
}
public static string Resta(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 - operador2;
retorno = resultado.ToString();
return retorno;
}
public static string Multiplicación(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 * operador2;
retorno = resultado.ToString();
return retorno;
}
public static string División(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 / operador2;
retorno = resultado.ToString();
return retorno;
}
}
}
Thanks in advance.
You can do what you're describing by using the Managed Addin Framework (MAF) in the System.Addin namespace. I've used it to write apps that scans a folder for DLLs and dynamically loads them. You can also use it to unload and reload DLLs as they appear and disappear from the folder.

CompileAssemblyFromSource + Obfuscation = don't work

i have working CompileAssemblyFromSource code. But when i use any code protector like RedGate SmartAssembly or Themida it's stop working and i get error "Could not load file or assembly or one of its dependencies". Can you please help me with that?
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
namespace stringToCode
{
public class Program
{
public static int q = 0;
static void Main(string[] args)
{
try
{
string source = "namespace stringToCode { public class FooClass { public void Execute() { Program.q = 1; } } }";
Console.WriteLine("q=" + q);
using (var foo = new CSharpCodeProvider())
{
var parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
string location = assembly.Location;
if (!String.IsNullOrEmpty(location))
{
parameters.ReferencedAssemblies.Add(location);
}
}
catch (NotSupportedException)
{ }
}
var res = foo.CompileAssemblyFromSource(parameters, source);
var type = res.CompiledAssembly.GetType("stringToCode.FooClass");
var obj = Activator.CreateInstance(type);
var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
Console.WriteLine("q=" + q);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);;
}
Console.ReadLine();
}
}
}
sorry for my question. I just understand why it happens)
This is code is example. The main problem i have with code that i get from server.
So when i obfuscate my vars i don't obfuscare them at my "online" code that i use with CompileAssemblyFromSource. So this just can't work. Because vars don't have same names.

Create Class at Runtime, File not Found Exception

im having a Problem creating a Class at runtime. Everytime i debug the code below i get the following error message at var cls = results.CompiledAssembly.GetType("test.DummyHelloWorldHandler");
Could not load file or assembly 'file:///C:\Users\MyName\AppData\Local\Temp\1ivc3qic.dll' or one of its dependencies. Das System kann die angegebene Datei nicht finden.
the Name of the *.dll file differs everytime i debug the programm
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace DynamicNS
{
class Program
{
static void Main(string[] args)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
parameters.ReferencedAssemblies.Add("System.Collections.dll");
CompilerResults results = provider.CompileAssemblyFromSource(parameters, GetCode());
var cls = results.CompiledAssembly.GetType("test.DummyHelloWorldHandler");
var method = cls.GetMethod("Received", BindingFlags.Static | BindingFlags.Public);
object[] parms = { "Hallo Welt" };
method.Invoke(null, parms);
Console.ReadLine();
}
static string[] GetCode()
{
return new string[]
{
#"using System.Collections;
namespace test
{
public class DummyHelloWorldHandler
{
protected internal Queue _queue;
public void Received(string message)
{
lock (_queue)
{
_queue.Enqueue(message);
}
Console.WriteLine('Enqueued');
}
public DummyHelloWorldHandler()
{
_queue = new Queue();
}
}
}"
};
}
}
}
The code returned by GetCode does not compile because of the wrong quotes.
You can check that by iterating over the Errors property of your CompilerResults.
You have to remove this line:
parameters.ReferencedAssemblies.Add("System.Collections.dll");
and change the GetCode() method like this:
private static string[] GetCode()
{
return new string[]
{
#"using System;
using System.Collections;
namespace test
{
public class DummyHelloWorldHandler
{
protected internal Queue _queue;
public void Received(string message)
{
lock (_queue)
{
_queue.Enqueue(message);
}
Console.WriteLine(""Enqueued"");
}
public DummyHelloWorldHandler()
{
_queue = new Queue();
}
}
}"
};
}
#"using System.Collection
Should probably be
#"using System.Collections;
Also: Console.WirteLine()? Hmmm. Perhaps you should paste that entire GetCode() string into a test program, make it compile, and then paste it back into your original project.
After your edits, this still won't compile:
Console.WriteLine('Enqueued');
It's got single quotes instead of double quotes around the string.
Are you sure your code could actually be compiled? You seem to be missing a semicolon after your using statement.
Check the Errors property of your results, it contains the errors that were encountered while compiling your source.

MvxBind:Error: 10.40 Exception thrown during the view binding

I'm trying to create a simple service using the code provided but i don't understand why have an exception when binding.
10-19 11:42:09.148 I/mono-stdout( 1622): MvxBind:Error: 10.40 Exception thrown during the view binding
MvxBindingLayoutInflatorFactory Line 133!
I need some help please :)
My Source:
DataStore Interface:
using Core.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace Core.Interfaces
{
public interface IDataStore
{
void UpdateFeed(FeedModel feedModel);
void DeleteFeed(FeedModel feedModel);
void CreateFeed(FeedModel feedModel);
FeedModel GetFeed(Uri uri);
ObservableCollection<FeedModel> Feeds { get; }
}
}
DataStore Class:
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Interfaces;
using System.Collections.ObjectModel;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Interfaces.Platform;
using Cirrious.MvvmCross.Interfaces.Localization;
using Cirrious.MvvmCross.ExtensionMethods;
using Core.Helpers;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.IO;
namespace Core.Models
{
public class DataStore
: IDataStore
, IMvxServiceConsumer<IMvxSimpleFileStoreService>
, IMvxServiceConsumer<IMvxResourceLoader>
{
public DataStore()
{
Load();
}
public void UpdateFeed(FeedModel feedModel)
{
var toUpdate = this.m_feeds.First(feed => feed.Url == feedModel.Url);
toUpdate.CloneFrom(feedModel);
Save();
}
public void DeleteFeed(FeedModel feedModel)
{
this.m_feeds.Remove(this.m_feeds.First(feed => feed.Url == feedModel.Url));
Save();
}
public void CreateFeed(FeedModel feedModel)
{
this.m_feeds.Add(feedModel);
Save();
}
public FeedModel GetFeed(Uri uri)
{
return this.m_feeds.First(feed => feed.Url == uri);
}
private void Load()
{
var fileService = this.GetService<IMvxSimpleFileStoreService>();
if (!fileService.TryReadBinaryFile(LocationDataService.StoreFileName, LoadFrom))
{
var resourceLoader = this.GetService<IMvxResourceLoader>();
resourceLoader.GetResourceStream(LocationDataService.ResourceFileName, (inputStream) => LoadFrom(inputStream));
}
}
private bool LoadFrom(Stream inputStream)
{
try
{
var loadedData = XDocument.Load(inputStream);
if (loadedData.Root == null)
return false;
using (var reader = loadedData.Root.CreateReader())
{
var list = (List<FeedModel>)new XmlSerializer(typeof(List<FeedModel>)).Deserialize(reader);
this.m_feeds = new ObservableCollection<FeedModel>(list);
return true;
}
}
catch
{
return false;
}
}
private void Save()
{
var fileService = this.GetService<IMvxSimpleFileStoreService>();
fileService.WriteFile(LocationDataService.StoreFileName, (stream) =>
{
var serializer = new XmlSerializer(typeof(List<FeedModel>));
serializer.Serialize(stream, m_feeds.ToList());
});
}
private ObservableCollection<FeedModel> m_feeds;
public ObservableCollection<FeedModel> Feeds
{
get { return this.m_feeds; }
}
}
}
BaseViewModel:
using Cirrious.MvvmCross.Commands;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.Commands;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.ViewModels;
using Core.Interfaces;
namespace Core.ViewModels
{
public class BaseViewModel
: MvxViewModel
, IMvxServiceConsumer<IDataStore>
{
protected IDataStore DataStore
{
get { return this.GetService<IDataStore>(); }
}
}
}
FeedManagerViewModel:
using Cirrious.MvvmCross.Commands;
using Cirrious.MvvmCross.Interfaces.Commands;
using Core.Controls;
using Core.Models;
using System;
using System.Collections.ObjectModel;
namespace Core.ViewModels
{
public class FeedsManagerViewModel
: BaseViewModel
{
public ObservableCollection<FeedModel> Feeds { get { return this.DataStore.Feeds; } }
...
}
}
View xml:
<Mvx.MvxBindableListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="{'ItemsSource':{'Path':'Feeds'}, 'ItemClick':{'Path':'DisplayItemCommand'}}"
local:MvxItemTemplate="#layout/feedlist_viewmodel" />
This is most likely an error in your XML... but it's hard to tell from just that one line of trace.
What version of MvvmCross are you running?
The tip version of both Master and vNext show line 133 as
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception during creation of {0} from type {1} - exception {2}", name, viewType.FullName, exception.ToLongString());
So hopefully if you use the tip, then that should give you a lot more information about what is going wrong.
Beyond that, you can always try setting a breakpoint on the offending line to extract more information.
If the exception is on line 99 then change the error logging there from:
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception thrown during the view binding ", exception.ToLongString());
to:
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception thrown during the view binding {0}", exception.ToLongString());
The error will be in there somewhere :)
Another good debugging technique is to comment out lines one-by-one until the problem goes away - this helps identify where the problem is.
You've got a working development environment and a really powerful debugger - using it is a good skill to learn. 'Code Complete' is one of my favourite books ever :)

Categories