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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/279523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:22:13  来源:igfitidea点击:

Debugging C# Custom Installer Classes

c#.netinstaller

提问by Deano

I have written an installation class that extends Installer and overrides afterInstall, but I'm getting a null pointer exception. How can I go about debugging my class?

我已经编写了一个扩展安装程序并覆盖 afterInstall 的安装类,但是我得到了一个空指针异常。我该如何调试我的课程?

回答by BCS

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,制作它的副本(或创建一个差异虚拟硬盘)并在 VM 下的调试器下运行安装程序。

That is what I would do (but I'm no expert).

这就是我会做的(但我不是专家)。

回答by Oscar Cabrero

attach the installer process to Visual studio in Debug->Processes->Attach or CTRL + ALT + P set the breakpoint and you should be able to go

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

回答by stephbu

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
  • 短暂的过程
  • 时间敏感的过程
  • 闯入衍生的子进程
  • 安装人员
  • 服务停止/启动
  • 分布式系统

回答by stephbu

I use EventLog.WriteEntry("source", "message"), and check the EventLog when installing. Maybe not optimal, but works for me :)

我使用 EventLog.WriteEntry("source", "message"),并在安装时检查 EventLog。也许不是最佳的,但对我有用:)

回答by Timex

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. 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.

至少它可以更好地利用 IDE 工具。这对于具有大量组件的大型安装程序特别有用。然后,您还可以创建有序的单元测试并按顺序运行它们,以在调试或自动构建期间模拟安装程序。

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. (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.

另一个技巧是通用的 SOLID/GRASS 软件原则......在整洁/薄层中开发,使您的实际“自定义操作”安装程序逻辑非常简单,而是调用您拥有的任何特定于您的安装程序的可重用 API 内容,就像我们习惯于 UI 开发一样。(无论如何,安装程序只是另一个 UI。)如果您的目标是让产品的所有安装程序共享特定的 UI 体验,这一点尤其重要。

回答by Mario Topf

You can also use the installUtil.exe utility to test your installer component.

您还可以使用 installUtil.exe 实用程序来测试您的安装程序组件。

In case you created a c# 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 (e.g. /Args=myargument "path to the assembly")

如果您使用安装程序类创建了 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. --paralax

最后设置断点时,按 f5 即可调试代码。--视差

回答by Wayne Bloss

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

回答by Almund

For logging purposes (in 3.5) what about using:

出于日志记录目的(在 3.5 中)如何使用:

Context.LogMessage("My message");

回答by Bob Denny

Surprised no one has actually answered. Put a MessageBox.Show("hello") into your custom action's Install() member. Build the deployment in 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". Attach the debugger to that instance of msiexec. Now go back to the source of your custom action and place a breakpoint right after the call to MessageBox.Show(). Close the MessageBox and your breakpoint will be hit, and you're debugging in the IDE!

没想到居然没人回答。将 MessageBox.Show("hello") 放入自定义操作的 Install() 成员中。在调试配置中构建部署。安装。当 MessageBox 出现时,进入 VS IDE、Debug、Attach Process 并查找标记为“Managed”的 msiexec 实例。将调试器附加到 msiexec 的该实例。现在返回到自定义操作的源代码并在调用 MessageBox.Show() 之后立即放置一个断点。关闭 MessageBox,您的断点将被命中,并且您正在 IDE 中进行调试!

回答by Muhammad Mubashir

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). This should work in Visual Studio 2010 as well. 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. For example:

在您的安装程序方法中添加 Debugger.Launch() 语句,该语句将启动“Visual Studio just in time debugger”,您可以在其中附加 Visual Studio 的实例并调试您的安装程序类 (MSI)。这也应该适用于 Visual Studio 2010。但是您需要具有管理权限才能执行此操作。如果您没有管理权限,您可能会遇到问题。因此,请以管理员身份登录以调试 MSI。例如:

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。