背景:

某个.net 应用以大发棋牌大发棋牌技巧技巧 Win dows大发棋牌大发棋牌技巧技巧 服务 的形式对外提供大发棋牌大发棋牌技巧技巧 服务 ,然后通过IIs的web应用和该大发棋牌大发棋牌技巧技巧 服务 进行交互,通过web的方式向用户提供业务。该项目有点年头,目前相当于自己维护,没厂家支持,而且自定义了很多开发在上面,但是有一个棘手的问题是该项目没有提供所有源码的,类似大发棋牌大发棋牌技巧技巧 服务 程序,使用的相关DLL还进行了混淆加密,所以其内部逻辑通过反编译看源码会非常绕,而且就算反混淆后,代码的大发棋牌大发棋牌技巧技巧 组织 和命名也会差很多,看起来会非常的累。


症状:

1. 某次为了和生产保持一致,就地升级了测试环境的操作系统(2012 r2 到2016),这个大发棋牌大发棋牌技巧技巧 服务 死活其不来,还好做了VM的快照。这个程序错误的时候就在日志里记了一条“输入字符串格式不对”,没头没脑,也不包含stack trace ,不知道哪里报的错。后来没有办法,拿快照回退,初步判定为操作系统兼容性问题(注意是.net 4.x 开发的,虽然有点怀疑这个结论)

2. 另外的同事为了熟悉这个系统,在新的测试环境,重新部署了一套这个系统(操作系统使用的2019),系统可以运行,没有问题。(所以大发棋牌大发棋牌技巧技巧 我 很怀疑1 中的兼容性问题,但目前大发棋牌大发棋牌技巧技巧 我 找不到原因)

3. 恢复快照的测试环境,后又经历过两次大发棋牌大发棋牌技巧技巧 服务 起不来的问题。有次打了补丁,有次是重启就不行了。但是因为没有太多思路去排错(因为配置什么的都没有变过,关键是也没有什么有用的日志协助排错,而且没大发棋牌大发棋牌技巧技巧 技术 支持,没源码),后面偷懒直接恢复了快照解决。

4.  测试环境因为需要更新补丁,重启,结果大发棋牌大发棋牌技巧技巧 服务 又挂了。还是一样的报错

尝试解决:

实在忍不了,大发棋牌大发棋牌技巧技巧 我 必须得把这个原因找出来,不然在生产上出现,真的没法处理,而且到时候肯定手忙脚乱。初步的想法是通过调试器直接调试这个大发棋牌大发棋牌技巧技巧 服务 ,然后找到报错的位置,大致按逻辑找到可能出错的位置。从而找出到底是配置问题、还是兼容性问题,还是其他的什么。


由于是个.net 应用,带调试功能,且能反编译的DNSpy 就属于大发棋牌大发棋牌技巧技巧 我 的首选大发棋牌大发棋牌技巧技巧 工具 了。支持直接查看.net 语言编译的exe、dll 文件,而且支持直接调试,而且可以就地对dll、exe的代码进行修改并保存。


image

结果调试一个大发棋牌大发棋牌技巧技巧 Win dows 大发棋牌大发棋牌技巧技巧 服务 没有大发棋牌大发棋牌技巧技巧 你 想的简单。当使用DNSpy调试运行一个大发棋牌大发棋牌技巧技巧 Win dows 大发棋牌大发棋牌技巧技巧 服务 时,由于其不是通过net start 或者大发棋牌大发棋牌技巧技巧 Win dows 大发棋牌大发棋牌技巧技巧 服务 管理器执行的,所以报这个错误。

C681F9BE

这可如何是好,这个大发棋牌大发棋牌技巧技巧 服务 起来就挂掉,大发棋牌大发棋牌技巧技巧 我 没有通过attach 到进程的方式来调试啊。还好微软的文章提供了一些思路。http://docs.microsoft.com/en-us/dotnet/framework/大发棋牌大发棋牌技巧技巧 Win dows-services/how-to-debug-大发棋牌大发棋牌技巧技巧 Win dows-service-applications#debugging-tips-for-大发棋牌大发棋牌技巧技巧 Win dows-services

两个选项:

1. 在大发棋牌大发棋牌技巧技巧 服务 的onstart或者main 里增加sleep ,延长大发棋牌大发棋牌技巧技巧 服务 执行实际代码的时间,在sleep 没报错的时候,使用调试器attch上去(加sleep 也就一两行代码的改动,应该可以直接使用dnspy搞定,即使混淆过了,但是程序入口这些还是很容易找到的,因此选择了该大发棋牌技巧方法 )

2. 把大发棋牌大发棋牌技巧技巧 服务 的程序逻辑改写,重新编译成一个console 程序。(没源码,修改较多,看来不太适合大发棋牌大发棋牌技巧技巧 我 的情况)


Dnspy 打开大发棋牌大发棋牌技巧技巧 服务 程序的exe文件,定位到onstart 大发棋牌技巧方法 ,然后点击右键,选择”编辑大发棋牌技巧方法 (C#)“

image

增加一个sleep,大发棋牌大发棋牌技巧技巧 我 这里大概5秒钟,可以手快的执行完attach,另外在onstart处下断点。

image

保存修改。然后再DNspy的文件菜单中选择保存模块。这样会把更改写入到新的exe中(注意保留备份)


image

在大发棋牌大发棋牌技巧技巧 服务 管理器中启动大发棋牌大发棋牌技巧技巧 服务 。


使用dnspy 调试--附加到进程

image

注意点: 这里附加到进程能列出的是dnspy执行账号下的进程,加入大发棋牌大发棋牌技巧技巧 你 的大发棋牌大发棋牌技巧技巧 服务 以其他用户身份执行,可能列举不出来,所以可能要更换dnspy的运行账号。

image


后续由于涉及到应用内部的内容,就不写出来了,大概定位到是程序加载某些自生成的配置文件(二进制),然后某些目录的配置文件不知被谁拷贝了一份,名称为xx.yy-复制,导致程序加载报错(可能是文件名问题),但是报错内容只有一条“输入格式不正确”,因为程序本身对错误进行了catch ,然后没有记录下面stack信息,调试器里其实可以看到。虽然代码进行了混淆,但是还可以定位到大概的位置。

在 System.Version.VersionResult.SetFailure(ParseFailureKind failure, String argument)  
在 System.Version.TryParseComponent(String component, String componentName, VersionResult& result, Int32& parsedComponent)  
在 System.Version.TryParseVersion(String version, VersionResult& result)  
在 System.Version.Parse(String input)  
在 System.Version..ctor(String version)  
在 OO.Server.OOProcess.a(String A_0, Version& A_1)  
在 OO.Server.OOProcess.b(String A_0)  
在 l.c(String A_0)  
在 l.j()  
在 l.b(Boolean A_0)  
在 l.b(Boolean A_0)  
在 s4.a(Boolean A_0, Boolean A_1)  
在 aje.g()  
在 OO.Server.Server.Start()


总结分析:

综合以上多个历史症状,可以得出问题原因是复制的自动生成的配置文件导致了应用crash,只是大发棋牌大发棋牌技巧技巧 服务 不重启的时候,这个配置文件不会重新加载,所以无论是升级操作系统、打补丁、重启都是由于间接重启了大发棋牌大发棋牌技巧技巧 服务 导致配置重新加载,然后触发错误。

大发棋牌大发棋牌技巧技巧 更多 思考和问题:

这个程序是一个.net 反编译和更改代码相对简单,但是如果大发棋牌大发棋牌技巧技巧 服务 是个C程序或者C++编译的,如何进行调试呢?如何增加sleep 呢,或者有其他更好的大发棋牌技巧方法 进行调试。而且程序本身catch了异常,退出也是相对优雅的退出,不能通过在程序无处理异常时打开调试器的大发棋牌技巧方法 。