Reference shell32.dll in a programmatically compiled program? - c#

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");

Related

CefSharp NuGet package, AnyCPU cannot find files

I am currently trying to write a small service, which uses CefSharp (v57.0.0) to render HTML to a PDF file and followed the instructions to use "Any CPU" in my project (Feature Request - Add AnyCPU Support).
In my project I used the following assembly resolver that seems to work fine (it loads CefSharp.Core.dll, CefSharp.dll during initialisation):
// Will attempt to load missing assembly from either x86 or x64 subdir
private static Assembly Resolver(object sender, ResolveEventArgs args)
{
if (args.Name.StartsWith("CefSharp", StringComparison.Ordinal))
{
string assemblyName = args.Name.Split(new[] { ',' }, 2)[0] + ".dll";
string archSpecificPath = Path.Combine(
AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
Environment.Is64BitProcess ? "x64" : "x86",
assemblyName);
var outputAssembly = File.Exists(archSpecificPath) ? Assembly.LoadFile(archSpecificPath) : null;
return outputAssembly;
}
return null;
}
For the initialisation of CefSharp I set exactly the same values like in the example:
var settings = new CefSettings()
{
// By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
};
// Perform dependency check to make sure all relevant resources are in our output directory.
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
However, if I start my simple test, I get the following error code:
Message: System.Exception : Unable to locate required Cef/CefSharp dependencies:
Missing:CefSharp.BrowserSubprocess.exe
Missing:CefSharp.BrowserSubprocess.Core.dll
Missing:CefSharp.Core.dll
Missing:CefSharp.dll
Missing:icudtl.dat
Missing:libcef.dll
Executing Assembly Path:D:\projects\CefService\bin\Debug\x86
Any ideas what might be happening here and how to solve the problem?
The message is pretty clear, other assemblies could not be loaded.
Here are some generic instructions on how to do that:
load native ones (e.g. libcef.dll) first with LoadLibrary and FreeLibrary
see if loading a managed one will automatically load other managed ones it depends, else handle them (tedious)
You might be interested in these tools for spotting dependencies:
http://www.dependencywalker.com/
https://github.com/isindicic/DependencyWalker.Net
How do I determine the dependencies of a .NET application?

Globally importing VB.Net namespaces

I've got a C# program this is attempting to dynamically compile some VB.Net code.
var vbc = new Microsoft.VisualBasic.VBCodeProvider(new Dictionary<string, string>
{ { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters(new[] {"mscorlib.dll", "System.Core.dll",
"System.Data.dll", "System.dll", "System.Xml.dll", "Microsoft.VisualBasic.dll"},
#"MyFile.exe", false)
{
GenerateInMemory = false,
GenerateExecutable = true
};
CompilerResults results = vbc.CompileAssemblyFromFile(parameters, "file1.vb", "file2.vb",
"file3.vb", "file4.vb");
It's working, but with errors. The problem is, in a real Visual Basic project, by default, the following namespaces are automatically imported:
System
System.Collections
System.Collections.Generic
System.Data
System.Diagnostics
System.Linq
System.Xml.Linq
System.Threading.Tasks
Microsoft.VisualBasic
You can verify this yourself by going to create a new Visual Basic project, then looking at the properties of the project and clicking References. You will see that the above listed namespaces are automatically imported.
My question is, how do I globally auto import these namespaces and pass it into VBCodeProvider so it will automatically import these when it tries to compile?
I found a similar question to mine here, however, no answers have been provided except by the OP, who is doing something "hacky", which I prefer not to do.

How to dynamically compile source files into assembly in C#

I am aware of a class called AssemblyBuilder, and I would have thought I could use it to pass a folder containing C# source files, or pass a single C# source file to it in order to compile the source into an assembly (.dll) which can then be referenced in a config file.
I'm aware of csc.exe which can compile C#, and I'm effectively looking for a way to replicate this dynamically.
I couldn't figure out how to use AssemblyBuilder, or whether this is the wrong class to be using, or whether I should be doing something similar to the following:
http://support.microsoft.com/kb/304655
Can you point me in the right direction please.
You might want to look into CodeDomProvider
Example snippet:
CompilerParameters parms = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
IncludeDebugInformation = false
};
parms.ReferencedAssemblies.Add("System.dll");
parms.ReferencedAssemblies.Add("System.Data.dll");
CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
return compiler.CompileAssemblyFromSource(parms, source);
Warning: assemblies built dynamically in this fashion won't be handled by the garbage collector.

Including an embedded resource in a compilation made by Roslyn

I'm attempting to include an embedded resource into a dll that I am compiling using Roslyn. I've found something that helped put me on the right track here.
However, when I create the dll using the following code:
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
I find that it will pass all of the unit tests that I have created for the project except for those that rely on the Resources file.
The error I'm getting looks like the following:
System.Resources.MissingManifestResourceException ... Make sure "[Project].Properties.Resources.resources" was correctly embedded or linked into
assembly "[Project]" at compile time, or that all the satellite assemblies required are loadable and fully signed.
The dll is supposed to be signed, and when it is emitted by roslyn it comes out with the correct public key. Also, the Resource.resx is included in my project directly in the Properties folder.
I would appreciate any help anyone could provide.
Ok, so while I was looking for answers, I came across this web page where it was commented that the resource stream was null until the he added the namespace.
So after adding the namespace I got somehting like this
const string resourcePath = #"C:\Projects\...\Properties\Resources.resources";
var resourceDescription = new ResourceDescription(
"[namespace].Resources.resources",
() => File.OpenRead(resourcePath),
true);
var result = mutantCompilation.Emit(file, manifestResources: new [] {resourceDescription});
which runs exactly like you'd expect.

How do I pass parameters in run-time compilation in c#, winforms?

I'm stuck on run-time compilation and CodeDom.
Here's a simplified example of what I have so far.
public static void Testing()
{
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
string Output = "Out.exe";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Drawing.Dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.Dll");
parameters.CompilerOptions = "/t:winexe";
string[] text = new string[] { #"C:\MyProject\Test.cs", #"C:\MyProject\Test.Designer.cs",
#"C:\MyProject\Program.cs"};
CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, text);
Process.Start(Output);
}
It works perfectly alright, and loads the Test form.
But! I need to pass a parameter to this Test form (a list of Panel controls) to populate the form.
How can I do this? Maybe, I am looking in the wrong direction, and it has to be done in a different way?
Thanks a lot in advance!
EDIT
In the end, I give up on CodeDom and used Mono.Cecil instead, injecting .exe file with information from my main program.
What you are doing is compiling an executable assembly then starting it in another process.
If you want to pass it information, command line arguments are one option. However, passing a .Net object on the command line will not work.
If you want to pass somthing managed you will have to use your new assembly with some late binding and pass your object to the constructor perhaps, rather depends what the code you are compiling accepts, if you have that at design time ...
Are you re-writing Visual Studio?

Categories