保护Excel工作簿中的代码?

我想生成一个Excel工作簿,其中将包含专有公式和其他知识产权。 我很可能会用C#在Visual Studio 2010中生成这个工作簿。

这些项目中的代码有多受保护? 在C#中reflection的同样的问题仍然适用于这些工作簿项目? 如果是这样,是否有专门为这些types的工作簿的混淆工具?

添加到这个问题 – 什么好'烯VBA? 如果我们要走VBA路线,有没有办法保护这些代码呢?

正如其他答案所build议的,Excel 2003(.xls)中的VBA安全性是有缺陷的; 密码只是一点烦恼,往往不是开发者自己。 恕我直言,你绝对比VSTO更好,即使Excel 2007+(.xlsx)中的VBA安全性好得多,更不用说在几个世纪以来没有看到改进的VBA IDE(尽pipe没有正确的VBE添加在… )。

一个解决scheme可能是将敏感代码写入您的VSTO项目调用的单独的库中; 而不是复杂的公式,你可以暴露出“黑匣子”的function(即公式的function的抽象)。 它是如何实现的,只有没有源代码的人才可以使用),而且没有dll的工作簿不能计算(将#NAME?遍地)。

例如,用户可以看到=Smurf(SomeTableColumnName, SomeRangeName, SomeRangeReference, SomeCellReference) ,而不是=some proprietary formula returning a Smurf 。 当然这是以性能为代价的,所以我只会为了保护真正重要的东西而做到这一点。

我认为一个用户从这样的一个库文件中提取专有的公式,值得和他们一起离开 – 在这个和Alt + F11之间,还有一个步骤。 专有代码与其他.net程序集一样是“受保护的”。

UPDATE

仍然没有使用任何第三方库,如果专有代码 不需要 Excel互操作性,一个可能更好的解决scheme可能是在VBA中创build函数 (即将Excel交互部分留在Excel中),只传递原始types(VBA Integer = > .net Int16 ; VBA Long => .net Int32 ,string等)到一个甚至不需要使用Excel互操作的COM可见库; 这将是COM互操作而不是Excel互操作性能,虽然仍然存在(它保持.net托pipe代码与非托pipeCOM“交谈”),但是性能降低会显着降低。

VBA代码的责任是读写工作表,而COM可见库的作用是实现计算由VBA代码传递的值; 当然用户可以很方便地访问VBA代码(Alt + F11),但是他们又不能访问实际的计算实现。 然后,VBA代码可以被密码保护,没有DLL的计算结果将是0#VALUE! ,这取决于如何实现VBA代码。

关键是在Excel中保留特定于Excel的内容,并让.net库在不引用Excel互操作程序集的情况下select它所在的位置,例如,VBA函数将获取单元格引用,获取其值(可能validation它)并将其传递给它到.net程序集,它将返回VBA将返回到Excel的另一个基本types。

另外一个好处是,如果您曾经将Excel工作簿“转换”成Web应用程序,那么具有专有计算的库代码可以被重用。

以供将来参考:这里有2个新的创新产品,以帮助解决您的确切问题:

1) https://HiveLink.io : – 使用HiveLink,你可以创build一个电子表格的“轻量级”版本,这个版本给你的用户,但是它不包含任何敏感的VBA或者计算公式。 您可以从轻量级电子表格中去除知识产权,并向用户发送邀请以下载此电子表格。 当您的用户input他们的input数据时,HiveLink会将数据传送到原始电子表格中以处理数据,然后将结果自动返回给用户。

这种方法的好处在于,使用.NETreflection或者汇编代码进行反向工程是不可能的,因为您完全从计算机中删除了代码。 这是最安全的select,如果你的模型适合input/输出的往返devise,那就太好了 – 如果你需要即时发生的客户端交互式代码,那就不是那么好。 如果您确实需要快速的客户端交互式代码,通常这不太敏感,您可以使用工作簿保护,甚至使用DoneEx Excel Compiler等编译基本代码,并使用Excel Compiler和HiveLink的组合进行保护。

2) http://FCell.io :这允许你直接在电子表格中build立.NET代码。 它甚至在电子表格中带有一个代码编辑器窗口,就像用.NET代码编辑器replace现有的VBA代码编辑器一样。 代码编辑器中的对象模型比普通编辑器稍逊一筹,但您也可以创build“任务窗格”并将其embedded到工作簿中进行分发,以便用户甚至不需要安装任何东西! 我不确定代码是如何安全地embedded到工作簿中的,但是如果对他们来说足够重要的话,我可以100%确定人们可以访问你的代码。

进一步的意见Re Mat的马克杯有帮助的回应:

回复:性能成本 – 实际上你可能会注意到在.NET中实现的东西会带来显着的性能提升,特别是如果你使用multithreading的话,那么Excel根本就不用UDF或者macros。 我已经看到在.NET库中重写我的一些客户的代码100倍的收益(用于繁重的处理计算)。 您也可能发现维护和改进.NET代码比VBA更容易。 我已经做了大量的VBA代码和function到.NET代码的转换,并且在正确完成时从来没有出现明显的性能问题。

回复:用户通过反映.NET库获得访问? 我完全不同意这个 使用reflection访问.NET代码是非常容易的,甚至比破解Excel弱密码更容易。 如果你真的想要保护敏感的计算,那么最好是使用像HiveLink这样的东西来完全消除逆向工程的可能性,或者使用模糊处理使其变得更加困难/非常烦人。 对于混淆,我使用CryptoObfuscator($)和Dotfuscator($$$)。 如果没有这个,我不会在.NET库中分享我的客户的敏感模型VBA代码。 我也有时使用CryptoLicensing来允许他们通过为每个用户创build许可来控制谁可以访问他们的DLLfunction。

回复:离开VBA代码负责写/读/从工作表 – 我也高度反对这一点。 我build议尽可能在VBA中留下尽可能less的代码,并对.NET进行高级调用,留下读写.NET插件。 在你的工作表中使用命名的ranged标识你的input/输出和数据位置,然后在你的.NET库中定义这些命名的范围作为常量。 在你的图书馆,你可以很容易地读取范围,并写入范围。 这样维护更简单,更容易。

当您想要从VBA调用外部function的Excel的任何扩展库时,您必须使您的库COM可见。 有几种方法可以做到这一点:我强烈build议您避免使用regsvr32注册您的库与Windows COM列表 – 避免不惜一切代价!

注册库的最好方法是使用ExcelDna加载它,它允许您在每次启动Excel时dynamic加载DLL,而无需在registry中永久定义每个具有COM接口的类(更新版本时为噩梦)。 您最终创build了一个XLL文件,可以将DLL内部打包 – 您可以通过在registry中键入密钥来告诉Excel在每次启动时加载XLL。 好处是,这并不要求您将整个COM接口存储在registry中,因此pipe理新版本非常容易。

因此,你的VBA代码可能是这样的:

 Sub Button_Click() Call ThisWorkbook.EnsureLibraryInitialized Call ThisWorkbook.MyLibrary.ReadRangesAndWriteResults(someInputParam) End Sub 

请注意,VBA将在运行时查找此方法ReadRangesAndWriteResults。 如果你在VBA中公开这个编译时间的方法,那么你必须在registry中注册它的COM接口签名 – 不惜一切代价避免!

ThisWorkbook模块:

 Public MyLibrary as Object public sub Workbook_Open() EnsureLibraryInitialized End Sub public Sub EnsureLibraryInitialized() Dim addin As COMAddIn If MyLibrary is Nothing Then For Each addin In Application.COMAddIns If InStr(addin.Description, "MyLibrary.COMHelper") Then If addin.object Is Nothing Then 'complain it can't connect to library, tell user to reinstall it Else Set MyLibrary = addin.object Exit For End If Next End if End Sub 

回复:互操作和.NET库 – 好点的马克杯,这可能是一个噩梦时使用正常的Microsoft.Office.Interop.Excel。 因为您正在从托pipe的.NET环境访问本地代码,所以您必须确保您的.NET COM包装对象得到正确清理,否则,即使closures了Excel,您也会得到Excel的挂起/僵尸进程,看起来它已经消失/closures(查看任务pipe理器,他们可能仍然在那里!)

我发现处理这个问题的最好方法是使用NetOffice ,它基本上是Excel互操作模型的一个副本,但是为了安全地pipe理所有这些问题而创build。 最好还要注意COM对象的安全处理,例如这里和这里 。

祝你好运!

如果使用密码保存工作簿以作为XLSB打开(请注意,这不是保护工作簿结构等),工作簿使用合理安全的encryption(Excel 2013中更强大)encryption。
但是用户必须提供一个密码来打开它,这是不适合一些使用场景的。

所有其他forms的Excel保护相对较弱。

在Excel中保护代码最好使用C ++ XLL来完成。
接下来最好的是一个VB6 DLL(但是现在已经是一个死的技术,并且不能在64位Excel中工作)
接下来最好的是混淆的.NET,但是您确实需要使用Addin Express或XL DNA提供的.NET XLL接口,以避免.NET Interop和VSTO的低劣性能。