在VSTO中尝试/捕获的替代方案

时间:2014-12-11 23:09:24

标签: c# excel try-catch

一位同事提醒我,他在网上找到了这个方便的VBA,它在没有密码的情况下解锁了Microsoft Excel中的工作表:

Sub PasswordBreaker()

'Breaks worksheet password protection.

Dim i As Integer, j As Integer, k As Integer
Dim l As Integer, m As Integer, n As Integer
Dim i1 As Integer, i2 As Integer, i3 As Integer
Dim i4 As Integer, i5 As Integer, i6 As Integer

On Error Resume Next

For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
  ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
  Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
  Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)

  If ActiveSheet.ProtectContents = False Then
    MsgBox "One usable password is " & Chr(i) & Chr(j) & _
    Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _
    Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
    Exit Sub
  End If

Next: Next: Next: Next: Next: Next
Next: Next: Next: Next: Next: Next
End Sub

它很有效,并且很快就能完成。

我们有一个Excel的VSTO扩展,我们想要添加此功能。上面的代码到C#的近文字(仍然是离散的循环,没有递归或任何东西)转换如下:

    public static string Unprotect()
    {
        var addIn = Globals.ThisAddIn;
        Excel.Worksheet sheet = addIn.Application.ActiveSheet;

        if (!sheet.ProtectContents)
            return "This sheet was not protected";

        int[] la = new int[] { 65, 66 };

        foreach (int i in la)
            foreach (int j in la)
                foreach (int k in la)
                    foreach (int l in la)
                        foreach (int m in la)
        foreach (int i1 in la)
            foreach (int i2 in la)
                foreach (int i3 in la)
                    foreach (int i4 in la)
                        foreach (int i5 in la)
                            foreach (int i6 in la)
                                for (int n = 32; n <= 126; n++)
        {
            string password = string.Format(
                "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}",
                (char)i, (char)j, (char)k, (char)l, (char)m, 
                (char)i1, (char)i2, (char)i3, (char)i4, (char)i5, 
                (char)i6, (char)n);

            try
            {
                sheet.Unprotect(password);
                if (!sheet.ProtectContents)
                    return password;
            }
            catch (Exception ex)
            {
            }
        }
        return "Fail.";
    }

这同样成功,但是在需要很长时间才能找到密码的情况下,VBA解决方案会破坏C#解决方案的性能。差异可以是&lt; 1秒与1 1/2分钟。

我知道try-catch通常是一项昂贵的操作,并且必须抓住每次失败的尝试都是拖延性能的。

我猜测Excel VBA on error resume next必须是一个相当轻量级的操作?

在这个实例中有没有人知道try-catch的替代方法,也许是一种Excel特定的方式来处理这个问题?在我看来,我正在思考Int32.TryParse或Dictionary.TryGetValue。

0 个答案:

没有答案