Flier's Sky

天空,蓝色的天空,眼睛看不到的东西,眼睛看得到的东西
posts - 115, comments - 295, trackbacks - 26, articles - 0

更新:程序员的思维模式都差不多,Kerem KusmezerJohn Robbin 发布了一个类似的工具.NET Mass Downloader。既然有的用我就不重新发明轮子了,下面那个项目停止维护,有需求的朋友直接用那个工具好了,具体使用说明可以参考


Download All the .NET Reference Source Code at Once with Net Mass Downloader

更新:在 sourceforge 上申请了一个项目,有兴趣的朋友可以上去下载代码,或者提交bug和改进建议。不过我估计也就年后才有时间继续处理,暂且挖个坑反正这里吧,呵呵

    从去年MS就开始喊着要开放.NET源代码,如今终于在一个含糊不清的授权协议下,通过Source Server的方式放了出来。虽然是如愿开源,但目前只提供几个核心模块,而且还限制必须在VS2008里面在线访问。
    其实既然决定开放,何必搞那么多限制出来,让偶等用着不爽还得自己动手丰衣足食,写个程序直接模拟VS2008获取源码的行为,一次性全部拖回来备用。
    空口无凭,上载一个
System.Xml 的源码包,和一个理论上能跑的程序原型,有兴趣的朋友可以试试。回头有时间了把相关代码整理一下再放出来,下面先大概说一下思路。

    首先,VS2008虽然要
打个补丁才能用源码调试,但这并不是下载源码的必要条件。MS发布源码所依赖的Source Server的机制,很早就通过 WinDbg 的发布包引入了。有兴趣的朋友可以使用 WinDbg 工具自己架设 Source Server,具体步骤请参考 %Debugging Tools for Windows%\sdk\srcsrv\ 目录下文档和脚本。
    而这个 Source Server 说白就是从 .pdb 调试符号文件里面,获取被绑定的已索引文件列表,然后根据系统_NT_SOURCE_PATH环境变量指定的服务器,拼接出一个 URL 然后通过http下载。具体这块的配置,可以参考
    Configuring Visual Studio to Debug .NET Framework Source Code
    讨厌的是MS在dbghelp.dll里面做了一些手脚,直接通过url去下载调试符号和源码是不被允许的。刚好scz前面研究过symbol server的行为,基本确定ms服务端是根据user agent来进行判断的。也就是说在发起请求时,把当前http的user agent改成ms认可的方式,就能够模拟dbghelp.dll通过srcsrv.dll完成的工作,具体代码类似

public const string DefaultUserAgent = "Microsoft-Symbol-Server/9.9.9.9 (C; V; ;)";

    
public void Restart(Uri uri)
    
{
      _request 
= (HttpWebRequest)WebRequest.Create(uri);
      _request.UserAgent 
= DefaultUserAgent;    

      IAsyncResult result 
= (IAsyncResult)_request.BeginGetResponse(
        
new AsyncCallback(ResponseCallback), this);
      ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
        
new WaitOrTimerCallback(TimeoutCallback), this, _timeout, true);      
    }
    另外一个罗嗦的事情,是每个链接建立后,MS服务器会先返回一个罗嗦的license声明,srcsrv.dll会弹出一个对话框让你Accept才能继续下载。
    例如你通过命令行去下载一个文件
wget  --user-agent=Microsoft-Symbol-Server/9.9.9.9
    Http:
//ReferenceSource.microsoft.com/source/.net/8.0/DEVDIV/
    depot
/DevDiv/releases/whidbey/REDBITS/ndp/fx/src/Misc/
   
InvariantComparer.cs/1/InvariantComparer.cs
    会直接返回一对垃圾信息,类似
SYMSRVCOMMAND:
YESNODIALOG:
IDYES:Accept:Accept=0cf80f849aa7449e9d064ade971bd887
IDNO:Decline:Decline=0cf80f849aa7449e9d064ade971bd887
TITLE:End User License Agreement
BUTTONDESCRIPTION:Please read carefully and understand the license agreement above. 
If you want to accept the license agreement, please click the “Accept” button.
TEXT:This license applies to the .NET Framework components that Microsoft makes available to you
in source code form.  To print these terms, select the contents of this area and copy then paste
into an application that can print text.

MICROSOFT .NET FRAMEWORK REFERENCE LICENSE
.NET FRAMEWORK REFERENCE SOURCE CODE


This license governs use of the accompanying software. If you use the software, you accept this license.
If you do not accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction" and "distribution" have the same meaning here as under U.S. copyright law.
 


    解决方法很简单,直接用正则表达式找到里面一个随机生成的id,然后程序自动Accept即可,代码类似
    private static Regex _accept = new Regex(@"IDYES:Accept:Accept=(\w*)");

          
if (task._auth)
          
{
          }

          
else
          
{
            
string license = Encoding.Unicode.GetString(task._buf, 0, read);

            Match m 
= _accept.Match(license);

            
if (m.Success)
            
{

              task._auth 
= true;

              
string id = m.Groups[1].Value;

              _logger.DebugFormat(
"Accept license id {0} for {1}", id, task._request.Address);

              Uri uri 
= new Uri(string.Format("{0}?Accept={1}", task._uri.ToString(), id));

              task.Restart(uri);
            }

          }

其他的基本上没什么需要说明的,就是很基本的http请求调用啥的,呵呵

至于从.pdb里面获取文件名列表,需要调用dbghelp.dll里面的一组api
SymInitializeW/SymCleanup用来初始化和析构symbol engine
SymLoadModuleExW/SymUnloadModule64用来加载要便利源代码的模块
SymEnumSourceFilesW用来遍历一个有.pdb符号且包含已索引源码的列表
SymGetSourceFileW和SymGetSourceFileTokenW/SymGetSourceFileFromToken两套API,都可以用来获得特定源码的下载URL,然后把这个地址用上面两个方法处理一下即可。

注意:目前的实现只是个原型,需要手动下载和配置.pdb文件,并且直接发起大量的异步http请求,对网速慢的朋友,可能需要用 -i 参数增加超时时间(确实15分钟)


   
   
 

Feedback

#1楼    回复  引用  查看    

2008-01-23 08:43 by cslar      
楼主编程能力甚强,,,不过,干嘛不多放点源码上来?

#2楼    回复  引用  查看    

2008-01-23 08:48 by 巫云      
想要JIT的源码,哈哈。

#3楼    回复  引用  查看    

2008-01-23 08:58 by 墙外行人      
佩服呀,

#4楼    回复  引用  查看    

2008-01-23 09:26 by 金鹏      
不错.

#5楼    回复  引用  查看    

2008-01-23 09:30 by 911      
佩服

#6楼    回复  引用  查看    

2008-01-23 11:21 by 路西菲尔      
期待把源码整理出来

#7楼    回复  引用  查看    

2008-01-23 11:52 by 老Q      
期待源码包,hoho

#8楼    回复  引用  查看    

2008-01-23 12:00 by hoodlum1980      
既然敢公开,相比ms觉得这是它推广他的.net framework类库的一个机遇,同时也可能说明这是ms在对c#类库重订的代码风格和设计标准是感到比较满意的,希望以此推广到更广大范伟的programmer中去。
但我并不是很赞成ms公布它的源码。

#9楼    回复  引用  查看    

2008-01-23 13:53 by 鞠强      
老大已经两年没有出手了。。。期待ing。。。

#10楼    回复  引用  查看    

2008-01-23 14:15 by Osamede      
fdg sdf

#11楼    回复  引用  查看    

2008-01-23 14:31 by Osamede      
对不住,放才按错了。
楼主太有才了,这俩天都是一个文件一个文件的下的,下了好多了,呵呵

#12楼    回复  引用  查看    

2008-01-23 15:52 by 破曉之陽      
還真會玩。呵呵

#13楼    回复  引用  查看    

2008-01-23 16:45 by beyondjay      
我看了一下楼主的blog顺带搜了一下楼主,感觉很牛x。
Java, .NET, 黑客技术,网络,机器人,操作系统都很厉害。
不知道你这样程度的人,目前在哪里高就?小弟佩服!

#14楼    回复  引用  查看    

2008-01-23 18:59 by birdshome      
老大一出手,就知有没有:)

#15楼    回复  引用  查看    

2008-01-23 23:51 by 刘荣华      
看到牛人了。
看了上面的回复,翻看了LZ每个博客
LZ对.NET,JAVA,嵌入式,网络每种技术领域都有精彩和深入的文章。

太佩服了。
跟您相比,咱就真是菜鸟了。
最近开始对嵌入式开发产生浓厚的兴趣,奈何不知道如何去学习。何况对一些硬件方面的基础太薄弱了,非常想跟LZ讨教一番。
我的邮件:mshunanboy@gmail.com

#16楼 [楼主]   回复  引用  查看    

2008-01-24 02:22 by Flier Lu      
@cslar
写这个只是一时冲动,几个小时内无法保障代码结构良好,回头有空把代码清理一下,免得放出来贻笑大方

@hoodlum1980
ms既然放出源码,说明是经过了仔细考虑的。一方面可能出于推广.net的大策略,另一方面ms近年来的确开放很多。

@鞠强
懒得更新blog,因为近期主要兴趣不在这上面。回头有空了把前段折腾的lock-free/wait-free和GPGPU啥的整理一下,那块的内容才叫有意思 :P

@Osamede
懒人推动世界进步 :D

@beyondjay
惭愧,涉及领域的确太广,但博而不深意义不大,混饭吃的工作倒跟这些关系不大

@刘荣华
嵌入式基本上是几年前折腾过,现在基本已经跟不上潮流了,呵呵。如果有.net基础,在.net cf上开发应该容易上手,毕竟现在资料多啊 :)

#17楼    回复  引用  查看    

2008-01-24 17:44 by 梦在天涯      

#18楼    回复  引用  查看    

2008-01-24 22:33 by Wisdom-zh      
微软的这种遮遮掩掩的态度, 有时真觉得有点变态.

#19楼    回复  引用  查看    

2008-01-27 12:29 by 汉广      
刚没事用那个程序下了好些,不错,呵呵。
只是好像同时只能打开一个进程下,要是同时运行俩个以上就会抛出异常,

#20楼    回复  引用  查看    

2008-01-27 13:50 by 汉广      
System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
一下这个就抛出异常

#21楼    回复  引用  查看    

2008-06-10 10:18 by lbq1221119      
哇塞,看到偶像scz了.
四哥现在还好吧