I have an application that uses a CefSharp.OffScreen browser to do a bit of scraping work. It runs in a scripting environment using CSScript to execute a dynamically-loaded class that calls CefSharp to do the work.
CefSharp works perfectly fine in a bin environment. There's even a way to place all of the CefSharp files in their own folder, using ProbingPath. But this only works if CefSharp is running in the same folder as your primary executable, or in the ProbingPath folder you have set up. ProbingPath can only be set up as a subfolder of the executable path.
CefSharp is marshalled from a simple DLL I wrote called MyCompany.Browser. It has a single method in it called Browse that accepts an url string and returns an html string. It does this by spinning up a CefSharp.OffScreen browser and executing it, and this all works perfectly fine in an ordinary bin environment.
In my dynamically-loaded script that CSScript executes, I have code that is functionally equivalent to this (a greatly-simplified, highly-contrived test):
using MyCompany.Browser;
public string GetResult(string url)
{
using (var browser = new CefSharpHeadlessBrowser())
{
return browser.Browse(url);
}
}
The way CSScript works is, if you give it a using MyCompany.Browser; reference, it will look in the folder from which it was executed, find the dll named MyCompany.Browser.dll, and load it for you. CefSharpHeadlessBrowser is a type in this MyCompany.Browser namespace, in a DLL called MyCompany.Browser.dll, in the primary bin folder on a server somewhere, which CSScript happily instantiates.
However, when I try to execute the browser.Browse() method, this happens:
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
These messages are coming from a CheckDependencies() method in CefSharp.dll, which MyCompany.Browser.dll has loaded. However, that's as far as the loading process gets. MyCompany.Browser has loaded because it's in the same folder as CSScript; CefSharp.dll loaded long enough to run its dependency checker and give me the above error messages because MyCompany.Browser.dll has a direct reference to it.
But the rest of CefSharp didn't load, because the dynamically-loaded script is not running in the same bin folder. Instead, it's running in:
c:\Users\admin\AppData\Local\Temp\CSSCRIPT\dynamic\879ec55a-f761-4306-a79c-1af6cf08b312.tmp
I would love for someone to be able to tell me that CefSharp has a registry entry, an app.config element, or something that will notify CefSharp that "Here is where you can find all of your files." Is there something like that, and if not, is there some other way to fix this?
Related
I have a 32 bit application that uses a DLL built by someone else, lets call it xyz.dll. This DLL has dependencies on few other old DLLs. All dlls are saved in the same folder where my app is located. My app compiles fine but in run time, it throws an error "Could not load file or assembly "xyz.dll" or one of its dependencies. is not a valid Win32 application"
I have 2 workarounds that seems to solve this problem. In first one I moved the DLLs to a separated folder and created a batch file to run the app. The batch file first add the dlls' path to the environment, then call the app. Interestingly if I leave the dlls in the same folder with the app and just add this to the path, it wouldn't work.
The second way also moved dlls to a folder and add this path to user environment variable and run the exe directly. Either one of these solutions requires extra steps which is not ideal for app deployment. I am wondering if there is a better way?
When your dll is in the same folder as the application, it is that dll that the application attempts to load, and this fails, as you said.
When you move the dll to another folder and add the pathname of that folder to the PATH environment variable, the application works. In this case, the application is not attempting to load the dll that you have moved to another folder. If this were the case, it would fail. It must be loading another version of the dll that is in one of the folder paths that are in your PATH environment variable.
Simply use Windows search to find all copies of your dll file on your computer. You will be able to determine where that other dll is.
In resume, we want to use the CefSharp dll to embed a browser in our .NET app.
We don't want to add size to our setup since the dll size is quite large.
Here is what i try to do :
I reference the DLL in my project as Copy local to false which when
compiling will not link the DLL in the files.
Before using the cefsharp class in my code i download the DLL plus all the file needed and extract it where the app .exe is located
This is where i hit a wall, if i try to use the cefsharp class after everything is done at the good place the cefsharp will not work
which is normal because the dll have not been loaded (unless an app restart).
Is there a way
to dynamically link my already referenced dll in memory, so i don't
have to restart my application?
Thanks !
I ended up restarting my app...
I need to retrieve the full path (up to directory) of the application's executable file made using mkbundle --static. It is a CLI application that I test on OSX, suppose the executable resides at /usr/local/bin/.
The matters might be further complicated (but I don't really know) since I want to run the utility from any directory, so I add the above path to $PATH environment variable (in this case, it is already there).
Now, suppose the application is launched while being at ~/dir1/dir2/, and suppose it prints the Application.StartupPath. That yields the path ~/dir1/dir2/. In contrast, I want to always retrieve the real directory from which the application is launched, i.e. /usr/local/bin/.
Is there any way to achieve this (preferably in a platform-independent way)?
I use Xamarin Studio configured with Mono/.NET 4.5 and C# 6.0.
UPDATE: Getting typeof(Program).Assembly.Location also doesn't help much.
I mean, it works well when I just run the normal application executable (produced during the build process).
However, if I run a bundle made with mkbundle --static, the Location just gives the executable name App.exe without any prior path.
Probably it just displays the relative path inside the bundle. Is there any way I can get the path to the bundle itself?..
The only thing I've found reliable (probably not the fastest way though) is through Process:
Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
With a type defined in an assembly that is part of your application you can find its location by doing:
string location = typeof(Foo).Assembly.Location;
This gives you the full path to the .dll or .exe, depending on where the type Foo is defined. Then you can use Path.GetDirectoryName if you only want the directory.
string directory = System.IO.Path.GetDirectoryName(location);
The above should work with Mono and also on Windows.
I have my WCF service that uses a third party DLL. this third party DLL is a com register DLL no problem there. But this DLL used an unmanaged, not registrable DLL that has to be in local execution path of the other DLL. The problem is that when my WCF start on IIS it load the third party DLL assembly but the DLL cannot find his DLL as it's not in my application bin folder. I manually putted the other DLL in the bin folder but the execution path is not there. That third party DLL does have methods to expose files in his directory but it doesn't see the file.
I know the problem is that because if i copy paste the method in a console app it run flawlessly but i HAVE to put the DLL's the third party DLL uses into my BIN folder to make it work. Calling the DLL method to see local file clearly shows that it uses my application execution path. I have no problem with having to do that. If i could force the execution path of my Service to always be the same in a place i could know i would simply shove these extra DLL in their and forget about it.
Anyone have an idea how to achieve that ?
The only solution is to create a console application. Install it on the server anywhere else than the web service. Hard code the console executable path into the web service and make the web service start the console app process passing the parameters to it then wait for process exit. Once the console app close go read the log file that it created and extract the result. Then simply return to the client the result.
Setup: MVC Web Api app, Visual Studio 2012
Folder layout:
D:\WebSites\MySite\bin\MyDLLBin\Some.dll
My application needs to LoadLibrary on an unmanaged DLL as part of a MVC Web API application. Before doing the LoadLibrary, I do a:
File.Exists(#"D:\WebSites\MySite\bin\MyDLLBin\Some.dll")
And this returns false which means I should not do the LoadLibrary.
I tried copying the DLL here:
C:\MyDLLs\Some.Dll
and
File.Exists(#"C:\MyDLLs\Some.DLL")
returns TRUE. So I do a LoadLibrary from there and everything is goodness.
I created the "C:\MyDLLs" folder by logging onto the server and creating it. The "D:\WebSites\MySite\bin\MyDLLBin" folder is created via Publishing from Visual Studio.
I think maybe some kind of permission problem, but I have logged onto the server and set "Everyone" to "Full Access" on every folder in the path "D:\WebSites\MySite\bin\MyDLLBin" and the File.Exists still fails.
It would be better for me to deploy Some.dll as part of the publish to the bin folder and not have to create a special folder on the server to hold the dll.
Can someone suggest a fix or some other things to try?
UPDATE #1:
Interestingly:
System.IO.FileInfo(#"D:\WebSites\MySite\bin\MyDLLBin\Some.dll").Length
does not throw an exception and returns 7132045.
Assuming that filePathInApp is the string holding the path to your file from the root of where the application is running (as opposed to the root of the file system),
Server.MapPath(filePathInApp) will alter your directory path to be "rooted" wherever the application is running. So you may want to try Server.MapPath("some.dll") or Server.MapPath("\MyDLLBin\some.dll")