Simple ASMX WebService and DLL not loaded - c#

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

Related

Costura not loading Native Dll

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; }
}

SharpShell server .dll NOT signed

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

How to skip the code which produces error when dll is Missing in C#?

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

Can I obtain the ClickOnce published Product Name from inside the application?

I have a ClickOnce Publish Name that is different from the assembly name. For discussion purposes, it is "App 6.0". I set it in the Properties for my project. Is there any way to get this value from inside the program?
Add a reference to Microsoft.Build.Tasks.v4.0.dll, then run this:
if (null != AppDomain.CurrentDomain.ActivationContext)
{
DeployManifest manifest;
using (MemoryStream stream = new MemoryStream(AppDomain.CurrentDomain.ActivationContext.DeploymentManifestBytes))
{
manifest = (DeployManifest)ManifestReader.ReadManifest("Deployment", stream, true);
}
// manifest.Product has the name you want
}
else
{
// not deployed
}
The DeployManifest can also provide other useful info from your manifest, like Publisher or SupportUrl.
The answer can be found in ClickOnce Run at Startup. Essentially, you use InPlaceHostingManager to get the ClickOnce manifest and read it. It bugs me that it is an asynchronous method, but this is the only thing that has worked thus far. Simplifications are much appreciated. See the webpage for a description of DeploymentDescription.
var inPlaceHostingManager = new InPlaceHostingManager(ApplicationDeployment.CurrentDeployment.UpdateLocation, false);
inPlaceHostingManager.GetManifestCompleted += ((sender, e) =>
{
try
{
var deploymentDescription = new DeploymentDescription(e.DeploymentManifest);
string productName = deploymentDescription.Product;
***DoSomethingToYour(productName);***
// - use this later -
//var commandBuilder = new StartMenuCommandBuilder(deploymentDescription);
//string startMenuCommand = commandBuilder.Command;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
}
});
ApplicationDeployment.UpdatedApplicationFullName Property

Application Specific Paths for DLL Loading when DLL is loaded dynamically

I am building a program that uses a very simple plugin system. This is the code I'm using to load the possible plugins:
public interface IPlugin
{
string Name { get; }
string Description { get; }
bool Execute(System.Windows.Forms.IWin32Window parent);
}
private void loadPlugins()
{
int idx = 0;
string[] pluginFolders = getPluginFolders();
Array.ForEach(pluginFolders, folder =>
{
string[] pluginFiles = getPluginFiles(folder);
Array.ForEach(pluginFiles, file =>
{
try
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(file);
Array.ForEach(assembly.GetTypes(), type =>
{
if(type.GetInterface("PluginExecutor.IPlugin") != null)
{
IPlugin plugin = assembly.CreateInstance(type.ToString()) as IPlugin;
if(plugin != null)
lista.Add(new PluginItem(plugin.Name, plugin.Description, file, plugin));
}
});
}
catch(Exception) { }
});
});
}
When the user selects a particular plugin from the list, I launch the plugin's Execute method. So far, so good! As you can see the plugins are loaded from a folder, and within the folder are several dll's that are needed but the plugin. My problem is that I can't get the plugin to 'see' the dlls, it just searches the launching applications startup folder, but not the folder where the plugin was loaded from.
I have tried several methods:
1. Changing the Current Directory to the plugins folder.
2. Using an inter-op call to SetDllDirectory
3. Adding an entry in the registry to point to a folder where I want it to look (see code below)
None of these methods work. What am I missing? As I load the dll plugin dynamically, it does not seem to obey any of the above mentioned methods. What else can I try?
Regards,
MartinH.
//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
Microsoft.Win32.RegistryKey appPaths = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(
string.Format(
#"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\{0}",
System.IO.Path.GetFileName(Application.ExecutablePath)),
Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree);
appPaths.SetValue(string.Empty, Application.ExecutablePath);
object path = appPaths.GetValue("Path");
if(path == null)
appPaths.SetValue("Path", System.IO.Path.GetDirectoryName(pluginItem.FileName));
else
{
string strPath = string.Format("{0};{1}", path, System.IO.Path.GetDirectoryName(pluginItem.FileName));
appPaths.SetValue("Path", strPath);
}
appPaths.Flush();
Use Assembly.LoadFrom not Assembly.LoadFile
Whenever I dynamically load plugins like this, I usually create an app domain and load the assembly in the new app domain. When creating an app domain, you can specify the base directory. Dependent assemblies will be loaded from this base directory.

Categories