libgit2 / libgit2sharp

Git + .NET = ❤
http://libgit2.github.com
MIT License
3.17k stars 886 forks source link

Allow loading native dependencies from PATH environment variable #2019

Closed glopesdev closed 1 year ago

glopesdev commented 1 year ago

LibGit2Sharp should respect the system specific library search paths. Not doing so prevents a wide-range of deployment scenarios from working properly.

It seems like LibGit2Sharp assumes specific directory structures for dependencies, which might or might not match the actual application deployment needs. There is an option to set native library paths explicitly, but this requires hard-coding strings in the application code and makes it impossible to separate coding of individual components from application packaging and deployment.

Please make sure to respect library search paths, such as the PATH environment variable in Windows (and similar strategies for Linux, etc).

Reproduction steps

Deploy git2-106a5f2.dll to a separate folder. Set PATH to include this folder. Call LibGit2Sharp methods.

Expected behavior

The native dependency is loaded since PATH includes its location as per Dynamic-link library search order.

Actual behavior

LibGit2Sharp crashes with "The specified file was not found" exception.

Version of LibGit2Sharp (release number or SHA1)

0.26.2

Operating system(s) tested; .NET runtime tested

Windows 10 / 11

glopesdev commented 1 year ago

Starting from Windows 8 and Windows 7 SP1 KB2533623, Microsoft introduced new API enhancements for securely loading external native libraries.

These API calls define a process wide DLL search path which can be modified only by direct calls to these OS-specific functions. LibGit2Sharp specifies the DefaultDllImportSearchPath attribute set to DllImportSearchPath.SafeDirectories which means that only this process wide DLL search path is used for loading native libraries, and the directories under the default PATH environment variable are ignored.

To workaround this, host applications should call the AddDllDirectory method for each active native library folder when bootstrapping the environment, if they require additional dynamic paths to be searched.

This approach already works today on libgit2sharp. If all PATH libraries need to be searched, the host application should scan the PATH and add all those directories manually to the process wide DLL search path using AddDllDirectory.