如何在dll中包含源代码?

简短版本:我希望我的程序能够(只读)在运行时访问自己的源代码。 有没有办法在编译期间自动将源代码打包到dll中?

长版:

背景是当发生exception时,我想自动创建一个包含所发生事件细节的文件。 除其他外,此文件应包括导致问题的函数的源代码。 我想通过电子邮件将此文件发送给其他人,并且接收者很可能没有(或者不想安装)Visual Studio,因此任何使用符号服务器等的东西都是不可能的。 它需要是纯文本文件。

理想情况下,我会找到相关的源代码文件,只需复制相关的行。 你可以放心地假设,只要我有一个包含整个源代码的文件夹,我就能找到我想要的文件和行。

到目前为止我能想出的最好的想法 – 而且我没有详细研究它,因为它看起来很乱 – 无论如何都是修改MSBuild文件以在编译期间创建源的.zip,并且需要.dll和.zip驻留在同一个文件夹中。

我发现的大多数关于stackoverflow的类似问题似乎都在处理反编译 .dll文件,这不是我想要做的。 我有源代码,我想以方便的方式将它与.dll一起发送。

更新:非常长的版本

似乎有些人严重质疑我为什么要这样做,所以这里的答案是:我的软件的主要目的是测试其他一些软件。 其他软件有GUI。 举个简单的例子,让我们说其他软件是标准的Windows计算器,那么我的测试用例可能看起来像这样:

calculator.Open(); calculator.EnterValue(13); calculator.PressButtonPlus(); calculator.EnterValue(38); calculator.PressButtonEnter(); int value = calculator.GetDisplayedValue(); Assert.That(value == 51); calculator.Close(); 

这些测试是以人类可读的方式有意编写的。

出现问题时我想要做的是给计算器的开发者一个关于如何重现问题的详细描述, 以一种他可以在没有我的软件的情况下手工复制的方式 。 (在这个例子中,他会打开计算器,输入13,按加号,依此类推。)

也许另一种选择是将每个函数calculator.Something()写出一条信息行到日志中,但这样做a)需要做更多的工作,b)只包括测试运行到它中止的点,并且c)承担一种风险,即在一个函数中忘记写入该行,从而对所做的事情给出不正确的表示。 但我对其他解决方案持开放态度,而不是复制源代码。

看一下这个问题: C#中是否存在__LINE__ __FILE__等价物?

C ++提供了在编译期间用代表信息替换的宏( __LINE__ __FILE____FILE__等)。 这意味着如果你写这样的东西:

 throw new CException(__FILE__); 

它会编译成这样的东西:

 throw new CException("test.cpp"); 

导致硬编码值。 C#编译器不提供这些宏,您不得不使用reflection来获取有关抛出exception的位置的信息。 您可以这样做的方式在上面链接的问题中描述。

如果您无法提供.pdb符号,则Exception.ToString() (或StackTrace.ToString() )的默认行为将不会返回行号,而是返回失败操作的MSIL偏移量。 据我所知,您可以使用ReSharper的堆栈跟踪资源管理器导航到代表代码(不是100%确定,但在stackoverflow上也有一个问题提到了这个事实)。

您可以将源文件的副本包含为资源。

  • 在项目文件夹中,创建一个名为Resources的子文件夹。 在那里复制源文件。
  • 在项目中创建资源文件,然后包含您在其中创建的源副本。
  • 设置预构建事件以将实际源文件复制到Resources文件夹,因此您始终拥有更新的副本。 在我创建的示例中,这很有效:

     copy $(ProjectDir)*.cs $(ProjectDir)Resources 
  • 在你的代码中,现在你可以得到这样的文件内容(我想资源文件的名称是Resource1.resx

     // Get the source of the Program.cs file. string contents = Resource1.Program; 

该项目最终结果如下:

项目树

是的,我还建议在MSBuild中以.zip或其他方式打包源代码,并将.zip打包到您的应用程序/ dll中。 在运行时,当发生exception时,您将获得Aschratt描述的文件和方法名称,从.zip中提取文件并在其中查找方法。