调试C#自定义安装程序类
我已经编写了一个安装类来扩展Installer并覆盖afterInstall,但是我得到了一个空指针异常。如何调试我的类?构建虚拟机,安装Visual studio,复制它(或创建差异虚拟硬盘),并在虚拟机下的调试器下运行安装程序调试C#自定义安装程序类,c#,.net,installation,C#,.net,Installation,我已经编写了一个安装类来扩展Installer并覆盖afterInstall,但是我得到了一个空指针异常。如何调试我的类?构建虚拟机,安装Visual studio,复制它(或创建差异虚拟硬盘),并在虚拟机下的调试器下运行安装程序 这就是我要做的(但我不是专家)。在调试->进程->附加或CTRL+ALT+p中将安装程序进程附加到Visual studio 设置断点,您应该能够转到对于难以调试的代码部分来说,方便的方法是 System.Diagnostics.Debugger.Break() 将
这就是我要做的(但我不是专家)。在调试->进程->附加或CTRL+ALT+p中将安装程序进程附加到Visual studio
设置断点,您应该能够转到对于难以调试的代码部分来说,方便的方法是
System.Diagnostics.Debugger.Break()
将抛出任何已安装的调试器(VStudio、WinDbg、远程调试器等)捕获的断点
使用它调试非常棘手的区域,在这些区域中,常规F5+Go或“附加到进程”很难或不可能执行,一些示例包括:
- 短命过程
- 时间敏感过程
- 进入衍生的子进程
- 安装工
- 服务停止/启动
- 分布式系统
[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,就像我们在UI开发中所习惯的那样。(无论如何,安装程序只是另一个UI。)如果您的目标是在产品的所有安装程序之间共享特定的UI体验,这一点尤其重要。您还可以使用installUtil.exe实用程序测试安装程序组件 如果使用Installer类创建了c#类程序集,请更改调试设置以启动外部程序“c:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe” 并相应地输入命令行参数(例如/Args=myargument“程序集路径”) 最后一次设置断点时,按f5,就可以调试代码了。
--paralax我使用以下类将简单日志写入目标目录。在我看来,这比尝试使用VisualStudio调试器更容易
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(""); }
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
命名空间MyCompany.Deployment
{
///
///启用快速简便的调试自定义操作的方法。
///
类日志文件
{
const string FileName=“MyCompany.Deployment.log”;
只读字符串\u文件路径;
公共日志文件(字符串primaryOutputPath)
{
var dir=Path.GetDirectoryName(primaryOutputPath);
_filePath=Path.Combine(dir,FileName);
}
公共作废打印(例外情况除外)
{
File.AppendAllText(_filePath,“Error:+ex.Message+Environment.NewLine+
“堆栈跟踪:”+Environment.NewLine+ex.StackTrace+Environment.NewLine);
}
公共作废打印(字符串格式,参数对象[]args)
{
var text=String.Format(Format,args)+Environment.NewLine;
AppendAllText(_filePath,text);
}
public void PrintLine(){Print(“”;}
}
}
出于日志记录的目的(在3.5中),使用以下方法如何:
Context.LogMessage("My message");
令人惊讶的是,实际上没有人回答。将MessageBox.Show(“hello”)放入自定义操作的Install()成员中。在调试配置中构建部署。安装。当MessageBox出现时,进入VSIDE、调试、附加进程并查找标记为“托管”的msiexec实例。将调试器附加到msiexec的该实例。现在回到自定义操作的源,并在调用MessageBox.Show()之后放置一个断点。关闭MessageBox,您的断点将被命中,您正在IDE中调试 在安装程序方法中添加Debugger.Launch()语句,该语句将启动“Visual Studio实时调试器”,您可以在其中附加Visual Studio实例并调试安装程序类(MSI)。这应该在VisualStudio2010中也适用。但你需要有管理权才能做到这一点。如果您没有管理权限,则可能会出现问题。因此,以管理员身份登录以调试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>
节目
$(MSBuildBinPath)\installutil.exe
$(AssemblyName).dll
如果您想让其他开发人员受益于此更改,请使用project文件;如果您想自己使用,请使用.user文件。以上所有内容都不适用于我。这才是真正起作用的。请注意,您需要插入“两个”行
这才是真正对我有用的
System.Diagnostics.Debugger.Launch();
然后右键单击安装程序项目并按“安装”将其与System.Diagnostics.Debugger.Break()技巧结合使用,life将非常擅长生成可调试的复制程序。我也会这样做。。。。在应用程序完成执行后,写入日志并检查日志,以便获得clea
System.Diagnostics.Debugger.Launch();