c# 使用GADL: Can‘t load requested DLL错误处理
关于使用c#使用GADL处理矢量或者栅格数据的资料,大家随便都能找到很多,这里不做赘述。
现在需要处理如标题所述的gdal Can't load requested DLL的问题,今天遇到的问题详细为:
gdal Can't load requested DLL ogr_MSSQLSpatial.dll ,都知道使用GDAL要先初始化配置:
GdalConfiguration.ConfigureGdal();GdalConfiguration.ConfigureOgr();
初始化配置在添加GADL包后自动生成的GdalConfiguration.cs中:
/******************************************************************************** Name: GdalConfiguration.cs.pp* Project: GDAL CSharp Interface* Purpose: A static configuration utility class to enable GDAL/OGR.* Author: Felix Obermaier******************************************************************************** Copyright (c) 2012-2018, Felix Obermaier** Permission is hereby granted, free of charge, to any person obtaining a* copy of this software and associated documentation files (the "Software"),* to deal in the Software without restriction, including without limitation* the rights to use, copy, modify, merge, publish, distribute, sublicense,* and/or sell copies of the Software, and to permit persons to whom the* Software is furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included* in all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER* DEALINGS IN THE SOFTWARE.*****************************************************************************/using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Gdal = OSGeo.GDAL.Gdal;
using Ogr = OSGeo.OGR.Ogr;namespace TifPipei
{public static partial class GdalConfiguration{private static volatile bool _configuredOgr;private static volatile bool _configuredGdal;private static volatile bool _usable;[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]static extern bool SetDefaultDllDirectories(uint directoryFlags);// LOAD_LIBRARY_SEARCH_DEFAULT_DIRSprivate const uint DllSearchFlags = 0x00001000;[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]static extern bool AddDllDirectory(string lpPathName);/// <summary>/// Construction of Gdal/Ogr/// </summary>static GdalConfiguration(){string executingDirectory = null, gdalPath = null, nativePath = null;try{if (!IsWindows){const string notSet = "_Not_set_";string tmp = Gdal.GetConfigOption("GDAL_DATA", notSet);_usable = tmp != notSet;return;}executingDirectory = AppContext.BaseDirectory;if (string.IsNullOrEmpty(executingDirectory))throw new InvalidOperationException("cannot get executing directory");// modify search place and orderSetDefaultDllDirectories(DllSearchFlags);gdalPath = Path.Combine(executingDirectory, "gdal");nativePath = Path.Combine(gdalPath, GetPlatform());if (!Directory.Exists(nativePath))throw new DirectoryNotFoundException($"GDAL native directory not found at '{nativePath}'");if (!File.Exists(Path.Combine(nativePath, "gdal_wrap.dll")))throw new FileNotFoundException($"GDAL native wrapper file not found at '{Path.Combine(nativePath, "gdal_wrap.dll")}'");// Add directoriesAddDllDirectory(nativePath);AddDllDirectory(Path.Combine(nativePath, "plugins"));// Set the additional GDAL environment variables.string gdalData = Path.Combine(gdalPath, "data");Environment.SetEnvironmentVariable("GDAL_DATA", gdalData);Gdal.SetConfigOption("GDAL_DATA", gdalData);//string driverPath = Path.Combine(nativePath, "plugins");Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", "./gdal/plugins");OSGeo.OSR.Osr.SetPROJSearchPath("./gdal/plugins");Environment.SetEnvironmentVariable("GEOTIFF_CSV", gdalData);Gdal.SetConfigOption("GEOTIFF_CSV", gdalData);//string projSharePath = Path.Combine(gdalPath, "share");//Environment.SetEnvironmentVariable("PROJ_LIB", projSharePath);//Gdal.SetConfigOption("PROJ_LIB", projSharePath);//OSGeo.OSR.Osr.SetPROJSearchPaths(new[] { projSharePath });Environment.SetEnvironmentVariable("PROJ_LIB", "./gdal/share");OSGeo.OSR.Osr.SetPROJSearchPath("./gdal/share");string certificateFile = Path.Combine(gdalPath, "curl-ca-bundle.crt");Gdal.SetConfigOption("GDAL_CURL_CA_BUNDLE", certificateFile);_usable = true;}catch (Exception e){_usable = false;Trace.WriteLine(e, "error");Trace.WriteLine($"Executing directory: {executingDirectory}", "error");Trace.WriteLine($"gdal directory: {gdalPath}", "error");Trace.WriteLine($"native directory: {nativePath}", "error");//throw;}}/// <summary>/// Gets a value indicating if the GDAL package is set up properly./// </summary>public static bool Usable{get { return _usable; }}/// <summary>/// Method to ensure the static constructor is being called./// </summary>/// <remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>public static void ConfigureOgr(){if (!_usable) return;if (_configuredOgr) return;// Register driversOgr.RegisterAll();_configuredOgr = true;PrintDriversOgr();}/// <summary>/// Method to ensure the static constructor is being called./// </summary>/// <remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>public static void ConfigureGdal(){if (!_usable) return;if (_configuredGdal) return;// Register driversGdal.AllRegister();_configuredGdal = true;PrintDriversGdal();}/// <summary>/// Function to determine which platform we're on/// </summary>private static string GetPlatform(){return Environment.Is64BitProcess ? "x64" : "x86";}/// <summary>/// Gets a value indicating if we are on a windows platform/// </summary>private static bool IsWindows{get{var res = !(Environment.OSVersion.Platform == PlatformID.Unix ||Environment.OSVersion.Platform == PlatformID.MacOSX);return res;}}private static void PrintDriversOgr(){
#if DEBUGif (_usable){var num = Ogr.GetDriverCount();for (var i = 0; i < num; i++){var driver = Ogr.GetDriver(i);Trace.WriteLine($"OGR {i}: {driver.GetName()}", "Debug");}}
#endif}private static void PrintDriversGdal(){
#if DEBUGif (_usable){var num = Gdal.GetDriverCount();for (var i = 0; i < num; i++){var driver = Gdal.GetDriver(i);Trace.WriteLine($"GDAL {i}: {driver.ShortName}-{driver.LongName}");}}
#endif}}
}
以上错误提示:无法在xxx\plugins\目录下找到 ogr_MSSQLSpatial.dll ,那么在以上代码的设置plugins环境时是不是初始化无法定位到plugins目录呢?
测试:将原始代码中设置环境变量强制修改成plugins的目录
原始代码部分:
string driverPath = Path.Combine(nativePath, "plugins");
Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", driverPath);
Gdal.SetConfigOption("GDAL_DRIVER_PATH", driverPath);
修改为:
Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", "./gdal/plugins");
OSGeo.OSR.Osr.SetPROJSearchPath("./gdal/plugins");
惊喜出现了,错误消失,程序正常运行。
总结:GADL在C# 中使用着实经常出现问题,大家的问题五花八门,需要自己去追踪一下。