當模塊被修改時,您不可能知道。 VBIDE API甚至不告訴你是否模塊被修改,所以你必須自己弄清楚。
VBIDE API令人難以忍受 - 正如您已經注意到的那樣。
Rubberduck尚未處理特定於主機的組件(例如表,查詢等),但其解析器在自上一次解析後判斷模塊是否被修改方面做了很好的工作。
「自上次檢查後修改」實際上是您所需要知道的。你不能靠行雖然統計,因爲這個:
Option Explicit
Sub DoSomething
'todo: implement
End Sub
將與此相同:
Option Explicit
Sub DoSomething
DoSomethingElse 42
End Sub
而且很明顯,你會希望這種改變被拾起和跟蹤。比較每一行代碼中的每個字符都可以工作,但速度要快得多。
總體思路是獲取CodeModule
的內容,對其進行散列,然後與之前的內容散列進行比較 - 如果有任何修改,我們正在查看「髒」模塊。它是C#,我不知道是否有一個COM庫可以容易地從VBA中散列字符串,但最糟糕的情況是,您可以在.NET中編譯一個小型實用程序DLL,公開一個需要String
並返回的COM可見函數一個散列,不應該太複雜。
下面是Rubberduck.VBEditor.SafeComWrappers.VBA.CodeModule相關的代碼,如果它的任何幫助:
private string _previousContentHash;
public string ContentHash()
{
using (var hash = new SHA256Managed())
using (var stream = Content().ToStream())
{
return _previousContentHash = new string(Encoding.Unicode.GetChars(hash.ComputeHash(stream)));
}
}
public string Content()
{
return Target.CountOfLines == 0 ? string.Empty : GetLines(1, CountOfLines);
}
public string GetLines(Selection selection)
{
return GetLines(selection.StartLine, selection.LineCount);
}
public string GetLines(int startLine, int count)
{
return Target.get_Lines(startLine, count);
}
這裏Target
是Microsoft.Vbe.Interop.CodeModule
對象 - 如果你在VBA的土地是那麼這只是一個CodeModule
,從VBA擴展性庫;這樣的事情:
Public Function IsModified(ByVal target As CodeModule, ByVal previousHash As String) As Boolean
Dim content As String
If target.CountOfLines = 0 Then
content = vbNullString
Else
content = target.GetLines(1, target.CountOfLines)
End If
Dim hash As String
hash = MyHashingLibrary.MyHashingFunction(content)
IsModified = (hash <> previousHash)
End Function
所以是的,你的「激烈」的解決方案几乎是唯一可靠的方法去實現它。幾件事情要記住:
- 「保持所有模塊的列表」,將工作,但如果你只儲存模塊名稱和模塊改名,緩存是陳舊的,你需要一種方法來使它無效。
- 如果你存儲每個模塊對象的
ObjPtr
而不是他們的名字,我不確定它在VBA中是否可靠,但我可以告訴你,通過COM互操作,COM對象的哈希碼不會始終一致在調用之間 - 所以你會有一個陳舊的緩存和一種方法來使它失效,也是如此。儘管如此,可能不是100%VBA解決方案的問題。
我會去Dictionary
存儲模塊的對象指針作爲一個關鍵,他們的內容哈希作爲一個值。
這就是說作爲Rubberduck項目的管理員,我寧願看到你加入我們,幫助我們整合全功能的源代碼控制(即特定主機的功能)直接進入VBE =)
![Rubberduck's Source Control panel](https://i.stack.imgur.com/8OPde.png)
將模塊導出爲文本文件非常簡單,那麼您可以比較全文。我不會建議只檢查行數,因爲有人可以在一行中更改代碼,並且不會被檢測到。幾年前,我喜歡'WinDiff.exe',它會顯示兩個文件的差異(我發現它仍然可以下載)。我建立了一個具有所有對象,控件,屬性和值的'數據字典'數據庫,然後可以比較舊的和新的來顯示更改。此外,如果您使用SourceSafe(或現代版本),可以跟蹤更改。 –
無恥的插件,但[Rubberduck加載項](https://github.com/rubberduck-vba/Rubberduck)具有源代碼管理功能。 – Comintern
@Comintern當然,但它不處理任何Access特定的組件。 –