简体   繁体   English

调试C#自定义安装程序类

[英]Debugging C# Custom Installer Classes

I have written an installation class that extends Installer and overrides afterInstall, but I'm getting a null pointer exception. 我编写了一个安装类,它扩展了Installer并覆盖了afterInstall,但是我得到了一个空指针异常。 How can I go about debugging my class? 我怎样才能调试我的课程?

Something that is handy for hard to debug sections of code is 对于难以调试的代码段而言非常方便的东西是

System.Diagnostics.Debugger.Break()

Will throw a breakpoint caught by any installed debugger (VStudio, WinDbg, Remote debugger etc...). 将抛出任何已安装的调试器(VStudio,WinDbg,远程调试器等)捕获的断点。

Use it to debug really tricky areas where regular F5+Go or "Attach to Process" is difficult or impossible to perform, some examples include: 使用它来调试非常棘手的区域,其中常规F5 + Go或“附加到进程”很难或不可能执行,一些示例包括:

  • short-lived processes 短暂的过程
  • time-sensitive processes 时间敏感的过程
  • breaking into spawned sub-processes 分解产生的子流程
  • installers 安装
  • service stop/start 服务停止/开始
  • distributed systems 分布式系统

The best way I've found is to write a unit test, and new up and initialize your installer class from your unit test: 我发现的最好方法是编写单元测试,并从单元测试中新建并初始化安装程序类:

[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());
} }

At least then it takes advantage of the IDE tooling better. 至少它会更好地利用IDE工具。 This is especially helpful for very large installers with LOTS of components. 这对于拥有大量组件的大型安装人员尤其有用。 Then you can also create ordered unit tests and run them in sequence to mimic your installer during debug or your automated builds. 然后,您还可以创建有序单元测试并按顺序运行它们,以在调试或自动构建期间模拟安装程序。

Another tip would be general SOLID/GRASS software principles...develop in neat/thin layers, keeping your actual "custom action" installer logic very simple and instead call into any reusable API stuff you have that is specific to your installer(s), just as we are used to with UI development. 另一个提示是一般的SOLID / GRASS软件原理...以整洁/薄层形式开发,保持您的实际“自定义操作”安装程序逻辑非常简单,而是调用任何特定于您的安装程序的可重用API内容就像我们习惯于UI开发一样。 (The installer is just another UI anyway.) This is especially key if your goal is to have a certain UI experience shared across all installers of your products. (无论如何,安装程序只是另一个UI。)如果您的目标是在产品的所有安装程序之间共享某种UI体验,那么这一点尤为关键。

Surprised no one has actually answered. 惊讶没有人真正回答过。 Put a MessageBox.Show("hello") into your custom action's Install() member. 将MessageBox.Show(“hello”)放入自定义操作的Install()成员中。 Build the deployment in debug config. 在debug config中构建部署。 Install. 安装。 When the MessageBox appears, go into VS IDE, Debug, Attach Process and look for the instance of msiexec that is labeled "Managed". 出现MessageBox时,进入VS IDE,Debug,Attach Process并查找标记为“Managed”的msiexec实例。 Attach the debugger to that instance of msiexec. 将调试器附加到msiexec的该实例。 Now go back to the source of your custom action and place a breakpoint right after the call to MessageBox.Show(). 现在返回自定义操作的源,并在调用MessageBox.Show()之后立即放置断点。 Close the MessageBox and your breakpoint will be hit, and you're debugging in the IDE! 关闭MessageBox,您的断点将被点击,您正在IDE中进行调试!

在Debug-> Processes-> Attach或CTRL + ALT + P中将安装程序进程附加到Visual Studio,设置断点,你应该可以去

In your installer method add Debugger.Launch() statement which will launch "Visual Studio just in time debugger" where you can attach an instance of visual studio and debug your installer class (MSI). 在安装程序方法中添加Debugger.Launch()语句,该语句将启动“Visual Studio just in time debugger”,您可以在其中附加visual studio实例并调试安装程序类(MSI)。 This should work in Visual Studio 2010 as well. 这应该也适用于Visual Studio 2010。 But you need to have administrative rights to do this. 但是您需要拥有管理权限才能执行此操作。 If you don't have administrative rights, you might have issues. 如果您没有管理权限,则可能会遇到问题。 So, log in as administrator for debugging MSI. 因此,以管理员身份登录以调试MSI。 For example: 例如:

public override void Install(System.Collections.IDictionary stateSaver)
{
    Debugger.Launch();
    base.Install(stateSaver);

}

In visual studio 2005, even Debugger.Break() use to work but somehow this does not work with Visual Studio 2010. 在visual studio 2005中,甚至Debugger.Break()都可以使用,但不知何故,这不适用于Visual Studio 2010。

Write the following code in the beginning of the method that you want to debug 在要调试的方法的开头写下以下代码

#if DEBUG
MessageBox.Show(Process.GetCurrentProcess().Id.ToString());
#endif

So when your method is called, the above code will be hit and you can then attach the debugger to the process(ctrl+alt+p) using the above process ID. 因此,当调用您的方法时,将触发上面的代码,然后您可以使用上面的进程ID将调试器附加到进程(ctrl + alt + p)。 You may have to start VS with elevated permissions. 您可能必须使用提升的权限启动VS.

You can also use the installUtil.exe utility to test your installer component. 您还可以使用installUtil.exe实用程序来测试安装程序组件。

In case you created ac# class assembly with your Installer class, Change your debug settings to start the external program 'C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\InstallUtil.exe' and enter your commandline arguments accordingly (eg /Args=myargument "path to the assembly") 如果您使用Installer类创建了ac#类程序集,请更改调试设置以启动外部程序'C:\\ Windows \\ Microsoft.NET \\ Framework \\ v2.0.50727 \\ InstallUtil.exe'并相应地输入命令行参数(例如, / Args = myargument“程序集的路径”)

As last set your breakpoints, press f5 and you're set to debug your code. 在上次设置断点时,按f5键,然后设置为调试代码。 --paralax --paralax

None of above worked for me. 以上都不适合我。 This is what actually worked. 这是实际工作的。 Note that you need to put insert "both" lines. 请注意,您需要插入“两个”行。

using System.Diagnostics;

MessageBox.Show("Test is about to begin");
Debugger.Launch();

I use the following class to write a simple log into the target directory. 我使用以下类将简单日志写入目标目录。 In my opinion, it's easier than trying to use the Visual Studio debugger. 在我看来,它比尝试使用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");

I use EventLog.WriteEntry("source", "message"), and check the EventLog when installing. 我使用EventLog.WriteEntry(“source”,“message”),并在安装时检查EventLog。 Maybe not optimal, but works for me :) 也许不是最优的,但对我有用:)

You might automate debugging of installer projects by adding following section to either .csproj or .csproj.user file: 您可以通过将以下部分添加到.csproj或.csproj.user文件来自动调试安装程序项目:

<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
  <StartAction>Program</StartAction>
  <StartProgram>$(MSBuildBinPath)\installutil.exe</StartProgram>
  <StartArguments>$(AssemblyName).dll</StartArguments>
</PropertyGroup>

Use project file if you want other developers benefit from this change and .user file if you want to use it by yourself. 如果您希望其他开发人员从此更改和.user文件中受益,请使用项目文件(如果您想自己使用它)。

build a VM, install Visual studio, make a copy of it (or create a differencing Virtual HDD) and run the installer under the debugger under the VM. 构建VM,安装Visual Studio,制作它的副本(或创建差异虚拟HDD)并在VM下的调试器下运行安装程序。

That is what I would do (but I'm no expert). 这就是我要做的事(但我不是专家)。

This is what actually worked for me. 这实际上对我有用。

System.Diagnostics.Debugger.Launch();

Then right click on the Installer Project and press "Install" 然后右键单击安装程序项目并按“安装”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM