So, I have strange question (maybe so stupid), but...
So, my task.
I have same class which gives me same functionality. So, in the main program, which I realize (yes, it's client-server app)) , I want to dynamically create ".exe wrapper" for this class - simplest code like this:
class Program
{
private SameClass mySameClass;
static void Main(string[] args)
{
mySameClass = new mySameClass(args);
Console.Readline();
}
}
In general, I want to create main app which creates slaves in the independent proccesses via dynamically code generation.
So, how to make it and control it?
Thank you.
So SameClass is supposed to contain the same functions and functionality as the process you want to have run multiple times... I guess what you need are Threads.
Not too sure what you mean by dynamically but let's say you have an event that triggers whenever you need a new SameClass process. Just run
SameClass newClone = new SameClass(args);
Trhead _thread = new Thread(new ThreadStart(newClone.Start));
_trhead.Start();
You can probably do this a little more elegant and refactor within SameClass but it's pretty hard to understand your question, so I guess this is the best I can do you hopefully answer your question.
Found solution based on CodeDom. Yes, It doesn't need reflection, sorry.
Code example:
using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Diagnostics;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var compiler = new CSharpCodeProvider();
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true);
parameters.CompilerOptions = "/platform:x64";
parameters.GenerateExecutable = true;
CompilerResults results = compiler.CompileAssemblyFromSource(parameters,
#"using System;
class Program {
public static void Main(string[] args) {
Console.WriteLine(""Hello world!"");
Console.ReadLine();
}
}");
var testProcess = new Process();
testProcess.StartInfo.FileName = results.CompiledAssembly.CodeBase;
testProcess.Start();
Console.WriteLine("I've run slave!");
Console.ReadLine();
}
}
}
Related
I'm trying to write some tests for testing GUI interface. I decided to choose NUnit.Forms. But the tests fall with the following error:
TearDown : System.ComponentModel.Win32Exception : The requested resource is in use
I have two versions of the source code tests.
First:
using System.Windows.Forms;
using NUnit.Extensions.Forms;
using NUnit.Framework;
using YAMP;
namespace Tests.GUITests
{
[TestFixture]
public class GuiTest : NUnitFormTest
{
private FrmMain _frm;
//[SetUp] // or it is still needed
public override void Setup()
{
base.Setup();
_frm = new FrmMain();
_frm.Show();
}
[Test]
public void TestData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = "2+2"};
var txtOutput = new TextBoxTester("txtOutput");
Assert.AreEqual("2+2", txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.AreEqual("4", txtOutput.Text);
}
}
}
Second:
using System.Windows.Forms;
using NUnit.Extensions.Forms;
using NUnit.Framework;
using YAMP;
namespace Tests.GUITests
{
[TestFixture]
public class GuiTest : NUnitFormTest
{
private FrmMain _frm;
//[SetUp] // or it is still needed
public override void Setup()
{
base.Setup();
_frm = new FrmMain();
_frm.Show();
}
[TearDown]
public override void TearDown()
{
_frm.Close();
_frm.Dispose();
}
[Test]
public void TestData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = "2+2"};
var txtOutput = new TextBoxTester("txtOutput");
Assert.AreEqual("2+2", txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.AreEqual("4", txtOutput.Text);
}
}
}
And there are two different versions of the method TestNoData:
public void TestFormNoDataHandler()
{
var messageBoxTester = new MessageBoxTester("Message");
messageBoxTester.ClickOk();
}
[Test]
public void TestNoData()
{
ExpectModal("Message", TestFormNoDataHandler);
var txtInput = new TextBoxTester("txtInput") {["Text"] = string.Empty};
Assert.AreEqual(string.Empty, txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.IsFalse(_frm.DialogResult == DialogResult.OK);
}
[Test]
public void TestNoData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = string.Empty };
Assert.AreEqual(string.Empty, txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.IsFalse(_frm.Enable);
}
Testable form is very simple. There are two TextBox - "txtInput", "txtOutput" and button - "btnRes". In "txtInput" introduced a mathematical expression, and "txtOutput" output response. The decision of expression occurs when you press "btnRes". If the field "txtInput" empty, the button is disabled and you can not click on it.
When searching for solutions to this problem came on the following links:
AutomaticChainsaw: WinForms testing using NUnitForms
c# - I need to create a windows form from within a NUnit test - Stack Overflow
Unfortunately I can attach only 2 links. But the information I learned is very different. Especially the part of writing methods Setup and TearDown.
In any case, I specify the version I use:
Visual Studio 2015 Community
NUnit - 2.6.4.14350
NUnitForms - 1.3.1771.29165
Because it seems to me that the problem might be too recent versions of frameworks, as article I learned quite old.
Thank you for any suggestion.
UseHidden Property: Tests are run on a separate hidden desktop. This makes them much faster and it works for any tests that are not using the keyboard or mouse controllers. They are less disruptive and input tests cannot interfere with other applications.
UseHidden property controls whether a separate desktop is used at all.
Though tests on the separate desktop are faster and safer (There is no danger of keyboard or mouse input going to separate running applications.), however for some operating systems or environments the separate desktop does not work. And the tests throw up errors like:
System.ComponentModel.Win32Exception : The requested resource is in use
--TearDown
at NUnit.Extensions.Forms.Desktop.Destroy()
at NUnit.Extensions.Forms.Desktop.Dispose()
at NUnit.Extensions.Forms.NUnitFormTest.Verify()
In that case you can override UseHidden property from test class and set it to return false. This will cause the tests to run on original, standard desktop.
To help me learn c#, I am converting a script I made in lua to C#
I want to know if it is possible to add a function to a list (table in lua) and call it
Here's what I have in Lua
functions{ function() print("Hello World!") end }
functions[1]()
Output: Hello World!
In C# I am using Lists
Example
var functions = new List</* What do I put here */>();
functions.Add(/* Somehow define a public static void here */);
Thank you.
Use Action or Func<TResult> depending whether you need result or not, use lambda expression to define function in style you are looking for:
var functions = new List<Action>();
functions.Add(() => { Console.WriteLine("Here!"); }
functions[0]();
Awesome! Well, I can't say with certainty that this is the best answer, but it's my take on the this situation.
class Program
{
static void Main(string[] args)
{
var functions = new List<Action>();
functions.Add(new Action(delegate
{
// Do stuff
Console.WriteLine("Successfully did stuff.");
}));
functions[0].DynamicInvoke();
Console.ReadKey();
}
}
Actions in .NET are used a lot with the Task Parallel Library.
I am trying to figure out how you could go about importing and using a .dll at runtime inside a C# application. Using Assembly.LoadFile() I have managed to get my program to load the dll (this part is definitely working as I am able to get the name of the class with ToString()), however I am unable to use the 'Output' method from inside my console application. I am compiling the .dll then moving it into my console's project. Is there an extra step between CreateInstance and then being able to use the methods?
This is the class in my DLL:
namespace DLL
{
using System;
public class Class1
{
public void Output(string s)
{
Console.WriteLine(s);
}
}
}
and here is the application I want to load the DLL
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(#"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
var c = Activator.CreateInstance(type);
c.Output(#"Hello");
}
Console.ReadLine();
}
}
}
Members must be resolvable at compile time to be called directly from C#. Otherwise you must use reflection or dynamic objects.
Reflection
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(#"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
var c = Activator.CreateInstance(type);
type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {#"Hello"});
}
Console.ReadLine();
}
}
}
Dynamic (.NET 4.0)
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(#"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
dynamic c = Activator.CreateInstance(type);
c.Output(#"Hello");
}
Console.ReadLine();
}
}
}
Right now, you're creating an instance of every type defined in the assembly. You only need to create a single instance of Class1 in order to call the method:
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(#"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
var theType = DLL.GetType("DLL.Class1");
var c = Activator.CreateInstance(theType);
var method = theType.GetMethod("Output");
method.Invoke(c, new object[]{#"Hello"});
Console.ReadLine();
}
}
You need to create an instance of the type that expose the Output method:
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(#"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
var class1Type = DLL.GetType("DLL.Class1");
//Now you can use reflection or dynamic to call the method. I will show you the dynamic way
dynamic c = Activator.CreateInstance(class1Type);
c.Output(#"Hello");
Console.ReadLine();
}
Activator.CreateInstance() returns an object, which doesn't have an Output method.
It looks like you come from dynamic programming languages? C# is definetly not that, and what you are trying to do will be difficult.
Since you are loading a specific dll from a specific location, maybe you just want to add it as a reference to your console application?
If you absolutely want to load the assembly via Assembly.Load, you will have to go via reflection to call any members on c
Something like type.GetMethod("Output").Invoke(c, null); should do it.
foreach (var f in Directory.GetFiles(".", "*.dll"))
Assembly.LoadFrom(f);
That loads all the DLLs present in your executable's folder.
In my case I was trying to use Reflection to find all subclasses of a class, even in other DLLs. This worked, but I'm not sure if it's the best way to do it.
EDIT: I timed it, and it only seems to load them the first time.
Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 4; i++)
{
stopwatch.Restart();
foreach (var f in Directory.GetFiles(".", "*.dll"))
Assembly.LoadFrom(f);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
Output:
34
0
0
0
So one could potentially run that code before any Reflection searches just in case.
It's not so difficult.
You can inspect the available functions of the loaded object, and if you find the one you're looking for by name, then snoop its expected parms, if any. If it's the call you're trying to find, then call it using the MethodInfo object's Invoke method.
Another option is to simply build your external objects to an interface, and cast the loaded object to that interface. If successful, call the function natively.
This is pretty simple stuff.
In C# (.NET), can two threads running in the same application have DIFFERENT "WorkingFolders"??
As best I can tell, the answer would be "NO". I think the WORKING DIR is set by the PROCESS in Win32.. Am I wrong here?
According to the following test code, (as well the Win32 SetCurrentDirectory API call), this is NOT possible, but has anyone figured out a way to MAKE it possible?
using System;
using System.Threading;
public class TestClass {
public ManualResetEvent _ThreadDone = new ManualResetEvent(false);
public static void Main() {
Console.WriteLine(Environment.CurrentDirectory);
Thread _Thread = new Thread(new ParameterizedThreadStart(Go));
TestClass test = new TestClass();
_Thread.Start(test);
if(test._ThreadDone.WaitOne()) {
Console.WriteLine("Thread done. Checking Working Dir...");
Console.WriteLine(Environment.CurrentDirectory);
}
}
public static void Go(object instance) {
TestClass m_Test = instance as TestClass;
Console.WriteLine(Environment.CurrentDirectory);
System.IO.Directory.SetCurrentDirectory("L:\\Projects\\");
Console.WriteLine(Environment.CurrentDirectory);
m_Test._ThreadDone.Set();
}
}
I know SOMEONE out there has to have ran across this before!
I'm going to guess what you're trying to do is to make code such as File.Open("Foo.txt") behave differently on different threads. Can you do this? The short answer is No - nor should you be trying to do this. On Windows, the current working directory is set at the process level. The .NET framework does not violate that rule.
A better approach would be to create an abstraction on top of Environment.CurrentDirectory that is thread specific. Something like:
public static class ThreadEnvironment
{
[ThreadStatic]
static string _currentDir;
public static string CurrentDirectory
{
get
{
if (_currentDir == null) // If Current Directory has not been set on this thread yet, set it to the process default
{
_currentDir = Environment.CurrentDirectory;
}
return _currentDir;
}
set
{
if (value == null)
throw new ArgumentException("Cannot set Current Directory to null.");
_currentDir = value;
}
}
}
You can then refer to ThreadEnvironment.CurrentDirectory to get that thread's current directory, which will default to the process directory if it has not been set on that thread. For example:
static void Main(string[] args)
{
(new Thread(Thread1)).Start();
(new Thread(Thread2)).Start();
}
static void Thread1()
{
Console.WriteLine("Thread1 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
ThreadEnvironment.CurrentDirectory = #"C:\";
Console.WriteLine("Thread1 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
}
static void Thread2()
{
Console.WriteLine("Thread2 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
ThreadEnvironment.CurrentDirectory = #"C:\Windows";
Console.WriteLine("Thread2 Working Dir is: {0}", ThreadEnvironment.CurrentDirectory);
}
You would, of course, then need to qualify that path whenever dealing with file IO, however this is arguably a safer design anyway.
has anyone figured out a way to MAKE it possible?
It's simply not possible. You can't even have different working directories per App Domain.
The windows rule is: one Environment set per Process. Running in .NET won't change the basic rules.
Instead of that, if you experienced problem in loading assemblies, consider adding the corresponding folder to the PATH environment variable.
I want to implement C# as the scripting language in my game.
My problem is, that my script will not compile if I want to use classes defined in the game core (exe).
The script looks like this:
using System;
using ConsoleApplication1;
class Script
{
private static void Call()
{
Console.WriteLine("called");
}
public static void Init()
{
Console.WriteLine("Script");
Call();
GameObject myO; // THIS IS WHAT I WANT TO GET WORKED,
//IF THIS IS COMMENTED OUT, IT COMPILES FINE, GAMEOBJECT
// IS DEFINED IN THE "ConsoleApplication1" NAMESPACE.
}
}
The script is compiled like in the MDX sample:
static void Main(string[] args)
{
CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
//cp.CompilerOptions = "/target:library";
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
cp.IncludeDebugInformation = false;
cp.ReferencedAssemblies.Add("ConsoleApplication2.exe");
cp.ReferencedAssemblies.Add("System.dll");
CompilerResults cr = provider.CompileAssemblyFromFile(cp, "script.cs");
if (!cr.Errors.HasErrors)
{
Console.WriteLine("Success");
cr.CompiledAssembly.GetType("Script").GetMethod("Init").Invoke(null, null);
}
Console.ReadLine();
}
Is there any way to call functions or create objects defined in the "ConsoleApplication1" namespace via the script?
This is a daily programming problem. It's not working and you think it should be working. So break it down. Instead of working on a big problem, work on a smaller problem. Just tackle trying to compile the script outside of your program. Once you get that working, then you can try to compile it as a script from inside your program, knowing that you've got the basic problem of references and compiler issues sorted out.
Something like:
csc /reference:ConsoleApplication1.exe script.cs
From the looks of it, it might be as simple as changing the reference from ConsoleApplication2.exe to ConsoleApplication1.exe.