Why AssemblyResolver fire even when dll is loaded (manualy)? - c#

I have C# solution with 2 project:
DLLTest (Console app)
BLib (library)
In DLLTest I set reference to BLib and set Copy Local property to false.
Compile solution.
Copy BLib.dll to 'C:\BLib.dll' and run application.
In first step in my code I load Assembly from path 'C:\BLib.dll' then invoke method from there. On invoking method from BLib assembly fire AssemblyResolver and try load assembly which I loaded before manually.
Can I do something that application to know that the library has already been loaded and not try load it again?
This is BClass.cs file from BLib project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BLib
{
public class BClass
{
public static void PrintName()
{
Console.WriteLine("BLib");
}
}
}
This is Program.cs file from DLLTest project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace DLLTest
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Assembly.LoadFile(#"C:\BLib.dll");
Console.WriteLine("Loaded assembles:");
AppDomain.CurrentDomain.GetAssemblies().ToList()
.ForEach(p => Console.WriteLine(p));
Console.WriteLine("End list of assembles");
try
{
PrintMessage();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
private static void PrintMessage()
{
BLib.BClass.PrintName();
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine(args.Name);
return null;
}
}
}

I find similar question Why is AssemblyResolve called when Assembly is in CurrentDomain? Answer from there follow me to Choosing a Binding Context where everything was detailed described (row Neither column Disadvantages).
That I think so, this is security reason.

Related

Error CS0116: A namespace cannot directly contain members such as fields or methods

Ok so im trying to make a program that checks if a program is currently running. It is giving me a error when ever i declare a void. I am new to C# so im sorry if its a stupid.
using System;
using System.Windows;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.VisualBasic.ApplicationServices;
namespace IsProgramRunning
{
private void IsRunning()
{
Process[] pname = Process.GetProcessesByName("VLC Player");
if (pname.Length > 0)
{
MessageBox.Show("Process Running");
}
else
{
MessageBox.Show("Process Not running");
}
System.Threading.Thread.Sleep(5 * 1000);
}
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
If im going about this all wrong and there is a easy way to do it in c++ that would be good to
To have instance members and methods, you need a class. You have confused a namespace with a class
namespace MyAwesomeNameSpace
{
public class ProgramRunningHelper
{
// put your class code here
}
}
Compiler Error CS0116
A namespace cannot directly contain members such as fields or methods.
A namespace can contain other namespaces, structs, and classes.

VisualStudio NUnit3TestAdapter testing project with third party dlls

I have a testing project Proj_Test with two nuget packages.
<packages>
<package id="NUnit" version="3.6.0" targetFramework="net45" />
<package id="NUnit3TestAdapter" version="3.6.0" targetFramework="net45" />
</packages>
Proj_Test has a reference to the tested project Proj.
Proj has references to several other dlls that need to be loaded.
Where can I add this information so that I can start the tests using the NUnit3TestAdapter from within my IDE without actually copying the dlls to the output folder.
There was a solution for the Nunit2 Runners. But I fail when attempting to use that for Nunit3 via NUnit3TestAdapter.
According to the tips and tricks section i added a settings file Test.runsettings via the menu.
<RunSettings>
<NUnit>
<PrivateBinPath>D:\Drive\AnyThirdParty</PrivateBinPath>
</NUnit>
</RunSettings>
The setting seems to be ignored.
How can I manage these dependencies for my tests?
EDIT:
This is what happened to me I think.
Private assemblies are deployed in the same directory structure as the application. If the directories specified for PrivateBinPath are not under ApplicationBase, they are ignored.
Is creating a copy really the only solution?
If you can't find anything better,try to resolve it yourself
using ConsoleApplication6;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Reflection;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestInitialize]
public void Init()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += MyResolveEventHandler;
}
[TestMethod]
public void TestMethod1() { Assert.AreEqual(new MyClass().DoSomething(), 1); }
[TestMethod]
public void TestMethod2() { Assert.AreEqual(new MyClass().DoSomething(), 1); }
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
return Assembly.LoadFile(#"C:\MyPath\MyAssembly.dll");
}
}
}
Unfortunately assembly probing works only on subdirectories so you can't use it...
Thanks to George Vovos answer, this is what I ended up implementing.
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
//https://github.com/nunit/docs/wiki/SetUpFixture-Attribute
//A SetUpFixture outside of any namespace provides SetUp and TearDown for the entire assembly.
[SetUpFixture]
class GlobalSetup
{
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int SetDllDirectory(string NewDirectory);
static HashSet<string> directories = new HashSet<string>
{
#"D:\Drive\AnyThirdParty\"
};
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AddManagedHandler();
SetNativeDirectories();
}
private void SetNativeDirectories()
{
if(directories.Count() != 1)
{
//TODO: add support for multiple directories
throw new NotImplementedException("current implementation only supports exactly one directory");
}
if (0 == SetDllDirectory(directories.First()))
{
throw new Exception("SetDllDirectory failed with error " + Marshal.GetLastWin32Error());
}
}
private void AddManagedHandler()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
IEnumerable<string> candidates = FindCandidates(new AssemblyName(args.Name));
return Assembly.LoadFrom(candidates.First());
}
private static IEnumerable<string> FindCandidates(AssemblyName assemblyname)
{
List<string> candidates = new List<string>();
foreach (var path in directories)
{
string candidate = string.Format(#"{0}{1}.dll", path, assemblyname.Name);
if (File.Exists(candidate))
{
candidates.Add(candidate);
}
}
if (!candidates.Any())
{
throw new FileNotFoundException(string.Format("Can not find assembly: '{0}.dll'", assemblyname.Name));
}
return candidates;
}
}

reference Scripting compiling c# csc

I need to compile via csc.exe this code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Scripting;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
Scripting.FileSystemObject fso = new Scripting.FileSystemObject();
Scripting.Folder folder = fso.GetFolder(#"E:\backup_SQL_Planet\");
Int64 dirSize = (Int64)folder.Size;
string abc = Convert.ToString(dirSize);
Console.WriteLine(abc);
}
}
}
when i execute csc.exe there was a problem with reference of (using Scripting;)
How do I reference using Scripting?

Error with CreateInstanceAndUnwrap

I just get an error each time I run this code:
AppDomain newDomain = AppDomain.CreateDomain("newDomain");
AssemblyName assemblyName = AssemblyName.GetAssemblyName(path);
Command cmd = (Command)newDomain.CreateInstanceAndUnwrap(assemblyName.FullName, typename);
cmd.Execute();
Where path is the path of the Dll and typename is "NWT_Projekt.TestClass"
My command class:
using System;
namespace NWT_Projekt
{
public interface Command
{
void Execute();
}
}
and this is the source code of the DLL
using System;
using System.Collections;
using System.Xml;
using System.IO;
using System.Windows.Forms;
namespace NWT_Projekt
{
public class TestClass : NWT_Projekt.Command
{
public MainForm f;
public TestClass()
{
f = Form.ActiveForm as MainForm;
}
public void Execute()
{
//do something
}
}
}
ERROR (google translator :D)
An exception of type "System.Runtime.Serialization.SerializationException 'occurred in NWT PRojekt.exe.
Additional information: The type "NWT_Projekt.TestClass' in Assembly 'scripts, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null' is not marked as serializable.
EDIT2:
With the [Serializable] it works now, but after I run the code one time and then I want to create a second dll it gives me an IO error, because the file is in use!
How can I fix this?
If you want your command to run on its own appDomain, you should use MarshalByRefObject.
using System;
using System.Collections;
using System.Xml;
using System.IO;
using System.Windows.Forms;
namespace NWT_Projekt
{
public class TestClass : MarshalByRefObject, NWT_Projekt.Command
{
public MainForm f;
public TestClass()
{
f = Form.ActiveForm as MainForm;
}
public void Execute()
{
//do something
}
}
}
I advice you to prefix your interfaces : ICommand

Task.Factory.StartNew() not working for me

I wrote this small application. for some reason i am not being able to print "Hello from a thread" when i run this program. however if i debug it and put a breakpoint inside Do() method, it does print.
Any ideas?
using System;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
internal class Program
{
private static void Main(string[] args)
{
Task.Factory.StartNew(Do);
}
private static void Do()
{
Console.WriteLine("Hello from a thread");
}
}
}
Are you sure that the program simply isn't closing before you can see the output? Because this works fine for me.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static void Main(string[] args)
{
Task.Factory.StartNew(Do);
Console.Read();
}
private static void Do()
{
Console.WriteLine("Hello from a thread");
}
}
}
Edit: Added the comment I wrote in response to this, including my reasoning to why the text wasn't printed.
Its either because the application closes down before the thread has the possibility of outputting the string to the screen. It's also possible that you simply cant see it because it closes straight away. Either way the reason it worked with the breakpoint is because you keep the application alive longer.
Try this.
using System;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
internal class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(Do);
Console.ReadKey();
}
static void Do()
{
Console.WriteLine("Hello from a thread");
}
}
}

Categories

Resources