2010-03-10 25 views
2

我在2小時前創建了這個程序,當我將這個文件對準presaved .xls文件時,它運行得很順利。但是當我關閉它並開始新實例時,它開始生成空引用異常,爲什麼?PLZ解釋。行爲的變化和空引用異常的產生

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 




using System.IO; 

using System.Threading; 
using Microsoft.Office.Interop; 
using Excel = Microsoft.Office.Interop.Excel; 


namespace svchost 
{ 

    class MainClass 
    { 
     Excel.Application oExcelApp; 


     static void Main(string[] args) 
     { 
      MainClass mc = new MainClass(); 
      while (true) 
      { 
       if (mc.chec()) 
       { 
        Console.WriteLine("RUNNING"); 

        Thread.Sleep(4000); 
       } 
       else 
       { 
        Console.WriteLine("NOT RUNNING"); 

        Thread.Sleep(8000); 
       } 

      } 


     } 
     public bool chec() 
     { 



      try 
      { 
       oExcelApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); 
       Excel.Workbook xlwkbook = (Excel.Workbook)oExcelApp.ActiveWorkbook; 

       //****PROBLEM FROM HERE********* 

      Console.WriteLine(xlwkbook.Name + "\n"); 
      ke kw = new ke(ref oExcelApp,ref xlwkbook); 

      Console.WriteLine(xlwkbook.Author); 

      xlwkbook = null; 
     } 
     catch (Exception ec) 
     { 
      oExcelApp = null; 
      System.GC.Collect(); 
      Console.WriteLine(ec); 
      return false; 

     } 
     oExcelApp = null; 

     System.GC.Collect(); 
     return true; 
    } 
} 




class ke 

{ 
    public ke(ref Excel.Application a1, ref Excel.Workbook b1) 
    { 
     Excel.Worksheet ws = (Excel.Worksheet)a1.ActiveSheet; 
     Console.WriteLine(a1.ActiveWorkbook.Name + "\n" + ws.Name); 
     Excel.Range rn; 
     rn = ws.Cells.Find("657/07", Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, 
    Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, Type.Missing, Type.Missing); 
     Console.WriteLine(rn.Text); 

    } 

} 

} 
+1

請閱讀:http://stackoverflow.com/editing-help並請重新格式化您的代碼。 – spender

+0

異常發生在哪一行? –

+0

@spender:爲他修好了。 – Kredns

回答

5

哇,很多可怕的事情發生在那裏。

  1. 永遠不要寫行GC.Collect()除非你有一個非常好的理由。這不是其中之一。

  2. oExcelApp = null無所作爲。我猜這是從VB腳本/應用程序「翻譯」過來的,你必須編寫Set xxx = Nothing,然後發現GC是不確定的,你可以用GC.Collect()「修復」它。讓GC完成工作,如果你不知道自己在做什麼,就不要亂它。

  3. 趕上頂級Exception並吃它...不重新投擲,不包裹,不記錄,什麼都沒有。在這種情況下,也許應該是一個finally,與return truetry塊內,return falsefinally塊之後。

  4. ref參數在不需要參考語義因任何原因的方法。擺脫他們。

  5. 無意義的類和方法名。我們應該如何理解這裏發生了什麼?

  6. 從不檢查null結果,這無疑是爲什麼你會得到例外。我看到幾個例子。第一個是以rn = ws.Cells.Find開始的行之後 - 此方法可返回nullActiveWorkbook屬性也可以返回null,並將其傳遞給ke構造函數,該構造函數不驗證工作簿是否是有效的引用。最後,Marshal.GetActiveObject也可以返回null,並且您從不檢查以確保其成功。

  7. 創建類和使用它的構造做,可以在一個單一的方法來完成同樣的工作。我不明白爲什麼ke類甚至存在 - 它沒有方法或屬性!給這個方法一個合適的名字,刪除那個類並把它放在和其他工作相同的類中。

  8. 聲明變量,然後在下一行分配他們。我想這是更多的代碼風格問題,但再次讓我覺得這是從VB的某種自動翻譯。如果在聲明變量後立即分配變量,則將該聲明和賦值放在同一行上,即Range rn = ...

  9. Thread.Sleep的使用,大概是爲了防止某種競爭條件 - 而不是一個可靠的手段。

希望這些事情之一(可能#6)將帶領您解決方案...

+0

1 + 2> - 我不知道,但一次40'S的EXCEL.EXE運行taskmanager時,我離開了對象。所以我決定手動銷燬它。 3 + 4 + 5 + 7>。實際上程序非常龐大,大部分編碼仍然存在,同時我在初始階段出現錯誤,所以我決定問你們所有人。 6>實際上整個程序是用於追蹤特定數字「657/07」,這是關鍵。 8>我在這裏applozise,因爲這段代碼是爲了更好的可見性而編寫的,否則我不得不一直在移動滾動條。 9>其它會吞噬我整個處理器的優勢 – perilbrain

+0

@peril brain:如果使用Marshal.GetActiveObject,則不會發生這種情況。我的猜測是,你最初創建一個新的Excel實例,而不是調用'Quit()'方法或設置'Visible = true'來使應用可見,這就是爲什麼你在任務管理器中獲得這些孤立的進程。如果你將構造改爲'Marshal.GetActiveObject',你必須知道,不像'new Excel.Application'或'new ApplicationClass',它不會啓動一個新的進程,但**可以返回'null' 。修復代碼 - 閱讀C#Excel interop上的許多教程之一。 – Aaronaught

0
 public bool chec() 
      { 
       Excel.Application oExcelApp; 


       try 
       { 

        oExcelApp = (Excel. 

Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); ; 
       if (oExcelApp.ActiveWorkbook != null) 
       { 
        Excel.Workbook xlwkbook = (Excel.Workbook)oExcelApp.ActiveWorkbook; 


        ke k = new ke(ref oExcelApp, ref xlwkbook); 

       } 


      } 
      catch 
      { 
       if (reg > 100) { } else { reg++; goto End; }//public static int reg=0; 
       oExcelApp = null; 

       /*Process[] ppo = Process.GetProcessesByName("EXCEL"); 
       foreach(Process pppp in ppo) 
       { 
        pppp.Kill(); 
       }*/ 

       End: 
       return false; 

      } 

       finally{ oExcelApp = null; 
       System.GC.Collect();} 




      return true; 
     } 
    }