2014-06-21 47 views
0

我想更多地瞭解Runtime.InteropServices。要做到這一點,我決定爲Excel中的一個基本的遊戲,從一個C#DLL運行。以下是遊戲的頂級C#代碼:COM互操作:C#DLL導致Excel崩潰( 「預期:要」)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Runtime.InteropServices; 

namespace ExcelEscapeGame 
{ 

    [Guid("F4810BC6-C65E-4D1B-855A-D645C7F66893")] 
    [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    public interface IEscapeGame 
    { 
     [DispId(1)] 
     void NewGame([param: MarshalAs(UnmanagedType.I1)] byte EnemyMoveSpeed, 
      [param: MarshalAs(UnmanagedType.I1)] byte PlayerMoveSpeed, 
      [param: MarshalAs(UnmanagedType.I1)] byte EnemyCount, 
      [param: MarshalAs(UnmanagedType.I4)] int OuterWidth, 
      [param: MarshalAs(UnmanagedType.I4)] int OuterLength, 
      [param: MarshalAs(UnmanagedType.I4)] int BorderWidth); 

     [DispId(2)] 
     [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] 
     int[,] GameMap(); 
    } 

    [Guid("B937DE85-776F-4822-A3B7-A936F2043537")] 
    [ComVisible(true), ClassInterface(ClassInterfaceType.None)] 
    public class EscapeGame : IEscapeGame 
    { 
     private GameFrame GF; 
     private EnemyFlock TheHorde; 
     private Player player; 
     private int[,] BaseMap; 
     private bool Initialized = false; 

     public void NewGame(byte EnemyMoveSpeed, byte PlayerMoveSpeed, byte EnemyCount, 
      int OuterWidth, int OuterLength, int BorderWidth) 
     { 
      GF = new GameFrame(new Point(0, 0), new Point(BorderWidth, BorderWidth), OuterLength, OuterWidth); 
      TheHorde = new EnemyFlock(EnemyCount, EnemyMoveSpeed); 
      TheHorde.RandomlyPositionAtEdge(GF); 
      player = new Player(PlayerMoveSpeed, GF.CentrePoint()); 
      BaseMap = GF.FrameMap(); 
      Initialized = true; 
     } 

     public EscapeGame() { } 

     public EscapeGame(byte EnemyMoveSpeed, byte PlayerMoveSpeed, byte EnemyCount, 
      int OuterWidth, int OuterLength, int BorderWidth) 
     { 
      this.NewGame(EnemyMoveSpeed, PlayerMoveSpeed, EnemyCount, 
      OuterWidth, OuterLength, BorderWidth); 
     } 

     public int[,] GameMap() 
     { 
      TestInitialized(); 
      int[,] map = CopyMap(); 
      Point[] EnemyPositions = TheHorde.Positions(); 
      foreach (Point p in EnemyPositions) 
      { 
       map[p.x, p.y] = (int)ColourEnum.ENEMY; 
      } 
      map[player.Position.x, player.Position.y] = (int)ColourEnum.PLAYER; 
      return map; 
     } 

     private int[,] CopyMap() 
     { 
      TestInitialized(); 
      int[,] OutMap = new int[BaseMap.GetUpperBound(0) + 1, BaseMap.GetUpperBound(1) + 1]; 
      for (int i = 0; i <= BaseMap.GetUpperBound(0); i++) 
      { 
       for (int j = 0; j <= BaseMap.GetUpperBound(1); j++) 
       { 
        OutMap[i, j] = BaseMap[i, j]; 
       } 
      } 

      return OutMap; 
     } 

     private void TestInitialized() 
     { 
      if (!Initialized) throw new NullReferenceException("The class was not initialized"); 
     } 

    } 
} 

我想從Excel中調用它。當我最初測試時,一切似乎都正常。現在,我已經添加了更多的類的DLL(包括上述EscapeGame類),東西似乎已經打破了,我不明白爲什麼。第一以下兩個VBA潛艇(Test)的使用很好地工作,現在只需導致Excel立即崩潰(沒有錯誤信息),第二(Go)只是給出「預期:以」作爲一個錯誤消息,並且不會開始運行(輔助功能就在那裏情況下,他們有相關的):

Sub Test() 

Dim point As New ExcelGames.point 

point.MakePoint 10, 10 
Set p.Position = point 

p.MoveSpeed = 2 

Dim arr As Variant, pRange As Excel.Range 

arr = p.Paths 

Set pRange = Sheet1.Range("f10") 

Application.ScreenUpdating = False 
For i = 0 To UBound(arr, 1) 
    pRange.Offset(arr(i, 0), arr(i, 1)).Interior.ColorIndex = 5 
Next i 
Application.ScreenUpdating = True 


End Sub 


Sub Go() 

Dim TheGame As New EscapeGame, p1 As New ExcelGames.point, offsetp As New ExcelGames.point 

p1.MakePoint 0, 0 
offsetp.MakePoint 2, 2 

TheGame.NewGame 2, 2, 10, 20, 20, 2 

Dim arr As Variant 

arr = TheGame.GameMap() 


Dim i As Long, j As Long 

Application.ScreenUpdating = False 
For i = 0 To UBound(arr, 1) 
    For j = 0 To UBound(arr, 2) 
     Sheet1.Cells(i + 1, j + 1).Value = arr(i, j) 
    Next j 
Next i 
Application.ScreenUpdating = True 

Dim gameRange As Excel.Range 

Set gameRange = Sheet1.Range(Cells(1, 1), Cells(UBound(arr, 1) + 1, UBound(arr, 2) + 1)) 

FormatRange gameRange 
FormatConditionRange gameRange, "=" & ExcelGames.ColourEnum_INNERSQUARE, 14395790 
FormatConditionRange gameRange, "=" & ExcelGames.ColourEnum_OUTERSQUARE, 15652797 
FormatConditionRange gameRange, "=" & ExcelGames.ColourEnum_PLAYER, 5296274 
FormatConditionRange gameRange, "=" & ExcelGames.ColourEnum_ENEMY, 8696052 

End Sub 

Private Sub FormatRange(ByRef xlrange As Excel.Range) 

With xlrange 
    .Columns.ColumnWidth = _ 
    .Columns("A").ColumnWidth/.Columns("A").Width * _ 
    .Rows(1).Height 
End With 

End Sub 

Private Sub FormatConditionRange(ByRef xlrange As Excel.Range, ByVal Formula As String, _ 
    ByVal Colour As Long) 

Dim FC As FormatCondition 

With xlrange 
    Set FC = .FormatConditions.Add(xlCellValue, Operator:=xlEqual, Formula1:=Formula) 
    With FC 
     .Interior.Color = Colour 
     .Font.Color = Colour 
     .StopIfTrue = False 
    End With 
End With 

End Sub 

他們的第一線執行之前無論是潛艇的失敗 - 通過在VBIDE步執行代碼,不利於亮點錯誤的原因。完全沒有錯誤 - 當我使用類從一個C#控制檯應用程序的一切DLL效果很好。 「預期:要」的含義是什麼,任何人都可以提出我做錯了什麼?

回答

0

的解決方案是命名第二子「走出去」造成的Excel認爲它期待GoTo語句。這似乎影響了該模塊中的所有代碼。一旦我將名稱更改爲「GoWork」,該子程序就會正確執行。