&引用;“无磁盘”;从C#/.NET使用GDAL时出错
我正在使用的构建包括使用C#和.NET4.0的桌面GIS应用程序中的C#绑定 我使用以下文件夹结构将整个GDAL发行版包含在可执行文件的子目录中:&引用;“无磁盘”;从C#/.NET使用GDAL时出错,c#,.net,windows,gis,gdal,C#,.net,Windows,Gis,Gdal,我正在使用的构建包括使用C#和.NET4.0的桌面GIS应用程序中的C#绑定 我使用以下文件夹结构将整个GDAL发行版包含在可执行文件的子目录中: \Plugins\GDAL \Plugins\GDAL\gdal \Plugins\GDAL\gdal-data \Plugins\GDAL\proj 我们使用的是EPSG:4326,该软件是使用32位目标构建的,因为GDAL C#API用于32位库(可以尝试使用64位,因为Tamas提供了这些,还没有开始使用它) 当我运行我的应用程序时,我得到以
\Plugins\GDAL
\Plugins\GDAL\gdal
\Plugins\GDAL\gdal-data
\Plugins\GDAL\proj
我们使用的是EPSG:4326,该软件是使用32位目标构建的,因为GDAL C#API用于32位库(可以尝试使用64位,因为Tamas提供了这些,还没有开始使用它)
当我运行我的应用程序时,我得到以下错误
当不再连接软件(如可移动驱动器)时,通常会发生此错误。无法“捕获”此异常,因为它会弹出一个系统对话框
使用任何按钮取消对话框后,软件将继续按设计执行
错误发生在我第一次调用以下方法时
OSGeo.OSR.CoordinateTransformation.TransformPoint(double[] inout);
奇怪的是:
- 错误发生在一台计算机上,并且只有一台计算机(到目前为止)
- 我已经在其他几台32位和64位计算机上运行过这个软件,没有任何问题
- 编译我正在使用的GDAL shim库后,在第一次运行时不会出现此错误,它只会在每次后续运行时出现
- 无论发布版本或调试版本如何,都会发生这种情况
- 无论是否附加了调试器,都会发生这种情况
- 无论我是打开还是关闭Gdal.UseExceptions还是Osr.UseExceptions(),它都会发生李>
>强>禁用可移动驱动器导致错误消失。< /强>这不是我认为真正的解决方案,因为我不能要求客户这样做。
- 捕捉错误
- 更改GDAL目录和环境设置
- 改变计算机和操作系统:这是有效的
- 使用SysInternals ProcMon跟踪正在打开的文件,它们看起来都是存在的文件
- 当硬盘出现故障时,我重新构建了这台有问题的计算机,但毫无效果
- 使用“清理”注册表
- GDAL目录中的文件在执行时保持不变
- 非托管代码中发生错误
- 在GDAL初始化期间,某些路径指的是计算机上不再连接的驱动器
- 我还假设这仅限于计算机配置错误
- Windows 7 Pro
- 英特尔酷睿i7 920@2,67GHz
- 12.0 GB内存
- 64位操作系统
- 驱动器C:120 GB SSD,带操作系统、开发(Visual Studio 10)等
- 驱动器D:1 TB WD 10000K,带数据,未访问数据李>
我要么需要一个方向来捕捉错误,要么需要一个工具或技术来让我找出导致错误的原因。我不想在发布软件时,考虑到某些系统可能会有这种行为。我没有使用此库的经验,但也许一些新鲜的眼睛会给你一个灵感 首先,写得好的问题!显然这个问题真的让你难倒了 您关于在重建后未发生错误的注释突然出现:此库在运行后是否在其二进制目录中生成某种状态文件? 如果是这样的话,它可能正在将不正确的路径信息保存到该“配置”文件中,从而错误地试图加速其下一次启动 也许可以扫描此目录以查找“新生成”和“首次运行”之间的更改 至少你可能会找到一个文件,你可以在关机时清理,以避免此警报
HTH也许你可以试试这个:
- 运行diskmgmt.msc
- 如果我假设磁盘2是可移动磁盘,请更改磁盘2的驱动器号(右键单击)
- 运行应用程序
- 如果这消除了错误,则应用程序中的某些内容引用了旧的驱动器号
- 它可能在p/libs中
- 也许可以看到:它讨论了gcc以某种方式将驱动器号编译成二进制
- +1一个很好的问题,但是不可能“抓住”
这是一个可怕的解决方案,将在5年内出现。但现在它被储存在这里
您可以将自定义错误处理程序添加到gdal。这可能有助于:
事实证明,没有办法明确回答这个问题。 我最终“解决”了这个问题,因为我发现系统上有一些注册的硬件不存在。几年后,为什么只有格达尔设法挑起了这个bug,这对我来说仍然是个谜
我将无法捕获此异常归因于p/invoke涉及的特性以及在系统上抛出的非常低级别的硬件错误。如果您愿意,您可以向上投票,以补偿我的赏金。我将检查目录中是否有启动时写入的某种文件。考虑到这一点,可能会有一些写入注册表的内容更难拦截。有人能推荐一个拦截注册表写入的工具吗?我猜SysInternals有一个。SysInternals绝对会处理监视器更新1:根据下面的第一个答案,我查看了GDAL目录中的文件数,并且文件数是稳定的。更新2:我采纳了自己的建议,使用设备管理器禁用了系统上的所有可移动设备。这“解决”了问题!这不是一个真正的解决办法,所以我将把这个问题留待讨论。如何跟踪哪个软件正在访问哪个可移动设备?可能是方法调用导致了异常,因此Visual Studio尝试加载库的原始源文件,这些源文件可能是从PC上指向空驱动器的驱动器编译而来的?不过,您应该可以使用ProcMon看到这一点。嘿!在过去的8个小时里你需要帮助吗?让
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);
}
}