I'm working on a SolidWorks plugin (DLL). It depends on a couple of files (sqlite DB, sketches etc). To install the plugin, you only have to open the DLL with SolidWorks.
In the DLL are some routines that call File.Open() on a number of resource files that I'll refer to by relative paths. The dir. hierarchy would look like:
Plugin/
plugin.dll
Sketches/
various.sldprt
otherfile.db
otherdeps.txt
...
Where the root dir. of the plugin can be anywhere on the system. The plugin can be easily loaded by SolidWorks with Open File Dialog. The problem is that once I load the DLL, any calls to File.Open() (eg File.Open("Sketches/various.sldprt")) with relative paths won't work because it'll be relative to the dir. where SLDWORKS.exe (SW install dir.) resides instead of the dir. of the DLL. This would mean I'll have to put all my resource files in the SolidWorks install dir., which I would like to avoid. Is that possible?
What you can do is add your addin folder as a prefix to any local path before calling File.Open().
Addin folder can be obtained as :
string path = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
Related
How can I programmatically get the path of the current project in my C# code?
Do I have any preprocessor directives for this? Or any macros?
Note: I don't need the path of the current executing assembly, but rather a path of the project, from which this assembly was compiled.
Note (2) - What I'm trying to achieve: I have several files that are compiled as embedded resources. I load and use them in the runtime. I would like to create a "debug" mode, in which the files are loaded from their original location on disk and not from the resource stream. This would enable me to fast-edit the files for test purposes without the need to recompile the assembly.
Since the assembly is copied to a different location, outside the project from which it was compiled, in the "debug" mode I can't load the files using relative path.
You might be able to make use of the CallerFilePathAttribute.
https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callerfilepathattribute(v=vs.110).aspx
string fileName = "SampleFile.txt";
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LocalConstants.EMAIL_PATH, fileName);
C:\****\****\Documents\Visual Studio 2010\Projects\WindowsApplication1\WindowsFormsApplication1\bin\Debug\Emails\SampleFile.txt
I have to use the C# class library code in my native code which is written in c++. For this I added one interface written in c++ add the my C# class library project as dependency to it. This works fine till I put the C# dll in .exe folder , but I put this in libs folders (where we keep our dll's), I get file not found exception when tried to call the C# dll function.
Is there any way to keep c# dll in libs folder and make it work?
Thanks.
Yes, you need to re-add it from the libs folder and it will be fine. Or if you are naming the DLL in your code itself, then just provide the full path along with the DLL name. Then when you recompile, the .exe will contain the path you gave it in the source code and will look for the DLL there.
From the MSDN(LoadLibrary),
Remarks section::
The first directory searched is the directory containing the image
file used to create the calling process (for more information, see the
CreateProcess function). Doing this allows private dynamic-link
library (DLL) files associated with a process to be found without
adding the process's installed directory to the PATH environment
variable. If a relative path is specified, the entire relative path is
appended to every token in the DLL search path list. To load a module
from a relative path without searching any other path, use
GetFullPathName to get a nonrelative path and call LoadLibrary with
the nonrelative path. For more information on the DLL search order,
see Dynamic-Link Library Search Order.
The search path can be altered
using the SetDllDirectory function. This solution is recommended
instead of using SetCurrentDirectory or hard-coding the full path to
the DLL.
If a path is specified and there is a redirection file for
the application, the function searches for the module in the
application's directory. If the module exists in the application's
directory, LoadLibrary ignores the specified path and loads the module
from the application's directory. If the module does not exist in the
application's directory, LoadLibrary loads the module from the
specified directory. For more information, see Dynamic Link Library
Redirection.
If you call LoadLibrary with the name of an assembly
without a path specification and the assembly is listed in the system
compatible manifest, the call is automatically redirected to the
side-by-side assembly.
This is all you need to know about path search of a dll. The easy solution, enter the full path in LoadLibrary call or set your PATH environment variable to contain the alternate path of the dll.
I have a compiled c# assembly that I am registering for COM exposure. In order to import my library into some legacy c++ code the .tlb file needs to be in one of my "include" directories.
Instead of adding my bin directory to the include directories of the project that will use it, and since these projects will always be compiled under the same folder structure, I was wondering if, on compile, it was possible to direct my .tlb file to a specific directory.
In the Project Properties under the Build Events there is a Post-build events section. Here you can apply any command you'd like, including copy.
Here's some example code that will copy a file form the bin\Debug directory to another directory in the C:\ drive.
copy "$(TargetDir)\filename.tlb" "C:\output directory path\"
Use XCOPY in a post-build task.
If I reference an external unmanaged DLL in C# by the following:
[DLLImport("MyDLL.dll", ...
Where should the DLL be placed when I want to run the code from my IDE? Should it be in the bin\Debug folder?
Which compiling configuration you are using?
If you want to run the application from Visual Studio Debug/Run it would be in your project folder
If you want to run by double click, it should be near your exe which is in
bin\Debug
or
bin\Release
folder.
Anywhere locatable by the LoadLibrary function. See Dynamic-Link Library Search Order for more information:
If SafeDllSearchMode is enabled, the search order is as follows:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
bin\Debug satisfies the first point, assuming that you're only ever running the application in its Debug configuration.
Yes, alongside the .exe file produced by the compiler (which ends up in bin\Debug\ as you said) should be perfect.
I have a C# application that is being internationalized. I want to keep all of my language resource directories (en-US, es-SP, etc...) in a single directory called "languages" within the installation directory, so that the file path would be something like C:\application\
languages\en-US\resource.dll for each compiled resource file.
Unfortunately, the .dll that references the language resource file is in the C:\application\mainprogram.dll location. What do I need to set in Visual Studio so that mainprogram.dll can correctly access all of my language resource dll files?
Also of note is that the language resource files work fine if all of their folders are on the same level as the mainprogram.dll file.
You can specify additional private paths using the Probing Element in your configuration.
Alternatively and probably more than you would need:
You can hook in to the AppDomains Assembly resolve event which gets called every time it fails to find an assembly via standard probing.