savefiledialog “sometimes” throws an System.Access

2019-09-07 18:26发布

问题:

I'm using Win7 with Visual Studio 2013

My Application is a webbrowser-component with GeckoFx. At the download-call I trigger to open the SaveFileDialog. On some cases (not on every call) I got the following error, when I call SaveFileDialog in line 822 (see also code below):

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: 

I already searched for this problem and took care of saveFileDialog1.AutoUpgradeEnabled = False as many solutions suggests, but it didn't help.

Here are the lines in which the error appears. Note: I had to call the SaveFileDialog in some cases twice.. I don't know why this happens. I just asked another question for why this happens (see here 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

回答1:

I looked at both your questions, and although I have no experience with GeckoFx, I would start with way the file is being created locally. Your getting an AccessViolation -2147467261 which usually means corrupt memory(or at least locked memory).

This may explain the behavior you described in your other question. If the Directory specified in globalParameters.getDownloadDirectory() is itself invalid, or it became corrupted by whatever is causing your root issue, the Dialog may close(this is just speculation, as it doesn't explain why no error is thrown).

To debug this, I would log every time you create a directory and/or file. I would also check periodically throughout execution that you have access to the Directory and File you are trying to save to. The reason I would do this is because the AccessViolation is happening in the unmanaged function GetSaveFileName(OPENFILENAME_I ofn). This is the function used to initialize the dialog and where I believe the InitialDirectory is set. You should be able to see the InitialDirectory and default file name. With this data, when it bugs out, you will hopefully see an pattern.

RunFileDialog

GetSaveFileName

OPENFILENAME

It is hard to be more specific as you didn't describe how globalParameters.getDownloadDirectory() is being populated or if it changes. To this point, one thread mentioned that .RestoreDirectory may be the cause of the issue, so maybe try disabling it. You also said that the error is thrown on line 822 but did not include line numbers so I don't know which exact line is bugging out.

On as side note, I'm not sure what your using objTarget As nsILocalFilefor and it doesn't seem like you use it further in your code. This may be where your memory is being corrupted or it is just my ignorance of GeckoFx.

If none of this works, you may need to figure out to get the unmanaged code StackTrace from inside of System.Windows.Forms.UnsafeNativeMethods.GetSaveFileName(OPENFILENAME_I ofn).

General AccessViolation TroubleShooting

-2147467261 Error

-2147467261 Error

Good Luck!