使用来自C#/。NET的GDAL的“No Disk”错误

我正在使用GDAL的 Tamas Szekeres版本,包括使用C#和.net 4.0的桌面GIS应用程序中的C#绑定

我将以下文件夹结构包含在我的可执行文件的一个子目录中的整个GDAL发行版:

\Plugins\GDAL \Plugins\GDAL\gdal \Plugins\GDAL\gdal-data \Plugins\GDAL\proj 

我们使用的是EPSG:4326,而且由于GDAL C#API使用p / invoke到32位库(可以尝试64位,因为Tamas提供这些,所以没有得到它然而)。

当我运行我的应用程序时,我得到以下错误

在这里输入图像说明

当软件尝试访问不再连接的设备 (如可移动驱动器)时,通常会发生此错误。 由于popup一个系统对话框,所以不能“捕捉”这个exception。

在使用任何button解除对话框之后,软件继续按devise执行。

我第一次调用下面的方法时发生错误

 OSGeo.OSR.CoordinateTransformation.TransformPoint(double[] inout); 

奇怪的东西:

  • 错误发生在一个,只有一台计算机(到目前为止)
  • 我已经在32位和64位的其他几台电脑上运行这个软件没有问题
  • 在编译我正在使用的GDAL匀场库之后,这个错误不会在第一次运行时发生, 它只发生在随后的每次运行
  • 它会发生,无论发布,还是debugging构build
  • 无论debugging器是否连接,都会发生
  • 无论我打开还是closuresGdal.UseExceptions或Osr.UseExceptions();
  • 禁用可移动驱动器导致错误消失。 这不是我认为是真正的解决scheme,因为我不能要求客户这样做。

我已经尝试了以下内容:

  • 捕捉错误
  • 改变GDAL目录和环境设置
  • 改变电脑和操作系统:这工作
  • 使用SysInternals ProcMon跟踪哪些文件正在打开,但没有运气,它们都显示为存在的文件
  • 硬盘驱动器出现故障时,我重新构build了有问题的计算机,但无济于事。
  • 使用CCleaner “清理”registry
  • GDAL目录中的文件在执行时没有改变

假设

  • 错误发生在非托pipe代码中
  • 在GDAL初始化期间,某些path指的是不再连接的计算机上的一个驱动器
  • 我也在假设这只限于计算机configuration错误

组态

  • Windows 7专业版
  • 英特尔酷睿i7 920 @ 2,67GHz
  • 12.0 GB RAM
  • 64位操作系统
  • 驱动器C:带有操作系统的120GB SSD,开发(Visual Studio 10)等
  • 驱动器D:1 TB WD 10,000k,数据不被访问。

问题

我要么需要一个方向来捕捉错误,要么是一个工具或技术,让我找出是什么原因造成的。 我不想发布软件,有些系统可能会有这种行为。

我对这个图书馆没有经验,但也许有些新鲜的眼睛可能会给你一个脑波。

首先,写得很好! 显然这个问题真的让你难倒了…

关于在重建之后没有出现错误的提示尖叫出来:这个库在它的二进制目录中生成某种状态文件后运行? 如果是这样,它可能会将不正确的路径信息保存到该“配置”文件中,以加速其下一次启动的错误尝试。

也许扫描这个目录中的“新建”和“第一次运行”之间的变化?

至少你可能会发现一个文件,你可以清理关闭,以避免此警报…

HTH

也许你可以试试这个:

  • 运行diskmgmt.msc
  • 如果我假设磁盘2是可移动磁盘是真实的,请更改磁盘2的驱动器号(右键单击)
  • 运行你的应用程序
  • 如果这消除了错误,应用程序中的某些内容就是指旧的驱动器盘符
  • 它可能在p /调用的库中
  • 也许看到: http ://gcc.gnu.org/bugzilla/show_bug.cgi?id = 46501它谈论的gcc以某种方式编译驱动器字母成二进制

+1伟大的问题,但不可能“赶上”

其中一个可怕的解决方案,将在5年DailyWTF出现。 但现在它存储在这里http://www.pinvoke.net/default.aspx/user32.senddlgitemmessage

 using Microsoft.VisualBasic; //this reference is for the Constants.vbNo; public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr SendDlgItemMessage(IntPtr hDlg, int nIDDlgItem, uint Msg, UIntPtr wParam, IntPtr lParam); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr SetActiveWindow(IntPtr hWnd); // For Windows Mobile, replace user32.dll with coredll.dll [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter. [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern uint GetDlgItemText(IntPtr hDlg, int nIDDlgItem,[Out] StringBuilder lpString, int nMaxCount); public void ClickSaveBoxNoButton() { //In this example, we've opened a Notepad instance, entered some text, and clicked the 'X' to close Notepad. //Of course we received the 'Do you want to save...' message, and we left it sitting there. Now on to the code... // //Note: this example also uses API calls to FindWindow, GetDlgItemText, and SetActiveWindow. // You'll have to find those separately. //Find the dialog box (no need to find a "parent" first) //classname is #32770 (dialog box), dialog box title is Notepad IntPtr theDialogBoxHandle; // = null; string theDialogBoxClassName = "#32770"; string theDialogBoxTitle = "Notepad"; int theDialogItemId = Convert.ToInt32("0xFFFF", 16); StringBuilder theDialogTextHolder = new StringBuilder(1000); //hardcoding capacity - represents maximum text length string theDialogText = string.Empty; string textToLookFor = "Do you want to save changes to Untitled?"; bool isChangeMessage = false; IntPtr theNoButtonHandle; // = null; int theNoButtonItemId = (int)Constants.vbNo; //actual Item ID = 7 uint theClickMessage = Convert.ToUInt32("0x00F5", 16); //= BM_CLICK value uint wParam = 0; uint lParam = 0; //Get a dialog box described by the specified info theDialogBoxHandle = FindWindow(theDialogBoxClassName, theDialogBoxTitle); //a matching dialog box was found, so continue if (theDialogBoxHandle != IntPtr.Zero) { //then get the text GetDlgItemText(theDialogBoxHandle, theDialogItemId, theDialogTextHolder, theDialogTextHolder.Capacity); theDialogText = theDialogTextHolder.ToString(); } //Make sure it's the right dialog box, based on the text we got. isChangeMessage = Regex.IsMatch(theDialogText, textToLookFor); if ((isChangeMessage)) { //Set the dialog box as the active window SetActiveWindow(theDialogBoxHandle); //And, click the No button SendDlgItemMessage(theDialogBoxHandle, theNoButtonItemId, theClickMessage, (System.UIntPtr)wParam, (System.IntPtr)lParam); } } 

你可以添加自定义错误处理程序到gdal。 这可能有助于:

http://www.gdal.org/ogr/cpl__error_8h.html

http://trac.osgeo.org/gdal/ticket/2895

原来,没有办法肯定回答这个问题。 我最终通过弄清楚在系统上注册了一些不存在的硬件来“解决”了这个问题。 对我来说,这仍然是一个谜,为什么几年后,只有GDAL设法挑起这个错误。

我将把无法捕捉这个例外归结为p / invoke所涉及的特性以及系统上非常低的硬件错误。