【发布时间】:2010-09-21 17:26:15
【问题描述】:
我编写了一个扩展 Installer 并覆盖 afterInstall 的安装类,但我得到一个空指针异常。我该如何调试我的课程?
【问题讨论】:
标签: c# .net installation
我编写了一个扩展 Installer 并覆盖 afterInstall 的安装类,但我得到一个空指针异常。我该如何调试我的课程?
【问题讨论】:
标签: c# .net installation
构建一个 VM,安装 Visual Studio,复制它(或创建一个差异化虚拟硬盘)并在 VM 下的调试器下运行安装程序。
这就是我会做的(但我不是专家)。
【讨论】:
在 Debug->Processes->Attach 或 CTRL + ALT + P 中将安装程序进程附加到 Visual Studio 设置断点,你应该可以去
【讨论】:
对于难以调试的代码部分来说很方便的是
System.Diagnostics.Debugger.Break()
将抛出任何已安装的调试器(VStudio、WinDbg、远程调试器等)捕获的断点。
使用它来调试非常棘手的区域,其中常规 F5+Go 或“附加到进程”难以或无法执行,一些示例包括:
【讨论】:
我使用 EventLog.WriteEntry("source", "message"),并在安装时检查 EventLog。也许不是最佳的,但对我有用:)
【讨论】:
我发现最好的方法是编写单元测试,然后从单元测试中新建和初始化安装程序类:
[TestClass] public class InstallerTest {
[TestMethod]
public void InstallTest() {
// substitute with your installer component here
DataWarehouseInstall installer = new DataWarehouseInstall();
string assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string installLogFilePath = Path.Combine(assemblyDirectory, "install.log");
installer.Context = new System.Configuration.Install.InstallContext(installLogFilePath, null);
// Refactor to set any parameters for your installer here
installer.Context.Parameters.Add("Server", ".");
//installer.Context.Parameters.Add("User", "");
//installer.Context.Parameters.Add("Password", "");
installer.Context.Parameters.Add("DatabaseName", "MyDatabaseInstallMsiTest");
//installer.Context.Parameters.Add("DatabasePath", "");
// Our test isn't injecting any save state so we give a default instance for the stateSaver
installer.Install(new Hashtable());
} }
至少它可以更好地利用 IDE 工具。这对于具有大量组件的大型安装程序特别有用。然后,您还可以创建有序的单元测试并按顺序运行它们,以在调试或自动构建期间模仿您的安装程序。
另一个技巧是通用 SOLID/GRASS 软件原则...在整洁/薄层中开发,保持您实际的“自定义操作”安装程序逻辑非常简单,而是调用您拥有的任何可重用 API 内容,这些内容特定于您的安装程序(s),就像我们习惯于 UI 开发一样。 (无论如何,安装程序只是另一个 UI。)如果您的目标是在产品的所有安装程序之间共享某种 UI 体验,这一点尤其重要。
【讨论】:
您还可以使用 installUtil.exe 实用程序来测试您的安装程序组件。
如果您使用 Installer 类创建了 c# 类程序集,请更改调试设置以启动外部程序“C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe” 并相应地输入你的命令行参数(例如 /Args=myargument "path to the assembly")
与上次设置断点一样,按 f5 即可调试代码。 --视差
【讨论】:
我使用以下类将简单的日志写入目标目录。在我看来,这比尝试使用 Visual Studio 调试器更容易。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace MyCompany.Deployment
{
/// <summary>
/// Enables a quick and easy method of debugging custom actions.
/// </summary>
class LogFile
{
const string FileName = "MyCompany.Deployment.log";
readonly string _filePath;
public LogFile(string primaryOutputPath)
{
var dir = Path.GetDirectoryName(primaryOutputPath);
_filePath = Path.Combine(dir, FileName);
}
public void Print(Exception ex)
{
File.AppendAllText(_filePath, "Error: " + ex.Message + Environment.NewLine +
"Stack Trace: " + Environment.NewLine + ex.StackTrace + Environment.NewLine);
}
public void Print(string format, params object[] args)
{
var text = String.Format(format, args) + Environment.NewLine;
File.AppendAllText(_filePath, text);
}
public void PrintLine() { Print(""); }
}
}
【讨论】:
出于记录目的(在 3.5 中)如何使用:
Context.LogMessage("My message");
【讨论】:
很惊讶没有人真正回答。将 MessageBox.Show("hello") 放入自定义操作的 Install() 成员中。在调试配置中构建部署。安装。当 MessageBox 出现时,进入 VS IDE、Debug、Attach Process 并查找标记为“Managed”的 msiexec 实例。将调试器附加到该 msiexec 实例。现在返回自定义操作的源并在调用 MessageBox.Show() 之后立即放置一个断点。关闭 MessageBox,您的断点将被命中,您正在 IDE 中进行调试!
【讨论】:
Show All Processes复选框被选中可能值得注意。此外,可以GetCurrentProcess 并用Id 肯定地识别正确的过程。 :)
System.Diagnostics.Debugger.Break() 时为什么要使用它?您必须添加 WindowsForms dll 才能使用 MessageBox。此外,对于 CustomInstallers,进程名称将为 InstallUtil。
在您的安装程序方法中添加 Debugger.Launch() 语句,该语句将启动“Visual Studio 即时调试器”,您可以在其中附加一个 Visual Studio 实例并调试您的安装程序类 (MSI)。这也应该适用于 Visual Studio 2010。但是您需要具有管理权限才能执行此操作。如果您没有管理权限,您可能会遇到问题。因此,以管理员身份登录以调试 MSI。例如:
public override void Install(System.Collections.IDictionary stateSaver)
{
Debugger.Launch();
base.Install(stateSaver);
}
在 Visual Studio 2005 中,即使是 Debugger.Break() 也可以正常工作,但不知何故这不适用于 Visual Studio 2010。
【讨论】:
在要调试的方法的开头写下如下代码
#if DEBUG
MessageBox.Show(Process.GetCurrentProcess().Id.ToString());
#endif
所以当你的方法被调用时,上面的代码将被命中,然后你可以使用上面的进程 ID 将调试器附加到进程(ctrl+alt+p)。您可能必须以提升的权限启动 VS。
【讨论】:
您可以通过将以下部分添加到 .csproj 或 .csproj.user 文件来自动调试安装程序项目:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<StartAction>Program</StartAction>
<StartProgram>$(MSBuildBinPath)\installutil.exe</StartProgram>
<StartArguments>$(AssemblyName).dll</StartArguments>
</PropertyGroup>
如果您希望其他开发人员从此更改中受益,请使用项目文件;如果您想自己使用,请使用 .user 文件。
【讨论】:
以上都不适合我。这实际上是有效的。请注意,您需要插入“两行”。
using System.Diagnostics;
MessageBox.Show("Test is about to begin");
Debugger.Launch();
【讨论】:
这实际上对我有用。
System.Diagnostics.Debugger.Launch();
然后右键单击安装程序项目并按“安装”
【讨论】: