【问题标题】:savefiledialog "sometimes" throws an System.AccessViolationExceptionsavefiledialog“有时”抛出 System.AccessViolationException
【发布时间】:2017-04-04 13:46:16
【问题描述】:

我正在使用 Win7 和 Visual Studio 2013

我的应用程序是一个带有 GeckoFx 的网络浏览器组件。在下载调用中,我触发打开 SaveFileDialog。在某些情况下(不是每次调用),当我在第 822 行调用 SaveFileDialog 时出现以下错误(另请参见下面的代码):

System.AccessViolationException wurde nicht behandelt.
  HResult=-2147467261
  Message=Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
  Source=System.Windows.Forms
  StackTrace:
       bei System.Windows.Forms.UnsafeNativeMethods.GetSaveFileName(OPENFILENAME_I ofn)
       bei System.Windows.Forms.SaveFileDialog.RunFileDialog(OPENFILENAME_I ofn)
       bei System.Windows.Forms.FileDialog.RunDialogOld(IntPtr hWndOwner)
       bei System.Windows.Forms.FileDialog.RunDialog(IntPtr hWndOwner)
       bei System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner)
       bei System.Windows.Forms.CommonDialog.ShowDialog()
       bei MYAPPLICATION.modMain.LauncherDialog_Download(Object sender, LauncherDialogEvent e) in X:\COMPANY\products\APPLICATIONWITHGecko45\MYAPPLICATION\modMain.vb:Zeile 822.
       bei Gecko.LauncherDialog.Show(nsIHelperAppLauncher aLauncher, nsISupports aWindowContext, UInt32 aReason) in D:\temp\9f0c5cd\Geckofx-Winforms\Dialogs\GeckoHelperAppLauncherDialog.cs:Zeile 91.
       bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       bei System.Windows.Forms.Application.Run(ApplicationContext context)
       bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       bei MYAPPLICATION.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
  InnerException: 

我已经搜索过这个问题,并按照许多解决方案的建议处理了 saveFileDialog1.AutoUpgradeEnabled = False,但它没有帮助。

以下是出现错误的行。 注意:在某些情况下,我不得不调用 SaveFileDialog 两次。我不知道为什么会发生这种情况。我刚刚问了另一个问题,为什么会发生这种情况(见这里SaveFileDialog closes automatically directly after calling showDialog()

Public Sub LauncherDialog_Download(ByVal sender As Object, ByVal e As Gecko.LauncherDialogEvent)

    Try
        Dim P As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & Path.DirectorySeparatorChar & "tmp" 'globalParameters._downloadDirectory '
        If Not System.IO.Directory.Exists(P) Then System.IO.Directory.CreateDirectory(P)

        Dim objTarget As nsILocalFile = Xpcom.CreateInstance(Of nsILocalFile)("@mozilla.org/file/local;1")

        Using tmp As New nsAString(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + vbTab & "temp.tmp")
            objTarget.InitWithPath(tmp)
        End Using

        'Save file dialog
        Dim saveFileDialog1 As New SaveFileDialog()

        saveFileDialog1.Filter = "CSV file (*.csv)|*.csv|All files (*.*)|*.*"
        saveFileDialog1.FilterIndex = 2
        saveFileDialog1.RestoreDirectory = True
        saveFileDialog1.FileName = e.Filename
        saveFileDialog1.AutoUpgradeEnabled = False
        saveFileDialog1.CheckPathExists = False
        saveFileDialog1.InitialDirectory = globalParameters.getDownloadDirectory() 'globalParameters._downloadDirectory

        If globalParameters._doNotShowDownloadPrompt Then
            ' this code Part does not happen in my cases and we can ignore it
        Else
            Dim dialogResultValue As DialogResult
            Try
                dialogResultValue = saveFileDialog1.ShowDialog()
            Catch ex As Exception
                logging.logInformation("Problems during loading of dialog: " & ex.ToString())
            End Try
            ' SpecialCase, if CSV File or Dicom just reopen dialog
            ' crazy but helps to display dialog
            logging.logInformation("Download URL: " & e.Url)
            If (e.Url.Contains("format=CSV") Or e.Url.Contains("DocGenericZIP") Or e.Url.Contains("type=application/dicom")) And dialogResultValue = DialogResult.Cancel Then
                Try
                    saveFileDialog1.Dispose() ' dispose old saveFileDialog

                    saveFileDialog1 = New SaveFileDialog()
                    saveFileDialog1.Filter = "CSV file (*.csv)|*.csv|All files (*.*)|*.*"
                    saveFileDialog1.FilterIndex = 2
                    saveFileDialog1.RestoreDirectory = True
                    saveFileDialog1.FileName = e.Filename
                    saveFileDialog1.AutoUpgradeEnabled = False
                    saveFileDialog1.InitialDirectory = globalParameters.getDownloadDirectory()
                    saveFileDialog1.CheckPathExists = False
                    dialogResultValue = saveFileDialog1.ShowDialog() 'this is the line 822 mentioned in the error above

                Catch ex As Exception
                    logging.logInformation("Errors during loading of fole Dialog: " & ex.ToString())
                End Try
            End If

            ' if upper saveFileDialog runs without errors, following lines works like a charm
            If dialogResultValue = DialogResult.OK Then
                Try
                    ' these lines put the download Information into another thread, so that the download 
                    ' can run and the user can use the browser simultaneously, 
                    ' otherwise the interaction in main-Form is blocked
                    Dim par As New Parameters
                    par.sender = sender
                    par.e = e
                    par.mime = e.Mime
                    par.url = e.Url
                    par.fileName = saveFileDialog1.FileName
                    par.dialogResultValue = dialogResultValue
                    par.myStream = saveFileDialog1.OpenFile()
                    ThreadJob(par)
                Catch ex As Exception
                    logging.logInformation("Error during loading of File" & e.ToString)
                End Try
            End If
        End If

    Catch ex As Exception
        logging.logInformation("Error during loading file. " & ex.ToString, "main", True)
    Finally
        'nothing to do here
    End Try
End Sub

【问题讨论】:

    标签: vb.net access-violation savefiledialog geckofx


    【解决方案1】:

    我查看了您的两个问题,虽然我没有使用 GeckoFx 的经验,但我会从在本地创建文件的方式开始。你得到一个 AccessViolation -2147467261 这通常意味着损坏的内存(或至少锁定的内存)。

    这可以解释您在其他问题中描述的行为。如果globalParameters.getDownloadDirectory() 中指定的目录本身无效,或者它被导致您的根本问题的任何原因损坏,则对话框可能会关闭(这只是推测,因为它没有解释为什么没有抛出错误)。

    为了调试它,我会在您每次创建目录和/或文件时进行记录。我还会在整个执行过程中定期检查您是否有权访问您尝试保存到的目录和文件。我这样做的原因是因为AccessViolation 发生在非托管函数GetSaveFileName(OPENFILENAME_I ofn) 中。这是用于初始化对话框的函数,我相信 InitialDirectory 是在其中设置的。您应该能够看到 InitialDirectory 和默认文件名。有了这些数据,当它出现问题时,您有望看到一种模式。

    RunFileDialog

    GetSaveFileName

    OPENFILENAME

    很难更具体,因为您没有描述globalParameters.getDownloadDirectory() 的填充方式或它是否发生变化。至此,一个线程提到.RestoreDirectory 可能是问题的原因,所以不妨尝试禁用它。您还说错误是在第 822 行引发的,但不包括行号,所以我不知道究竟是哪一行出现了问题。

    作为旁注,我不确定您使用 objTarget As nsILocalFilefor 是什么,而且您似乎没有在代码中进一步使用它。这可能是你的记忆被破坏的地方,或者只是我对 GeckoFx 的无知。

    如果这些都不起作用,您可能需要弄清楚从 System.Windows.Forms.UnsafeNativeMethods.GetSaveFileName(OPENFILENAME_I ofn) 内部获取非托管代码 StackTrace。

    General AccessViolation TroubleShooting

    -2147467261 Error

    -2147467261 Error

    祝你好运!

    【讨论】:

    • 感谢您的回复,稍后我会检查您的建议。目前,异常在dialogResultValue = saveFileDialog1.ShowDialog() ' this is the line 822 mentioned in the error above 行中抛出(见上文)。我可以在代码视图中添加行号吗?
    • 很遗憾,我认为您不能添加行号。
    • 感谢您的建议。不知何故,我可以弄清楚(我的问题和你的答案)SaveFileDialog.ShowDialog(Me) 需要引用表单Me。只有这样 saveFileDialog 才能正确加载而不会出现错误,甚至在没有任何其他用户操作的情况下完成其调用。不幸的是,我把下载部分放到了一个未被Inherits System.Windows.Forms.Form 继承的vb 类中,因此它没有对表单的引用(这显然是必需的)。我改变了我的代码,所以我可以引用表单,它就像一个魅力。
    • AND globalParameters.getDownloadDirectory() 获取标准临时目录或配置文件定义的目录。如果目录不存在,将在此方法中创建。因此,此时我可以排除访问问题,否则它应该已经在getDownloadDirectory() 中抛出了这样的错误。
    • 很高兴听到它的成功。感谢您发布您的解决方案。这绝对是有道理的,特别是因为在内部 ShowDialog() 具有查找父句柄的逻辑,如果没有指定,就会发生奇怪的事情。 Owner Window Precedence。您还可以在调用堆栈中看到这一点。好收获!
    猜你喜欢
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    相关资源
    最近更新 更多