2015-07-10 68 views
0

更新:添加了完整的代碼塊,其中發生錯誤'System.AccessViolationException'發生了

更新2:我發現了一個奇怪的異常。當tabName變量等於「上一年的服務線」時,代碼現在一直在不斷突破。今天早上,我爲了咧嘴笑,將標籤名稱改爲「test」,所以tabName變量等於「test」,而且它更常用,然後不是。我真的很茫然。

我已經研究一噸,找不到任何解決什麼是我的代碼發生。它隨機發生。有時不發生,那麼其它時間它發生在同一地點,但所有的這部分代碼(上線templateSheet = templateBook.Sheets [TABNAME]):

public void ExportToExcel(DataSet dataSet, string filePath, int i, int h, Excel.Application excelApp) 
    { 
      //create the excel definitions again. 
      //Excel.Application excelApp = new Excel.Application(); 
      //excelApp.Visible = true; 
      FileInfo excelFileInfo = new FileInfo(filePath); 
      Boolean fileOpenTest = IsFileOpen(excelFileInfo); 

      Excel.Workbook templateBook; 
      Excel.Worksheet templateSheet; 

      //check to see if the template is already open, if its not then open it, 
      //if it is then bind it to work with it 
      if (!fileOpenTest) 
      { templateBook = excelApp.Workbooks.Open(filePath); } 
      else 
      { templateBook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath); } 


      //this grabs the name of the tab to dump the data into from the "Query Dumps" Tab 
       string tabName = lstQueryDumpSheet.Items[i].ToString(); 

       templateSheet = templateBook.Sheets[tabName]; 
       excelApp.Calculation = Excel.XlCalculation.xlCalculationManual; 

       templateSheet = templateBook.Sheets[tabName];   

      // Copy DataTable 
      foreach (System.Data.DataTable dt in dataSet.Tables) 
      { 
       // Copy the DataTable to an object array 
       object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count]; 

       // Copy the values to the object array 
       for (int col = 0; col < dt.Columns.Count; col++) 
       { 
        for (int row = 0; row < dt.Rows.Count; row++) 
        { rawData[row, col] = dt.Rows[row].ItemArray[col]; } 
       } 

       // Calculate the final column letter 
       string finalColLetter = string.Empty; 
       string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
       int colCharsetLen = colCharset.Length; 

       if (dt.Columns.Count > colCharsetLen) 
       { finalColLetter = colCharset.Substring((dt.Columns.Count - 1)/colCharsetLen - 1, 1); } 

       finalColLetter += colCharset.Substring((dt.Columns.Count - 1) % colCharsetLen, 1); 

       //this grabs the cell address from the "Query Dump" sheet, splits it on the '=' and 
       //pulls out only the cell address (i.e., "address=a3" becomes "a3") 
       string dumpCellString = lstQueryDumpText.Items[i].ToString(); 
       string dumpCell = dumpCellString.Split('=').Last(); 

       //referts to the range in which we are dumping the DataSet. The upper right hand cell is 
       //defined by the 'dumpCell' varaible and the bottom right cell is defined by the 
       //final column letter and the count of rows. 
       string firstRef = ""; 
       string baseRow = ""; 

       if (char.IsLetter(dumpCell, 1)) 
       { 
        char[] createCellRef = dumpCell.ToCharArray(); 
        firstRef = createCellRef[0].ToString() + createCellRef[1].ToString(); 
        for (int z = 2; z < createCellRef.Count(); z++) 
        { 
         baseRow = baseRow + createCellRef[z].ToString(); 
        } 
       } 
       else 
       { 
        char[] createCellRef = dumpCell.ToCharArray(); 
        firstRef = createCellRef[0].ToString(); 
        for (int z = 1; z < createCellRef.Count(); z++) 
        { 
         baseRow = baseRow + createCellRef[z].ToString(); 
        } 
       } 

       int baseRowInt = Convert.ToInt32(baseRow); 
       int startingCol = ColumnLetterToColumnIndex(firstRef); 
       int endingCol = ColumnLetterToColumnIndex(finalColLetter); 

       int finalCol = startingCol + endingCol; 
       string endCol = ColumnIndexToColumnLetter(finalCol - 1); 
       int endRow = (baseRowInt + (dt.Rows.Count - 1)); 
       string cellCheck = endCol + endRow; 
       string excelRange; 

       if (dumpCell.ToUpper() == cellCheck.ToUpper()) 
       { 
        excelRange = string.Format(dumpCell + ":" + dumpCell); 
       } 
       else 
       { 
        excelRange = string.Format(dumpCell + ":{0}{1}", endCol, endRow); 
       } 

       //this dumps the cells into the range on Excel as defined above 
       templateSheet.get_Range(excelRange, Type.Missing).Value2 = rawData; 

       //checks to see if all the SQL queries have been run from the "Query Dump" tab, if not, continue 
       //the loop, if it is the last one, then save the workbook and move on. 

       if (i == lstSqlAddress.Items.Count - 1) 
       { 
        excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic; 

        /*Run through the value save sheet array then grab the address from the corresponding list 
        place in the address array. If the address reads "whole sheet" then save the whole page, 
        else set the addresses range and value save that.*/ 
        //for (int y = 0; y < lstSaveSheet.Items.Count; y++) 
        //{ 
        // MessageBox.Show("Save Sheet: " + lstSaveSheet.Items[y] + "\n" + "Save Address: " + lstSaveRange.Items[y]); 
        //} 

        //run the macro to hide the unused columns 
        excelApp.Run("ReportMakerExecute"); 

        //save excel file as hospital name and move onto the next 
        SaveTemplateAs(templateBook, h); 

        //close the open Excel App before looping back 
        //Marshal.ReleaseComObject(templateSheet); 
        //Marshal.ReleaseComObject(templateBook); 
        //templateSheet = null; 
        //templateBook = null; 
        //GC.Collect(); 
        //GC.WaitForPendingFinalizers(); 
       } 
       //Close excel Applications 
       //excelApp.Quit(); 
       //Marshal.ReleaseComObject(templateSheet); 
       //Marshal.FinalReleaseComObject(excelApp); 
       //excelApp = null; 
       //templateSheet = null; 
       // GC.Collect(); 
       //GC.WaitForPendingFinalizers(); 
      } 

    } 

在try/catch塊也沒用。這是錯誤:當您嘗試在本地代碼(不是.NET)來訪問未分配的內存

"An unhandled exception of type 'System.AccessViolationException' occurred inSQUiRE (Sql QUery REtriever) v1.exe. Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt." 
+0

對不起,但您需要詳細說明您的問題。將相關代碼和信息組織起來,嘗試查看內部異常,並告訴我們您嘗試實現的是什麼... – gustavodidomenico

+0

@gustavodidomenico我添加了發生錯誤時發生的整個塊。我在這一點上可能會考慮它的內存緩衝區問題。 – Darw1n34

回答

0

那麼長的故事,測試三天更長的時間,這是因爲試圖打開並使用SQL結果填入Excel文件的。緩衝區被填滿並引發異常......它只發生在每次運行的同一時刻,因爲excel文件的加載時間是其工作或失敗的決定性因素。

所以負載後,我只是增加了一個拖延做......而檢查,看看是否該文件是可訪問的或不和它停止的故障。 fileOpenTest取自here

  do 
      { 
       Task.Delay(2000); 
      } 
      while(!fileOpenTest); 
0

System.AccessViolationException通常會發生。然後.NET將它轉換爲託管世界作爲這個例外。

你的代碼本身沒有任何不安全的塊。因此,訪問衝突必須發生在Excel內部。

鑑於這一事實,有時會發生,有些時候不是,我要說的是,它可以通過一個並行的Excel使用(我認爲的Excel COM不是線程安全的)引起的。

我建議你把所有的代碼lock塊內,以防止Excel並行開始使用。事情是這樣的:

public void ExportToExcel(DataSet dataSet, string filePath, int i, int h, Excel.Application excelApp) 
{ 
    lock(this.GetType()) // You can change here to other instance to me used a mutex 
    { 
     // Your original code here 
    } 
} 
+0

謝謝,我試過這個,但第一次運行,它拋出了相同的異常。我會繼續深入挖掘並行的excel。 – Darw1n34