How can i get dependency's assembly, that i don't use?
In .sln file i added ProjectDependency B,C in my project A
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "A", "A\A.csproj", "{BF8FD60F-8519-4DD5-8576-2E6AB68AC640}"
ProjectSection(ProjectDependencies) = postProject
{99BEBDF2-B5AE-4900-9BC2-7F0B4A1CDEA1} = {99BEBDF2-B5AE-4900-9BC2-7F0B4A1CDEA1}
{C8FC5959-A63A-4C0C-B245-BC21FA2027A6} = {C8FC5959-A63A-4C0C-B245-BC21FA2027A6}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "B", "Dependencies\B\B.csproj", "{C8FC5959-A63A-4C0C-B245-BC21FA2027A6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "C", "Dependencies\C\C.csproj", "{99BEBDF2-B5AE-4900-9BC2-7F0B4A1CDEA1}"
EndProject
But i cant get this dependencies in execution time
I tried write this code in A project
var results1 = AppDomain.CurrentDomain.GetAssemblies();
var results2 = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
to get this B and C dependencies. I didn't find them in results1, results2 variable.
EDIT:
I know about way to load assembly by path:
Assembly.Load()
But it doesn't look like flex solution
Just make some fake (empty) class/static property in projects B and C and reference somewhere it in project A. In that way compiler will include your assemblies in build time.
Related
I'm compiling a C# assembly at runtime within my program using CSharpCodeProvider, which depends on a few libraries which are built as .dlls, and also the program that's building it.
I'd ideally like to only build one executable, and not have to copy around all the dependencies with it.
Here's the code I'm using to compile the assembly:
//Create the compiler (with arguments).
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = true;
cp.OutputAssembly = "example.exe";
cp.GenerateInMemory = false;
//Reference the main assembly (this one) when compiling.
Assembly entryasm = Assembly.GetEntryAssembly();
cp.ReferencedAssemblies.Add(entryasm.Location);
//Reference an external assembly it depends on.
cp.ReferencedAssemblies.Add("someExternal.dll");
//Attempt to compile.
CompilerResults results = provider.CompileAssemblyFromSource(cp, someScript);
The executable this produces still needs someExternal.dll and the program that built it in the same directory when run, and I'd prefer it to be a single executable with all dependencies included.
Is there any way to do this?
In the end, I ended up using the ILRepack.Lib NuGet package for the job, which allows you to merge binaries programmatically, without using a command line tool.
Here's the code I'm using to pack all .dll files in the directory into the executable:
//Setting required options.
RepackOptions opt = new RepackOptions();
opt.OutputFile = "example_packed.exe";
opt.SearchDirectories = new string[] { AppDomain.CurrentDomain.BaseDirectory, Environment.CurrentDirectory };
//Setting input assemblies.
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
opt.InputAssemblies = new string[] { "example.exe", entryasm.Location }.Concat(files).ToArray();
//Merging.
ILRepack pack = new ILRepack(opt);
pack.Repack();
This snippet works fine:
System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
PS.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path));
PS.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainSetup ADS = AppDomain.CurrentDomain.SetupInformation;
AppDomain domain = AppDomain.CreateDomain("Pluging", null, ADS, PS, null);
Assembly asm = Assembly.LoadFile(DLLPath);
domain.Load(asm.FullName);
Creating a new AppDomainSetup fails:
System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
PS.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path));
PS.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainSetup ADS = new AppDomainSetup();
ADS.ApplicationBase= Path;
AppDomain domain = AppDomain.CreateDomain("Pluging", null, ADS, PS, null);
Assembly asm = Assembly.LoadFile(DLLPath);
domain.Load(asm.FullName);
The whole thing is running inside an asp.net project developed in VS2012.
this is the exception I receive:
Could not load file or assembly 'MacroBase, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system
cannot find the file specified.
could you please help?
The problem was that I used to rename dlls before storing them. I still don't know the work around but I changed my algorithm so that I can store and recall dll with the same name as it was originally compiled. Problem solved.
What was the effect of changing AppDomainSetup? In first alternative, asp.net was finding a copy of that renamed dll (with original name) in bin directory of asp.net project.
Suppose Project Main has a reference to Project Ref. In Main, I have defined a CSharpCodeProvider and use it to compile code at runtime.
var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.dll");
// Rest of the referenced assemblies.
The code which is compiled at runtime, might require a newer version of Project Ref to run correctly. So I tried to add the new Ref.Dll in a relative subfolder (plugins):
parameters.ReferencedAssemblies.Add(#"d:\project-output-path\plugins\Ref.dll");
I have also added the following:
AppDomain.CurrentDomain.AppendPrivatePath("plugins");
Problem is when I try to compile the script dynamically, the Ref.dll in the main folder is being used and causes error.
So, What would be the best way to reference the new Ref project only for my script?
P.S. I really prefer not having to create another AppDomain since the dynamically executing code is coupled with the code loaded in current AppDomain and cannot be separated.
I need shell32 in my program to create a shortcut.
This is my code:
var compiler = new CSharpCodeProvider();
var Params = new System.CodeDom.Compiler.CompilerParameters
{
GenerateExecutable = true,
OutputAssembly = outputName,
ReferencedAssemblies = {
"System.dll",
"System.Core.dll",
"System.Windows.Forms.dll",
"System.Drawing.dll",
#"C:\Windows\System32\Shell32.dll"
}
};
Doing this, I get an error:
Metadata file C:\Windows\System32\Shell32.dll could not be opened. An attempt was made to load a program with incorrect format.
Found nothing while searching.. I wasn't even sure what to search for :/
How would I go about doing this?
Shell32.dll (Windows file systems don't care about case, so "s" or "S" shouldn't matter) is not a .NET assembly and thus can't be treated as such.
If you want to call functions exported from non-.NET libraries, you should use the DllImportAttribute.
I had the same problem and just solved it.
Add the following to your referenced Assemblies list:
ReferencedAssemblies.Add("Interop.Shell32.dll");
I'm generating a dynamic assembly using Reflection.Emit which includes a single class. I have a bug which is causing a BadImageException. To resolve this I need to see the compiled code, and therefore I'm saving the dynamic assembly to disk.
I've already tried PEVerify against the assembly which seems to think there are no errors. I now want to view the generated code in Reflector, but the assembly appears as empty (which I know it's not).
Any idea why this is happening?
var assemblyName = new AssemblyName("An.Assembly");
var appDomain = Thread.GetDomain();
var assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
var typeBuilder = moduleBuilder.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class);
...
typeBuilder.CreateType();
assemblyBuilder.Save("temp.dll");
By the way I'm already using the Relection.Emit plugin for reflector which doesn't help with this issue.
Replace:
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
With:
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, "yourfilename.dll");
Then look for it in your current directory, probably your bin folder. Assemblies and modules are technically two separate entities, and you're only saving the assembly information, not the module information (where all your code lives). (Also, don't name them both with the same filename, of course.)