I am unable to get Costura to load a Native dll that my project needs to run. This is a full native dll so it is not a reference in the project.
I have added the dll to the costura32 folder in my project and set it as an embedded resource.
When I run the project I can see that costura has extracted the dll to %temp%\costura\1D5629B8D94FC3E9B53C7AB358A0E123\32\native.dll
The project is still unable to find the file with the error Unable to load DLL
When looking in procmon I can see that it looks for the file in the local folder then in %temp%\costura\1D5629B8D94FC3E9B53C7AB358A0E123\native.dll and cannot find it. It doesn't seem to be looking for it in the "32" folder.
I have tried several options in the config file Unmanaged32Assemblies, PreloadOrder but they all have the same result.
I cannot see what I am doing wrong here.
In my case I tried to access temp path for setting library path with below code and it worked.
private bool SetupSevenZipLibrary()
{
string costuraExtractionPath = null;
try
{
DirectoryInfo di = null;
string costuraTempPath = Path.Combine(
Path.GetTempPath(),
"Costura" //ex: Costura
);
di = new DirectoryInfo(costuraTempPath);
if (!di.Exists)
return false;
costuraExtractionPath = di.GetDirectories().First().FullName;
if (!Directory.Exists(costuraExtractionPath))
throw new Exception();
string sevenZipPath = Path.Combine(
costuraExtractionPath,
Environment.Is64BitProcess ? "64" : "32", "7z.dll"
);
if (!File.Exists(sevenZipPath))
throw new Exception();
SevenZipBase.SetLibraryPath(sevenZipPath);
return true;
}
catch { return false; }
}
Related
I need to develop a Shell Context Menu extension that references some other custom assemblies... I don't want to assign a Strong Name Key to those custom assemblies!
The guide I followed to do this uses the SharpShell project and illustrates how to sign (but does not expalins why) the assembly... and this is my problem: if I sign my final .dll then I have many errors during my project's building phase, because some assemblies my project references are not strongly named ("Referenced assembly does not have a strong name").
In general, googling about the C# Shell Extension implementation, all best tutorials I found sign the final assembly... is it mandatory?
Without signing the assembly ServerManager.exe returns this error: "The file 'XYZ.dll' is not a SharpShell Server".
Finally I've solved my troubles... the SharpShell.dll file obtained through NuGet was a different version of the ServerManager.exe ones.
Uninstalling the SharpShell NuGet package and directly referencing the SharpShell.dll you find inside the ServerManager folder was my solution!
Moreover, I was looking between the article comments... please read this question.
You don't need to use old DLL.
Please use this code directly, without using ServerManager.exe.
private static ServerEntry serverEntry = null;
public static ServerEntry SelectedServerEntry
{
get
{
if (serverEntry == null)
serverEntry = ServerManagerApi.LoadServer("xxx.dll");
return serverEntry;
}
}
public static ServerEntry LoadServer(string path)
{
try
{
// Create a server entry for the server.
var serverEntry = new ServerEntry();
// Set the data.
serverEntry.ServerName = Path.GetFileNameWithoutExtension(path);
serverEntry.ServerPath = path;
// Create an assembly catalog for the assembly and a container from it.
var catalog = new AssemblyCatalog(Path.GetFullPath(path));
var container = new CompositionContainer(catalog);
// Get the exported server.
var server = container.GetExport<ISharpShellServer>().Value;
serverEntry.ServerType = server.ServerType;
serverEntry.ClassId = server.GetType().GUID;
serverEntry.Server = server;
return serverEntry;
}
catch (Exception)
{
// It's almost certainly not a COM server.
MessageBox.Show("The file '" + Path.GetFileName(path) + "' is not a SharpShell Server.", "Warning");
return null;
}
}
Install code:
ServerRegistrationManager.InstallServer(SelectedServerEntry.Server, RegistrationType.OS64Bit, true);
Register code:
ServerRegistrationManager.RegisterServer(SelectedServerEntry.Server, RegistrationType.OS64Bit);
I have a Console Application in C# and a Class Library named AppManager.cs. The Method of this class is used in the console Application as given below.
try
{
AppManager mgr = new AppManager(); //Want to skip this line when dll is missing.
mgr.Method_Name(this, true); //Want to skip this line when dll is missing.
}
catch (Exception)
{
}
When I have published the Code and extracted only exe then application fails to run [I know as the exe try to find that dll and method present in dll won't available].
Now my Question is That Is there any way to skip the code which will produce error when it will not find the reference of dll.
I also tried this but it didn't worked:
String file = null;
String filePath = Path.GetDirectoryName(Application.ExecutablePath);
file = Directory.GetFiles(filePath, "myLibrary.dll", SearchOption.AllDirectories)
.FirstOrDefault();
if (file != null)
{
AppManager mgr = new AppManager();
mgr.Method_Name(this, true);
}
If you do that, it won't give the desired output too. Why don't you integrate the dll with your exe? You can do it by using this tool
Can you not simply check if the dll exists or not?
string filePath = #"SOME_PATH";
var exists = File.Exists(filePath);
if(exists)
{
AppManager mgr = new AppManager();
mgr.Method_Name(this, true);
}
I have a Resource project I use for various parts of our products. To make it more flexible I decided to place the .resx externally from the dll processed with the resgen tool, to allow users to add their own language files on the fly. Since the project will be accessed from various places, web, service or stand-alone winForm, how can I get the path of where the .dll is located so that I can supply the correct path for
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
temp = ResourceManager.CreateFileBasedResourceManager("Resources", cwd, null);
resourceMan = temp;
}
return resourceMan;
}
}
I can hardcode the path and it works great, though I would rather have it figure out the path at runtime.
I tried something like this, however it did not work
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(Resources)).Location;
//get the folder that's in
string theDirectory = Path.GetDirectoryName(fullPath); ResourceManager temp =
"Could not find any resources appropriate for the specified culture (or the neutral culture) on disk.
baseName: Resources locationInfo: fileName: Resources.resources"
Found the following to work from
How do I get the path of the assembly the code is in?
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
var path = Uri.UnescapeDataString(uri.Path);
var theDirectory = Path.GetDirectoryName(path);
I've a problem running an ASMX Web Service. I'm Calling a DLL from a method (AceptaTools.dll) and this DLL load ca4xml.dll.
AceptaTools.dll has been registered with REGSVR32. But ca4xml.dll Can't.
When i Invoke the service:
_objURL = _CA4XML.GetLastResponse();
i get a message "ca4xml.dll not loaded".
Looking al Dependency Walker:
Here both files in detail:
Both DLL are in BIN folder and my project run as x86... Why can't load?? Please help.
[WebMethod]
public string Send(string Ip, string Puerto, string NroDocumento, string TipoDocumento, string Comando, string Impresora, string Linea)
{
try
{
int _Result = 0;
string _Null = "";
string _objURL;
//Config Capsula
string serverConfig = "cfg|" + Ip.ToString() + "|" + Puerto.ToString() + "|10";
//Impresora FACTURA,1 por Defecto.
if (string.IsNullOrEmpty(Impresora)) { Impresora = "FACTURA,1"; }
if (string.IsNullOrEmpty(NroDocumento)) { NroDocumento = "0"; }
if (string.IsNullOrEmpty(Comando)) { Comando = "generar"; }
//Nuevo CAXML Cliente
AceptaTools.CA4XML_Client _CA4XML = new CA4XML_Client();
_Result = _CA4XML.Send(ref serverConfig, ref NroDocumento, ref Comando, ref Impresora, ref Linea, out _Null);
if (_Result != 0)
{
_objURL = _CA4XML.GetLastResponse(); //Get URL
return _objURL.ToString();
}
else
{
return "Error";
}
}
catch (Exception ex)
{
return ex.Message.ToString();
}
}
}
Did you make sure that the ca4xml.dll is deployed properly? Since I guess it is not referenced as .NET assembly the VS will treat it like a normal file and you will need to specifically tell VS to include it when deploying.
Do the following steps to check whether deployment has been setup properly:
Open the Solution Explorer -> Got to the ca4xml.dll -> Right click -> Select Properties -> Set Build Action = None & Copy to Output = Always
Also in addition to the Dependency Walker I suggest to use Process Monitor. When you use the file access view (disregarding registry changes etc.) you can see all the locations where a process tries to load a dll from. Afterwards you can make sure that the dll you are missing is in one of the listed locations, here is the link:
http://technet.microsoft.com/en-us/sysinternals/bb896645
When you do not load DLL in the program because you need to update some things .
you can update project in nuget manager
In a web application, I want to load all assemblies in the /bin directory.
Since this can be installed anywhere in the file system, I can't gaurantee a specific path where it is stored.
I want a List<> of Assembly assembly objects.
Well, you can hack this together yourself with the following methods, initially use something like:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
to get the path to your current assembly. Next, iterate over all DLL's in the path using the Directory.GetFiles method with a suitable filter. Your final code should look like:
List<Assembly> allAssemblies = new List<Assembly>();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (string dll in Directory.GetFiles(path, "*.dll"))
allAssemblies.Add(Assembly.LoadFile(dll));
Please note that I haven't tested this so you may need to check that dll actually contains the full path (and concatenate path if it doesn't)
To get the bin directory, string path = Assembly.GetExecutingAssembly().Location; does NOT always work (especially when the executing assembly has been placed in an ASP.NET temporary directory).
Instead, you should use string binPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
Further, you should probably take the FileLoadException and BadImageFormatException into consideration.
Here is my working function:
public static void LoadAllBinDirectoryAssemblies()
{
string binPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin"); // note: don't use CurrentEntryAssembly or anything like that.
foreach (string dll in Directory.GetFiles(binPath, "*.dll", SearchOption.AllDirectories))
{
try
{
Assembly loadedAssembly = Assembly.LoadFile(dll);
}
catch (FileLoadException loadEx)
{ } // The Assembly has already been loaded.
catch (BadImageFormatException imgEx)
{ } // If a BadImageFormatException exception is thrown, the file is not an assembly.
} // foreach dll
}
You can do it like this, but you should probably not load everything into the current appdomain like this, since assemblies might contain harmful code.
public IEnumerable<Assembly> LoadAssemblies()
{
DirectoryInfo directory = new DirectoryInfo(#"c:\mybinfolder");
FileInfo[] files = directory.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
// Load the file into the application domain.
AssemblyName assemblyName = AssemblyName.GetAssemblyName(file.FullName);
Assembly assembly = AppDomain.CurrentDomain.Load(assemblyName);
yield return assembly;
}
yield break;
}
EDIT: I have not tested the code (no access to Visual Studio at this computer), but I hope that you get the idea.
I know this is a old question but...
System.AppDomain.CurrentDomain.GetAssemblies()