Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调试C#自定义安装程序类_C#_.net_Installation - Fatal编程技术网

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

调试C#自定义安装程序类,c#,.net,installation,C#,.net,Installation,我已经编写了一个安装类来扩展Installer并覆盖afterInstall,但是我得到了一个空指针异常。如何调试我的类?构建虚拟机,安装Visual studio,复制它(或创建差异虚拟硬盘),并在虚拟机下的调试器下运行安装程序 这就是我要做的(但我不是专家)。在调试->进程->附加或CTRL+ALT+p中将安装程序进程附加到Visual studio 设置断点,您应该能够转到对于难以调试的代码部分来说,方便的方法是 System.Diagnostics.Debugger.Break() 将

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

构建虚拟机,安装Visual studio,复制它(或创建差异虚拟硬盘),并在虚拟机下的调试器下运行安装程序


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

在调试->进程->附加或CTRL+ALT+p中将安装程序进程附加到Visual studio
设置断点,您应该能够转到

对于难以调试的代码部分来说,方便的方法是

System.Diagnostics.Debugger.Break()
将抛出任何已安装的调试器(VStudio、WinDbg、远程调试器等)捕获的断点

使用它调试非常棘手的区域,在这些区域中,常规F5+Go或“附加到进程”很难或不可能执行,一些示例包括:

  • 短命过程
  • 时间敏感过程
  • 进入衍生的子进程
  • 安装工
  • 服务停止/启动
  • 分布式系统

我使用EventLog.WriteEntry(“源”、“消息”),并在安装时检查事件日志。也许不是最理想的,但对我来说很有用:)

我发现最好的方法是编写一个单元测试,然后从单元测试中新建并初始化安装程序类:

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