<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>赵翔鹏的Blog &#187; Windows编程</title>
	<atom:link href="http://www.zhaoxiangpeng.com/category/windows%e7%bc%96%e7%a8%8b/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zhaoxiangpeng.com</link>
	<description>Xiangpeng&#039;s Thinkpad</description>
	<lastBuildDate>Sat, 21 Jan 2012 17:45:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Windows里跟performance相关的一些概念</title>
		<link>http://www.zhaoxiangpeng.com/2009/11/performance-related-concepts-in-windows/</link>
		<comments>http://www.zhaoxiangpeng.com/2009/11/performance-related-concepts-in-windows/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 13:44:51 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/?p=656720</guid>
		<description><![CDATA[1、kernel里的Cache Manager： 提供了在ReadFile、WriteFile时的cache，包括read-ahead和write-behind机制。原理是把application本来应该让file system服务的I/O request截走，转给cache manager自己拥有的一小块memory。 Cache manager就像一个应用程序，它只管虚拟内存，真正的物理内存管理都由memory manager做。所以cache那一部分memory也可能被page out。 只针对普通的file，dll、exe文件不会read-ahead。更精确的说，凡是用memory-mapped file方式读取的文件，都不会被read-ahead。 2、Prefetch： 在启动一个Process时，总要load一些dll，常用的几个icon等。如果等用到了再去读就比较慢，而且硬盘磁头会来回跑路。prefetch会根据上次process运行的历史记录，按照它们在磁盘上的顺序预读这些dll。 因此，一个程序第一次运行时可能硬盘要转很久，但以后再运行就快了。Prefetch对Boot也有类似的优化，会自动defrag启动时用到的文件。 可能的问题：上次打开的文件这次未必用到。 3、SuperFetch： 为了解决“after-lunch effect”引入的。为啥午饭回来之后outlook很迟钝，硬盘在狂转？因为在idle的时候杀毒软件开始扫描磁盘，占用大量物理内存，outlook不幸被page out了。等杀毒软件运行完释放了内存，LRU算法会把杀毒软件留在内存的standby list里，而outlook的页面却不会从pagefile里回来。 类似Prefetch，SuperFetch记录内存的历史使用情况。它考虑了时间信息，比如“每天下午2：00要用Outlook”，这样就预先把需要的东西读到内存里。而且也会考虑把常用/重要的东西（比如输密码解锁那段code）尽量留在内存里。 只要发现你的空闲内存比较大（比如刚有一个大程序退出），它就会一点一点地吃掉你的空闲内存，把它认为需要用的东西放在内存里。所以很多人误以为SuperFetch浪费内存。 4、ReadyBoost： 用优盘当虚拟内存。hard fault发生时，从优盘读比硬盘稍微能快一点点。 5、ReadyBoot： 在boot的时候，预读一些硬盘数据到内存里。这个跟prefetch很像但是更智能。我现在还不是很清楚这个东西怎么工作的。还需要翻一翻宝书Windows Internals 5。。。 Update: 今天翻了宝书，发现宝书上只用了1页描述ReadyBoot……郁闷，还是不清楚。这也意味着即使我通过别的方法把它搞清楚，也不能把结果贴出来了。]]></description>
			<content:encoded><![CDATA[<p><strong>1、kernel里的</strong><a href="http://windowsitpro.com/Articles/Index.cfm?ArticleID=3864" target="_blank"><strong>Cache Manager</strong></a><strong>：</strong></p>
<p>提供了在ReadFile、WriteFile时的cache，包括read-ahead和write-behind机制。原理是把application本来应该让file system服务的I/O request截走，转给cache manager自己拥有的一小块memory。</p>
<p>Cache manager就像一个应用程序，它只管虚拟内存，真正的物理内存管理都由memory manager做。所以cache那一部分memory也可能被page out。</p>
<p>只针对普通的file，dll、exe文件不会read-ahead。更精确的说，凡是用memory-mapped file方式读取的文件，都不会被read-ahead。</p>
<p><strong>2、Prefetch：</strong></p>
<p>在启动一个Process时，总要load一些dll，常用的几个icon等。如果等用到了再去读就比较慢，而且硬盘磁头会来回跑路。prefetch会根据上次process运行的历史记录，按照它们<strong>在磁盘上的顺序</strong>预读这些dll。</p>
<p>因此，一个程序第一次运行时可能硬盘要转很久，但以后再运行就快了。Prefetch对Boot也有类似的优化，会自动defrag启动时用到的文件。</p>
<p>可能的问题：上次打开的文件这次未必用到。</p>
<p><strong>3、</strong><a href="http://technet.microsoft.com/en-us/magazine/2007.03.vistakernel.aspx" target="_blank"><strong>SuperFetch</strong></a><strong>：</strong></p>
<p>为了解决“after-lunch effect”引入的。为啥午饭回来之后outlook很迟钝，硬盘在狂转？因为在idle的时候杀毒软件开始扫描磁盘，占用大量物理内存，outlook不幸被page out了。等杀毒软件运行完释放了内存，LRU算法会把杀毒软件留在内存的standby list里，而outlook的页面却不会从pagefile里回来。</p>
<p>类似Prefetch，SuperFetch记录内存的历史使用情况。它考虑了时间信息，比如“每天下午2：00要用Outlook”，这样就预先把需要的东西读到内存里。而且也会考虑把常用/重要的东西（比如输密码解锁那段code）尽量留在内存里。</p>
<p>只要发现你的空闲内存比较大（比如刚有一个大程序退出），它就会一点一点地吃掉你的空闲内存，把它认为需要用的东西放在内存里。所以很多人误以为SuperFetch浪费内存。</p>
<p><strong>4、ReadyBoost：</strong></p>
<p>用优盘当虚拟内存。hard fault发生时，从优盘读比硬盘稍微能快一点点。</p>
<p><strong>5、ReadyBoot：</strong></p>
<p>在boot的时候，预读一些硬盘数据到内存里。这个跟prefetch很像但是更智能。我现在还不是很清楚这个东西怎么工作的。还需要翻一翻宝书<a href="http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301" target="_blank">Windows Internals 5</a>。。。</p>
<p>Update: 今天翻了宝书，发现宝书上只用了1页描述ReadyBoot……郁闷，还是不清楚。这也意味着即使我通过别的方法把它搞清楚，也不能把结果贴出来了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2009/11/performance-related-concepts-in-windows/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>C#和CLR的15个细节</title>
		<link>http://www.zhaoxiangpeng.com/2009/02/c%e5%92%8cclr%e7%9a%8415%e4%b8%aa%e7%bb%86%e8%8a%82/</link>
		<comments>http://www.zhaoxiangpeng.com/2009/02/c%e5%92%8cclr%e7%9a%8415%e4%b8%aa%e7%bb%86%e8%8a%82/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 23:36:37 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[计算机技术]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/c%e5%92%8cclr%e7%9a%8415%e4%b8%aa%e7%bb%86%e8%8a%82.html</guid>
		<description><![CDATA[这两周一直在training，一共听了4个课程，相当的累啊。 今天先把Jeffrey Richter的培训课：C# and CLR中讲到的一些东西整理一下： foreach的性能问题 foreach(string s in rows) { foo(s); }的实现是： IEnumerator e = rows.GetEnumerator(); try { string s; while (e.MoveNext()) { s = (String) e.Current; foo(s); } } finally { IDisposable d = e as IDisposable; if (d != null) d.Dispose(); } 每一步都调用了e.MoveNext()和e.Current两个方法；而大多数时候，完全有可能优化为一次调用。显然这对性能是有影响的。虽然foreach对于数组作了单独的优化（编译成for循环），但这还是值得注意的。 那么，怎么做比较快？ 对于List等Collection，可以用ForEach(Action&#60;T&#62; action)，FindAll(Predicate&#60;T&#62; match)，ConvertAll&#60;U&#62;(Converter&#60;T, U&#62; converter)等方法。它们比较快，但不是所有实现IEnumerable的类都提供。 LINQ追求compatiblity，而不是performance。因此LINQ的实现完全采用了foreach。值得注意。 yield的实现原理 实现一个支持IEnumerable的对象时，一般会用到yield关键字，这样foreach遍历这个对象时，可以做到lazy [...]]]></description>
			<content:encoded><![CDATA[<p>这两周一直在training，一共听了4个课程，相当的累啊。</p>
<p>今天先把Jeffrey Richter的培训课：C# and CLR中讲到的一些东西整理一下：</p>
<ol>
<li><strong>foreach的性能问题 </strong>      </p>
<p>foreach(string s in rows) { foo(s); }的实现是：       </li>
<div>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">IEnumerator e = rows.GetEnumerator();
<span style="color: #0000ff">try</span> {
  <span style="color: #0000ff">string</span> s;
  <span style="color: #0000ff">while</span> (e.MoveNext()) {
    s = (String) e.Current;
    foo(s);
  }
}
<span style="color: #0000ff">finally</span> {
  IDisposable d = e <span style="color: #0000ff">as</span> IDisposable;
  <span style="color: #0000ff">if</span> (d != <span style="color: #0000ff">null</span>) d.Dispose();
}</pre>
<p>每一步都调用了e.MoveNext()和e.Current<strong>两个</strong>方法；而大多数时候，完全有可能优化为一次调用。显然这对性能是有影响的。虽然foreach对于数组作了单独的优化（编译成for循环），但这还是值得注意的。</p>
<p>那么，怎么做比较快？</p>
<p>对于List等Collection，可以用ForEach(Action&lt;T&gt; action)，FindAll(Predicate&lt;T&gt; match)，ConvertAll&lt;U&gt;(Converter&lt;T, U&gt; converter)等方法。它们比较快，但不是所有实现IEnumerable的类都提供。</p>
<p>LINQ追求compatiblity，而不是performance。因此LINQ的实现完全采用了foreach。值得注意。</p>
</div>
</ol>
<ol>
<li><strong>yield的实现原理 </strong>
<p>实现一个支持IEnumerable的对象时，一般会用到yield关键字，这样foreach遍历这个对象时，可以做到lazy evaluation。例如：</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &#39;Courier New&#39;, courier, monospace; background-color: #f4f4f4">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">class</span> MyCollection: IEnumerable&lt;<span style="color: #0000ff">char</span>&gt; {
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> s; ...
  <span style="color: #0000ff">public</span> IEnumerable&lt;<span style="color: #0000ff">char</span>&gt; GetEnumerator() {
    <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i=0; i&lt;s.Length; i++) {
      <span style="color: #0000ff">yield</span> <span style="color: #0000ff">return</span> s[i];
    }
  }
}</pre>
</p></div>
<p>执行到yield时函数返回，下次调用时，接着上次运行的位置继续运行。这个continuation的效果是怎么做的呢？</p>
<p>包含yield的函数都会被编译器做成一个<strong>状态机</strong>。每调一次，就接着上次的状态继续运行。简单有效啊。我一直以为要有什么特殊的办法呢。</p>
<p></li>
<li><strong>exception handling的实现决定了throw的performance较差。 </strong>
<p>可以用Int32.TryParse代替try{Int32.Parse…}catch{…}，稍快一点。类似地建议使用Dictionary.TryGetValue。</p>
<p></li>
<li><strong>.Net CLR执行引擎对应于MSCorWks.dll和MSCorEE.dll这两个文件。<br />
      <br /></strong></li>
<li><strong>.Net 3.0, 3.5没有对CLR作任何修改。</strong>
<p>所有增加的东西（比如LINQ）都是syntactic sugar，只改了C#编译器而已。</p>
<p></li>
<li><strong>AppDomain<br />
      <br /></strong></p>
<p>如果把.Net虚拟机看成一个虚拟操作系统，AppDomain的概念则类似于操作系统中的进程。</p>
<p>可以用代码创建一个AppDomain，然后动态加载/卸载assembly，还可以设置权限，相当于提供了一个沙箱。</p>
<p>跨AppDomain的调用类似于RPC。</p>
<p>调用某个AppDomain内部的obj.foo(x)时，.net会自动帮你做出一个proxy object，你所调用的obj其实是一个proxy object。传给foo的参数x会先被被marshal，以保证AppDomain被安全隔离。</p>
<p>谁用AppDomain？SQL Server用这个技术实现managed存储过程。IIS会把不同的Web Application放在不同的AppDomain里，以实现动态装卸。</p>
<p></li>
<li><strong>动态载入Assembly的陷阱</strong>
<p>Sytem.Reflection.Assembly.LoadFrom(pathName)并不会载入pathName所指定的dll，而是看看pathName那个dll的名字、版本，然后到系统默认位置去找。（陷阱啊）</p>
<p></li>
<li><strong>C#里用reflection创建一个新对象
<p></strong>用Activator.CreateInstance。（奇怪的名字啊。）</p>
<p></li>
<li><strong>C#泛型之“where”</strong>
<p>可以用“where”来限定T的接口。例如</p>
<p>static T min&lt;T&gt;(T arg1, T arg2) where T: IComparable&lt;T&gt; {…}</p>
<p>不写where的话，就不能调arg1.CompareTo(arg2)。</p>
<p>为啥不把T换成IComparable？一是为保证arg1, arg2一定是同一个类型，二是泛型的效率更高。（JIT会为不同类型的T各生成一份native code，从而避免了boxing）</p>
<p>更多where的细节：</p>
<p>* 要想调T t1 = new T()，必须声明where T: new()或者where T: struct</p>
<p>* 要写T t2 = null，必须声明where T: class</p>
<p>* T z = default(T)是一个特殊的用法，会把T的每个bit都置为0。</p>
<p>* 假设定义了Foo&lt;T&gt;(T x, T y)，则if (x==null) … 是可以通过的，虽然C#中value type的值不允许为null（例如int a=null是错的）。这是因为，此时的语义是一致的，反正if里面的操作不被执行就是了，所以编译器对这种特殊情况网开一面。</p>
<p>* if (x==y)不行，除非写了where T: baseclass。（这里我也没理解为啥。。。&gt;_&lt;好像说是不知道应该用reference比较还是value比较？）</p>
<p></li>
<li><strong>匿名函数的背后。。。</strong>
<p>在C# 2.0以后可以用匿名的delegate，如ThreadPool.QueueWorkItem(delegate (Object obj) { Console.WriteLine(obj); })</p>
<p>但编译器的实现会带来一点点overhead，会生成一个小小的静态WaitCallback对象，可以用Reflector看生成的代码。（不要打开Reflector的optimization，否则就看不到了）</p>
<p>如果是自己写的话，可以选择每次动态建立一个WaitCallback对象然后销毁。当然这样做性能可能差一些，但这里的idea是：编译器会自动做一些事，但不一定是你所希望的。在使用这些高级feature前，最好先搞清楚背后发生了什么。</p>
<p>另一个细节：如果匿名函数中使用了外层函数的局部变量（即所谓的function closure），会导致创建额外的shared-state object，把用到的局部变量做成一个新对象传给匿名函数。</p>
<p>上述描述同样适用于lambda函数。因为C#的lambda函数就是匿名函数，改了改语法而已。</p>
<p></li>
<li><strong>Nullable type<br />
      <br /></strong></p>
<p>虽然C#要求value type的值不能是null，但写数据库程序时经常遇到某个值是null的情况。为此，C#2.0引入了Nullable type。例如，int? x = null。</p>
<p>int? x其实就是一个缩写，等价于Nullable&lt;int&gt; x。Nullable是预定义的一个类，简单地对x作了封装。（因为增加了一个类，显然对性能稍微有点影响）</p>
<p>这个小改动的实现其实很麻烦，需要修改CLR。为什么？因为原先的x是一个value type，现在则变成了一个object，看这个：</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &#39;Courier New&#39;, courier, monospace; background-color: #f4f4f4">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">void</span> M(Object o) {
  <span style="color: #0000ff">if</span> (o=<span style="color: #0000ff">null</span>) {Bar();}
}
<span style="color: #0000ff">void</span> F() {
  <span style="color: #0000ff">int</span>? x = <span style="color: #0000ff">null</span>;
  M(x);
}</pre>
</p></div>
<p>如果CLR不专门做修正的话，上面的Bar()不会被执行。（思考题：想一想为什么~）</p>
<p>另外，C#还引入了一个默认值运算符“??”，称为null-coalescing operator。</p>
<p>一句话，x ?? value是 (x==null) ? value: x的简写。</p>
<p></li>
<li><strong>属性(property)的简单声明 </strong>
<p>public int x {get; private set;}是个很好用的句式。</p>
<p>注意，public int x {get;}是错误的，不能通过编译。</p>
<p></li>
<li><strong>Extension method<br />
      <br /></strong></p>
<p></p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &#39;Courier New&#39;, courier, monospace; background-color: #f4f4f4">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> MyExtMethods {
  <span style="color: #0000ff">static</span> <span style="color: #0000ff">public</span> GetFirstLetter(<span style="color: #0000ff">this</span> <span style="color: #0000ff">string</span> s) {<span style="color: #0000ff">return</span> s[0];}
}</pre>
</p></div>
<p>然后就可以用string s = “hello”; char ch = s.GetFirstLetter()了。</p>
<p>原理很简单，编译器把上面那句话翻译成MyExtMethods.GetFirstLetter(s)。LINQ就用到了这个技术。</p>
<p></li>
<li><strong>匿名类型的背后。。。 </strong>
<p>var o = new {name = “Xiangpeng”, id = 123 };</p>
<p>在这背后是编译器生成的一个匿名类，包含了两个<strong>只读</strong>属性，形如public int id { get {return _id;} }为什么不做成可读写的呢？</p>
<p>很微妙。匿名类自动生成了GetHashCode()，返回的是对所有属性的hash code做XOR的结果。如果允许修改属性值，那么Hash code的值就会变化；而这个可能会出问题~保险起见，只读吧。</p>
<p></li>
<li><strong>每个thread占1M物理内存<br />
      <br /></strong></p>
<p>在Win32编程中thread的1M stack空间是Reserve的，直到真正用时才占用物理内存；而在.net中，这1M空间直接被commit。</p>
<p>还好，可以在新建thread时指定stack size。不过这也比较危险，设小了怕不够。实际上，最好尽量避免创建thread——太多的thread要么导致CPU竞争和context switch，要么都block着浪费内存。建议是：能用ThreadPool就用ThreadPool。 </li>
</ol>
<p>累死了，写了这么多……Jeffrey还有一个更牛的课：.net threading。里面的东西更多……要不要再总结一下呢。。。<img alt="Thinking" src="http://messenger.msn.com/MMM2006-04-19_17.00/Resource/emoticons/72_72.gif" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2009/02/c%e5%92%8cclr%e7%9a%8415%e4%b8%aa%e7%bb%86%e8%8a%82/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>用c#从Outtlook 2007里读取email信息</title>
		<link>http://www.zhaoxiangpeng.com/2009/01/howto-access-emails-in-outlook-via-c/</link>
		<comments>http://www.zhaoxiangpeng.com/2009/01/howto-access-emails-in-outlook-via-c/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 03:04:51 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/%e7%94%a8c%e4%bb%8eouttlook-2007%e9%87%8c%e8%af%bb%e5%8f%96email%e4%bf%a1%e6%81%af.html</guid>
		<description><![CDATA[首先要添加对Microsoft.Office.Interop.Outlook的引用。 using Microsoft.Office.Interop.Outlook之后，操作Outlook的代码如下。 注意，代码中演示了如何取出特定文件夹，和取出inbox等特殊文件夹： Application myApp = new ApplicationClass(); NameSpace mapiNameSpace = myApp.GetNamespace("MAPI"); MAPIFolder folder; folder = myApp.Session.Folders["邮箱 - Xiangpeng Zhao"].Folders["Maillists"].Folders["Windows 7"]; //folder = mapiNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox); foreach (MailItem mail in folder.Items) { string subject = mail.Subject; string body = mail.Body; // this will trigger the security warning... string senderName = mail.SenderName; string senderEmail = mail.SenderEmailAddress; // [...]]]></description>
			<content:encoded><![CDATA[<p>首先要添加对Microsoft.Office.Interop.Outlook的引用。</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image-thumb.png" style="border-width: 0px; display: inline" title="image" alt="image" border="0" height="412" width="486" /></a></p>
<p>using Microsoft.Office.Interop.Outlook之后，操作Outlook的代码如下。</p>
<p>注意，代码中演示了如何取出特定文件夹，和取出inbox等特殊文件夹：</p>
<p style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text">
<p style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">Application myApp = <span style="color: #0000ff">new</span> ApplicationClass();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">NameSpace mapiNameSpace = myApp.GetNamespace(<span style="color: #006080">"MAPI"</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">MAPIFolder folder;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt"></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">folder = myApp.Session.Folders[<span style="color: #006080">"邮箱 - Xiangpeng Zhao"</span>].Folders[<span style="color: #006080">"Maillists"</span>].Folders[<span style="color: #006080">"Windows 7"</span>];</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt"><span style="color: #008000">//folder = mapiNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt"></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt"><span style="color: #0000ff">foreach</span> (MailItem mail <span style="color: #0000ff">in</span> folder.Items) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">    <span style="color: #0000ff">string</span> subject = mail.Subject;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">    <span style="color: #0000ff">string</span> body = mail.Body; <span style="color: #008000">// this will trigger the security warning...</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">    <span style="color: #0000ff">string</span> senderName = mail.SenderName;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">    <span style="color: #0000ff">string</span> senderEmail = mail.SenderEmailAddress; <span style="color: #008000">// security warning</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt">}</pre>
<h2>如何跳过讨厌的Outtlook安全警告！</h2>
<p>运行上面的代码，Outlook就会弹出一个对话框：“A program is trying to access e-mail address information stored in Outlook…”必须按下“Allow”才能访问email信息。怎么跳过这个对话框？</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image1.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image-thumb1.png" style="border-width: 0px; display: inline" title="image" alt="image" border="0" height="196" width="375" /></a></p>
<p>这个问题的解决方法比我想像得复杂。针对不同的场景，可能需要不同的方案。<a href="http://www.outlookcode.com/article.aspx?id=52" target="_blank">Outlook "Object Model Guard" Security Issues for Developers</a>是一篇非常好的文章，介绍了各种方法。</p>
<p>因为我只想读取我自己机器上的email，所以就装了个免费的Outlook插件<a href="http://www.mapilab.com/outlook/security/" target="_blank">Advanced Security for Outlook</a>，它可以自动替换Outlook的安全警告对话框，取而代之的是一个允许自定义信任程序的对话框：</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image2.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2009/01/image-thumb2.png" style="border-width: 0px; display: inline" title="image" alt="image" border="0" height="443" width="404" /></a></p>
<p>这确实很方便。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2009/01/howto-access-emails-in-outlook-via-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server 2008 Reporting Service使用技巧</title>
		<link>http://www.zhaoxiangpeng.com/2008/12/sql-server-2008-reporting-service-tips/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/12/sql-server-2008-reporting-service-tips/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 15:19:44 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[计算机技术]]></category>
		<category><![CDATA[ssrs]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/sql-server-2008-reporting-service%e4%bd%bf%e7%94%a8%e6%8a%80%e5%b7%a7.html</guid>
		<description><![CDATA[SSRS用来做报表很方便，据说比Crystal Reports好用。简单的说，你的报表数据来自SQL语句，然后就可以在类似Excel的环境中画图了。 说是这么说，实际做起来还是会遇到很多小麻烦。下面是总结的一些技巧： 改变图表上字体大小（如X轴、Y轴上的数字）： 先把LabelsAutoFitDisabled属性设为True ，然后再设置字体大小 Data Label显示设置： 在Series的SmartLabels里面有一些有用的选项。AllowOutsidePlotArea设为True比较好。 自定义Legend标题： 要右键选Series的属性，不是Legend的属性 Pie chart显示百分比： 在Report properties - code中加入如下代码： Public Function GetLabel(ByVal currentValue As Integer, ByVal totalValue As Integer) As String If currentValue / totalValue &#60; 0 Then '表示百分比小于1的不显示出来 Return " " Else Return Format(currentValue / totalValue, "P1") End If End Function 然后设置data label表达式：=Code.GetLabel(Count(Fields!IssueID.Value), Count(Fields!IssueID.Value, "Issues")) Pie [...]]]></description>
			<content:encoded><![CDATA[<p>SSRS用来做报表很方便，据说比Crystal Reports好用。简单的说，你的报表数据来自SQL语句，然后就可以在类似Excel的环境中画图了。</p>
<p>说是这么说，实际做起来还是会遇到很多小麻烦。下面是总结的一些技巧：</p>
<ol>
<li>
<h3>改变图表上字体大小（如X轴、Y轴上的数字）：</h3>
<p>先把LabelsAutoFitDisabled属性设为True ，然后再设置字体大小</li>
<li>
<h3>Data Label显示设置：</h3>
<p>在Series的SmartLabels里面有一些有用的选项。AllowOutsidePlotArea设为True比较好。</li>
<li>
<h3>自定义Legend标题：</h3>
<p>要右键选Series的属性，不是Legend的属性</li>
<li>
<h3>Pie chart显示百分比：</h3>
<p>在Report properties - code中加入如下代码：</p>
<p>Public Function GetLabel(ByVal currentValue As Integer, ByVal totalValue As Integer) As String</p>
<p>If currentValue / totalValue &lt; 0 Then '表示百分比小于1的不显示出来</p>
<p>Return " "</p>
<p>Else</p>
<p>Return Format(currentValue / totalValue, "P1")</p>
<p>End If</p>
<p>End Function</p>
<p>然后设置data label表达式：=Code.GetLabel(Count(Fields!IssueID.Value), Count(Fields!IssueID.Value, "Issues"))</li>
<li>
<h3>Pie chart排序</h3>
<p>右键点一个Category，在Category Group Properties中设置Sort表达式即可</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image001.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image001-thumb.png" style="border-width: 0px" alt="clip_image001" border="0" height="363" width="601" /></a></li>
<li>
<h3>在Pie chart饼图外侧显示DataLabel：</h3>
<p>设置Series的CustomAttributes，PieLabelStyle=Outside</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image002.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image002-thumb.png" style="border-width: 0px" alt="clip_image002" border="0" height="692" width="680" /></a></p>
<p>注意：参考AdventureWorks示例，有一个很好的饼图。（google上搜到的都是过时的东西）</li>
<li>
<h3>Asp.net中使用ReportViewer控件：</h3>
<p>必须在IIS的Handler Mappings中新建一个Managed Handler才能正常显示。 可以google搜索Reserved.ReportViewerWebControl.axd。</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image003.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image003-thumb.png" style="border-width: 0px" alt="clip_image003" border="0" height="551" width="580" /></a></p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image004.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image004-thumb.png" style="border-width: 0px" alt="clip_image004" border="0" height="667" width="815" /></a></p>
<p>另一个解决方法：据说配置下web.config文件也可以搞定：</p>
<p>&lt;httpHandlers&gt;</p>
<p>    &lt;add path="Reserved.ReportViewerWebControl.axd" verb="*"</p>
<p>         type="Microsoft.Reporting.WebForms.HttpHandler,</p>
<p>               Microsoft.ReportViewer.WebForms,</p>
<p>               Version=8.0.0.0, Culture=neutral,</p>
<p>               PublicKeyToken=?????????????"</p>
<p>         validate="false" /&gt;</p>
<p>&lt;/httpHandlers&gt;</p>
<p><a href="http://www.knowsky.com/340782.html">http://www.knowsky.com/340782.html</a></li>
<li>
<h3>ReportViewer控件：</h3>
<p>可以设置ZoomMode属性为PageWidth，这样可以自动放缩。</p>
<p>图表放大时会失真,因为不是矢量图。建议把原始报表拉大一些，在页面中留一个小点的空，默认ZoomMode=PageWidth，用户选择100%就可以放大。</p>
<p>所有的toolbar按钮都可以选择显示或关闭，设置ShowXXX属性即可。</li>
<li>
<h3>其他：</h3>
<p>对报表修改之后要及时Deploy，才能看到效果。可以在VS的configuration manager里面设置，debug时自动deploy，比较方便。这个默认是没有打开的，如下图所示，建议把Deploy的对勾打上。</p>
<p><a href="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image005.png"><img src="http://www.zhaoxiangpeng.com/wp-content/uploads/12/1224/2008/12/clip-image005-thumb.png" style="border-width: 0px" alt="clip_image005" border="0" height="297" width="812" /></a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/12/sql-server-2008-reporting-service-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>LINQ学习笔记</title>
		<link>http://www.zhaoxiangpeng.com/2008/12/linq-study-notes/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/12/linq-study-notes/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 08:11:01 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[计算机技术]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/linq-study-notes.html</guid>
		<description><![CDATA[什么是LINQ LINQ是C# 3.0的新功能，可以用统一的的语法（类似sql、或者是函数式语言）访问各种数据，包括数据库、XML、对象。 Anders Hejlsberg说LINQ是"It's about turning query set operations and transforms into first-class concepts of the language" (http://channel9.msdn.com/showpost.aspx?postid=114680)。我的感受是：LINQ可以取代SQL，成为一种统一Database、XML世界的查询语言。 举个例子： var bycity = from p in db.Products join o in db.Orders on p.productID equals o.productID   where o.ShipToCity == "Beijing" select new {o.orderID, p.productName}; foreach (d in bycity) ... //或者GridView1.DataSource = bycity 这里的db.doctors可以是数据库DataSet，可以是个xml文件，也可以是个List&#60;T&#62;。 所有的新关键字，比如var, from, [...]]]></description>
			<content:encoded><![CDATA[<h3>什么是LINQ</h3>
<p>LINQ是C# 3.0的新功能，可以用统一的的语法（类似sql、或者是函数式语言）访问各种数据，包括数据库、XML、对象。</p>
<p>Anders Hejlsberg说LINQ是"It's about turning query set  operations and transforms into first-class concepts of the language" (<a href="http://channel9.msdn.com/showpost.aspx?postid=114680" class="docLink" target="_blank">http://channel9.msdn.com/showpost.aspx?postid=114680</a>)。我的感受是：LINQ可以取代SQL，成为一种统一Database、XML世界的查询语言。</p>
<p>举个例子：</p>
<pre name="code" class="c-sharp:nogutter">
var bycity = from p in db.Products
             join o in db.Orders
             on p.productID equals o.productID
             where o.ShipToCity == "Beijing"
             select new {o.orderID, p.productName};
foreach (d in bycity) ...
//或者GridView1.DataSource = bycity</pre>
<p>这里的db.doctors可以是数据库DataSet，可以是个xml文件，也可以是个List&lt;T&gt;。</p>
<p>所有的新关键字，比如var, from, group, select...都是syntactic sugar。编译器会自动把它翻译成基于Lambda表达式的代码，最后翻译成.net 2.0的程序。var的类型是type inference推断出来的，是强类型的，不等于object；select相当于函数式语言中的Map，当然也支持函数式语言中的Reduce（叫做Aggregate）；函数式语言用到的Lambda表达式其实很容易用函数指针delegate实现；最后生成的是一个匿名类型(anonymous type）。</p>
<p>推荐这本小书：<a href="http://www.baidu.com/s?wd=LINQ%3A+The+Future+of+Data+Access+in+C%23+3.0&amp;cl=3" target="_blank">LINQ: The Future of Data Access in C# 3.0</a>，只要两小时就看完了。了解一点原理后再用LINQ就方便多了。</p>
<h3>LINQ和ASP.net</h3>
<p>对ASP.net程序员而言，LINQ主要的应用是用它代替SQL访问数据库。除了不用拼字符串了，一个好处是，LINQ是强类型的，所以用起来更安全。我可以这样写：</p>
<pre name="code" class="c-sharp:nogutter">
var query = db.Orders.Where(o=&gt;o.Description.Contains(txtDescription.Text));
// Contains会被翻译成SQL的LIKE
DateTime sinceDate = DateTime.Parse(txtSinceDate.Text);
query = query.Where(o=&gt;o.ShipDate &gt; date);
// o.ShipDate也是DateTime类型的，所以可以直接比较</pre>
<p>Lambda表达式很好用的。<br />
比较麻烦的是，现在有两套数据库访问框架：一个是LINQ to SQL，一个是LINQ to Entity。在用LINQ前，又要花点时间考虑用哪个框架好。</p>
<p>二者对于各种基本CRUD操作有很好的支持。LINQ to SQL可以理解为SQL的替代品，基本上跟SQL能一一对应起来；而LINQ to Entity是2008年8月才推出的，是一个更强大的ORM框架，对多对多关系的支持更好。</p>
<p>举个例子：假设一个表linkProductOrder里只有两列，productID和orderID，用于表达product和order的联系。在LINQ to SQL中这个表会被映射到一个类linkProductOrder，还需要自己写join；而LINQ to Entity中就不会出现这个类，直接用product.Orders和order.Products就可以实现互相访问，完全消除了写join的必要。</p>
<p>我的体会是：LINQ to Entity目前还不够稳定，还是LINQ to SQL保险。用ORM框架的一个问题是，刚开始用时会有lose control的感觉，出了问题完全不知道怎么回事，不像SQL，模型很简单清晰，一个query下去肯定不会出毛病。</p>
<p>我用LINQ to Entity时遇到了几个问题，比如数据库改变后没法重新刷新对象模型，只能删掉对象模型文件重建；还有一次不知道为何新建的对象存不进数据库，这时调试起来非常麻烦。对于复杂的含有多个join的查询，我一般都会先用sql server测试一下，再写成代码；LINQ to Entity不用写join是省了一点事，但是这样反而要在脑子里维护两种模型翻过来译过去。相比之下LINQ to SQL就没出过什么问题。</p>
<p>希望等LINQ to Entity的下个版本出来之后，这种问题会少一些。</p>
<p>总结：不是做广告，C#真的很好很强大。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/12/linq-study-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>微软PDC大会和Channel 9</title>
		<link>http://www.zhaoxiangpeng.com/2008/11/microsoft-pdc-and-channel9/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/11/microsoft-pdc-and-channel9/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 16:45:06 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/microsoft-pdc-and-channel9.html</guid>
		<description><![CDATA[微软PDC大会展示了微软最新的技术，比如Windows 7，Windows Azure，而且门票可是超级贵的。最近才知道PDC的全部视频都是可以随便观看和下载的，就在微软MSDN的channel 9上。 MSDN上有很多东西——一个缺点就是太多。Channel 9是developer的频道，有很多视频，比如对Mark Russinovich的采访，讲到了Windows 7 kernel的一些改进。比如内核几个频繁使用的全局lock被细化，提高了多CPU时的performance； 启动时并行装载驱动程序，提高了boot performance；等等。虽然没有字幕，不过总的来说还算好懂。 最后很土的说，我真的没想到微软technical fellow（请对比IEEE fellow，ACM fellow的概念），sysinternal的创始人，在加入微软前凭着debugger就写出Windows Internals一书的Mark大神竟然那么年轻那么帅……在镜头面前甚至有一点腼腆……我一直以为他应该是个留着小胡子戴着眼镜老大叔的形象……]]></description>
			<content:encoded><![CDATA[<p>微软<a href="http://www.microsoftpdc.com">PDC大会</a>展示了微软最新的技术，比如Windows 7，Windows Azure，而且门票可是超级贵的。最近才知道PDC的全部视频都是可以随便观看和下载的，就在微软MSDN的channel 9上。</p>
<p>MSDN上有很多东西——一个缺点就是太多。<a href="http://channel9.msdn.com/">Channel 9</a>是developer的频道，有很多视频，比如<a href="http://channel9.msdn.com/shows/Going+Deep/Mark-Russinovich-Inside-Windows-7/">对Mark Russinovich的采访</a>，讲到了Windows 7 kernel的一些改进。比如内核几个频繁使用的全局lock被细化，提高了多CPU时的performance； 启动时并行装载驱动程序，提高了boot performance；等等。虽然没有字幕，不过总的来说还算好懂。</p>
<p>最后很土的说，我真的没想到微软technical fellow（请对比IEEE fellow，ACM fellow的概念），sysinternal的创始人，在加入微软前凭着debugger就写出Windows Internals一书的Mark大神竟然那么年轻那么帅……在镜头面前甚至有一点腼腆……我一直以为他应该是个留着小胡子戴着眼镜老大叔的形象……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/11/microsoft-pdc-and-channel9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用VSTO 2008写一个Outlook 2007插件</title>
		<link>http://www.zhaoxiangpeng.com/2008/09/howto-write-an-outlook-2007-addin-with-vsto-2008/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/09/howto-write-an-outlook-2007-addin-with-vsto-2008/#comments</comments>
		<pubDate>Mon, 08 Sep 2008 07:54:15 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[VSTO Outlook .Net]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/%e7%94%a8vsto%e5%86%99%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84outlook%e6%8f%92%e4%bb%b6.html</guid>
		<description><![CDATA[VSTO是微软的Office开发框架，基于.Net。跟以前的VBA宏相比，功能更强，优点很多，而且可以在Visual Studio里面用。我用VSTO做了一个Outlook插件(Addin)，模拟了Gmail的“存档”按钮。 为什么做这个？ 我喜欢Gmail的“存档(Archive)”按钮，它的功能很简单，就是把选中的邮件（一般是已经看过的邮件）移动到一个叫“Archive”的文件夹里。这样做的好处是可以保持收件箱(Inbox)里的邮件比较少（留下的都是要用的），看起来比较干净，而且载入的速度也快（以前我的Outlook收件箱里有5000封信，每次打开都很慢）。 虽然Outlook也很强大，虽然我也可以建一个“Archive”文件夹，把看过的email用鼠标拖拽过去，但这其实很麻烦，稍不留神就丢到错误的文件夹里了。所以我就花了些时间做了这个小程序。 实现 1. 首先在VS 2008里建一个Outlook 2007 Addin工程，在ThisAddIn类中加了几个成员变量： private Office.CommandBar archiveToolBar; private Office.CommandBarButton archiveEmailButton; private Outlook.Explorers selectExplorers; private Outlook.MAPIFolder inBox; private const string ARCHIVE_FOLDER_NAME = "Archived emails"; 2. 加一个Toolbar，放一个"Archive"按钮进去。 private void ThisAddIn_Startup(object sender, System.EventArgs e) { // Get inbox reference inBox = this.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); // Add toolbar selectExplorers = this.Application.Explorers; selectExplorers.NewExplorer += new [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.csdn.net/v_jzho/archive/2007/09/29/1806904.aspx" target="_blank">VSTO</a>是微软的Office开发框架，基于.Net。跟以前的VBA宏相比，功能更强，优点很多，而且可以在Visual Studio里面用。我用VSTO做了一个Outlook插件(Addin)，模拟了Gmail的“存档”按钮。</p>
<p><strong>为什么做这个？</strong></p>
<p>我喜欢Gmail的“存档(Archive)”按钮，它的功能很简单，就是把选中的邮件（一般是已经看过的邮件）移动到一个叫“Archive”的文件夹里。这样做的好处是可以保持收件箱(Inbox)里的邮件比较少（留下的都是要用的），看起来比较干净，而且载入的速度也快（以前我的Outlook收件箱里有5000封信，每次打开都很慢）。</p>
<p>虽然Outlook也很强大，虽然我也可以建一个“Archive”文件夹，把看过的email用鼠标拖拽过去，但这其实很麻烦，稍不留神就丢到错误的文件夹里了。所以我就花了些时间做了这个小程序。</p>
<p><strong>实现</strong></p>
<p>1. 首先在VS 2008里建一个Outlook 2007 Addin工程，在ThisAddIn类中加了几个成员变量：</p>
<pre name="code" class="c-sharp:nogutter">
        private Office.CommandBar archiveToolBar;
        private Office.CommandBarButton archiveEmailButton;
        private Outlook.Explorers selectExplorers;
        private Outlook.MAPIFolder inBox;
        private const string ARCHIVE_FOLDER_NAME = "Archived emails";</pre>
<p>2. 加一个Toolbar，放一个"Archive"按钮进去。</p>
<pre name="code" class="c-sharp:nogutter">
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            // Get inbox reference
            inBox = this.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            // Add toolbar
            selectExplorers = this.Application.Explorers;
            selectExplorers.NewExplorer += new Outlook
                .ExplorersEvents_NewExplorerEventHandler(newExplorer_Event);
            AddToolbar();
        }
        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }
        private void newExplorer_Event(Outlook.Explorer new_Explorer)
        {
            ((Outlook._Explorer)new_Explorer).Activate();
            archiveToolBar = null;
            AddToolbar();
        }
        private void AddToolbar()
        {
            if (archiveToolBar == null)
            {
                Office.CommandBars cmdBars =
                    this.Application.ActiveExplorer().CommandBars;
                archiveToolBar = cmdBars.Add("Archive Email",
                    Office.MsoBarPosition.msoBarTop, false, true);
            }
            try
            {
                Office.CommandBarButton button_1 =
                    (Office.CommandBarButton)archiveToolBar.Controls
                    .Add(1, missing, missing, missing, missing);
                button_1.Style = Office
                    .MsoButtonStyle.msoButtonCaption;
                button_1.Caption = "Arch&amp;ive";
                button_1.Tag = "Archive selected email";
                if (this.archiveEmailButton == null)
                {
                    this.archiveEmailButton = button_1;
                    archiveEmailButton.Click += new Office.
                        _CommandBarButtonEvents_ClickEventHandler
                        (ArchiveButtonClick);
                }
                archiveToolBar.Visible = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }</pre>
<p>3. 响应Button click事件，代码如下：</p>
<pre name="code" class="c-sharp:nogutter">
        private void ArchiveButtonClick(Office.CommandBarButton ctrl, ref bool cancel)
        {
            // Make sure we are at "inBox"
            Outlook.Explorer activeExplorer = this.Application.Explorers.Application.ActiveExplorer();
            if (activeExplorer.CurrentFolder.FullFolderPath != inBox.FullFolderPath)
            {
                MessageBox.Show("Please do archive operation in " + inBox.Name);
                return;
            }
            // Get "archive" folder
            Outlook.MAPIFolder archiveFolder = null;
            try
            {
                archiveFolder = inBox.Folders[ARCHIVE_FOLDER_NAME]; // ARCHIVE_FOLDER_NAME is a const string I defined.
            }
            catch (Exception ex)
            {
                inBox.Folders.Add(ARCHIVE_FOLDER_NAME, missing);  // Create a new folder if not exist.
                archiveFolder = inBox.Folders[ARCHIVE_FOLDER_NAME];
            }
            // move selected items to "archive" folder
            Outlook.Explorer activeExplorer = this.Application.Explorers.Application.ActiveExplorer();
            foreach (object selectedItem in activeExplorer.Selection)
            {
                try
                {
                    Outlook.MailItem moveMail = selectedItem as Outlook.MailItem;
                    if (moveMail != null) // TODO: &amp;&amp; movemail is in "inBox"
                    {
                        //string titleSubject = (string)moveMail.Subject;
                        //if (titleSubject.IndexOf("Test") &gt; 0)
                        moveMail.Move(archiveFolder);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }</pre>
<p>在自己的机器上编译运行这个小程序后，Outlook就会自动加入这个插件，以后每次启动Outlook都会运行。<strike>不过，要想做个安装包在别人机器上运行，可就麻烦了。这里有个<a href="http://blog.csdn.net/v_jzho/archive/2007/12/19/1954454.aspx">“简单”部署教程</a>。</strike> Update: VSTO 2008里，部署超级简单！</p>
<p><strong>部署</strong></p>
<p>VSTO 2008新增了ClickOnce功能。 只要右键点项目，选“publish”就可以生成安装文件，超级简单！<a href="http://blogs.msdn.com/pstubbs/archive/2007/05/17/vsto-my-favorite-feature-clickonce-deployment.aspx">这篇文章</a>里有几个截图。</p>
<p><strong>总结</strong></p>
<p>VSTO挺好用，什么时候给IE写插件也能用.Net就好了。MS Office在不断进步，Open Office，WPS Office貌似永远都赶不上啊……</p>
<p><strong>资料</strong></p>
<p><a href="http://www.objectarx.net/downloads/VSTO%20for%20Mere%20Mortals%20.rar">VSTO for Mere Mortals</a>，讲VSTO的一本入门书，适合入门，不过不详细。</p>
<p><a href="http://msdn.microsoft.com/en-us/office/aa905533.aspx" target="_blank">MSDN</a>里有好多how to小例子，值得看看。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/09/howto-write-an-outlook-2007-addin-with-vsto-2008/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>如何用Visual Studio 2008和Sql Server 2005 Express写一个数据库程序</title>
		<link>http://www.zhaoxiangpeng.com/2008/08/howto_write_a_database_program_with_visual_studio_2008_and_sql_server_2005_express/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/08/howto_write_a_database_program_with_visual_studio_2008_and_sql_server_2005_express/#comments</comments>
		<pubDate>Sat, 30 Aug 2008 01:55:29 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[walkthrough]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/%e5%a6%82%e4%bd%95%e7%94%a8visual-studio-2008%e5%92%8csql-server-2005-express%e5%86%99%e4%b8%80%e4%b8%aa%e6%95%b0%e6%8d%ae%e5%ba%93%e7%a8%8b%e5%ba%8f.html</guid>
		<description><![CDATA[装了Vista，SQL Server 2000不能用了。那就用Visual Studio自带的sql server express试试吧。没想到还挺难上手的，配置很麻烦。花了一晚上时间，终于配好了，下面是过程记录。 关键字：教程，配置，例子 一、安装 装完Visual studio和所带的sql server 2005 express之后，还要装如下的东西： 为了便于管理，你还需要去下一个管理器SSMSEE： http://download.microsoft.com/download/1/1/0/110d908f-c445-4523-b939-220c7d135f3d/SQLServer2005_SSMSEE.msi （注意：在vista下一定要run as administrator！步骤是，先启动一个admin权限的cmd窗口，再执行.msi程序，否则安装失败） Northwind数据库示例：（从Sql Server 2005之后，northwind就“消失”了，必须自己下载） http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&#38;displaylang=en 安装.msi文件后，到C:\SQL Server 2000 Sample Databases下执行相应脚本即可。 SQL Server 2005 Books Online文档：（153MB） http://technet.microsoft.com/en-us/sqlserver/bb428874.aspx 测试一下：在vs 2008的cmd prompt下执行sqlcmd命令，启动文本界面。 （注意大小写！-S，不是-s） D:\Program Files\Microsoft Visual Studio 9.0\VC&#62;sqlcmd -S .\sqlexpress -E 1&#62; use northwind 2&#62; go Changed database context to 'Northwind'. [...]]]></description>
			<content:encoded><![CDATA[<p>装了Vista，SQL Server 2000不能用了。那就用Visual Studio自带的sql server express试试吧。没想到还挺难上手的，配置很麻烦。花了一晚上时间，终于配好了，下面是过程记录。</p>
<p>关键字：教程，配置，例子</p>
<p>一、安装</p>
<p>装完Visual studio和所带的sql server 2005 express之后，还要装如下的东西：</p>
<p>为了便于管理，你还需要去下一个管理器SSMSEE：<br />
<a href="http://download.microsoft.com/download/1/1/0/110d908f-c445-4523-b939-220c7d135f3d/SQLServer2005_SSMSEE.msi" target="_blank">http://download.microsoft.com/download/1/1/0/110d908f-c445-4523-b939-220c7d135f3d/SQLServer2005_SSMSEE.msi</a><br />
（注意：在vista下一定要run as administrator！步骤是，先启动一个admin权限的cmd窗口，再执行.msi程序，否则安装失败）</p>
<p>Northwind数据库示例：（从Sql Server 2005之后，northwind就“消失”了，必须自己下载）<br />
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en" target="_blank">http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en</a><br />
安装.msi文件后，到C:\SQL Server 2000 Sample Databases下执行相应脚本即可。</p>
<p>SQL Server 2005 Books Online文档：（153MB）<br />
<a href="http://technet.microsoft.com/en-us/sqlserver/bb428874.aspx" target="_blank">http://technet.microsoft.com/en-us/sqlserver/bb428874.aspx</a></p>
<p>测试一下：在vs 2008的cmd prompt下执行sqlcmd命令，启动文本界面。<br />
（注意大小写！-S，不是-s）</p>
<p>D:\Program Files\Microsoft Visual Studio 9.0\VC&gt;sqlcmd -S .\sqlexpress -E<br />
1&gt; use northwind<br />
2&gt; go<br />
Changed database context to 'Northwind'.<br />
1&gt; select * from employees<br />
2&gt; go</p>
<p>最后，修改sql server express的配置：</p>
<p>1、开启sql2005远程连接功能：<br />
配置工具-&gt;SQL Server 外围应用配置器-&gt;服务和连接的外围应用配置器-&gt;打开MSSQLSERVER节点下的Database Engine 节点,先择"远程连接",接下建议选择"同时使用TCP/IP和named pipes",确定后,重启数据库服务.</p>
<p>（不开的话，很可能Visual studio连不上数据库。）</p>
<p>2、登陆改为混合模式:<br />
打开management studio管理器-&gt;以windows方式连接并进入数据库-&gt;右键点击你的数据服务器-&gt;属性-&gt;security&gt;选中Sql server and windows Authentication</p>
<p>3、新建Sql server方式的用户名和密码:<br />
management studio管理器-&gt;security-&gt;右键点击logins-&gt;new login...-&gt;选中sql server authentication-&gt;设置login name 和password（confirm password）<br />
最好去掉“enforce password expiration”前的小钩，否则每次登陆都要修改密码。<br />
/*<br />
management studio管理器-&gt;windows Authentication&gt;new query&gt;sp_password null,'sa123456','sa'<br />
这样就设置了一个用户名为sa ,密码为:sa123456的用户,下次在登陆时,可以用Sql server方式,<br />
用户名为sa ,密码为:sa123456的用户进数据库了.<br />
*/</p>
<p>4、做完上面三步后,这样写连接字符串就可以顺利进入数据库了(server=.\\sqlexpress;uid=用户名;pwd=密码;database=master")。</p>
<p>5、在configuration manager中打开sql server browser服务。否则visual studio无法自动发现数据库名。</p>
<p>注意，server不能写=local！必须用“.”</p>
<p>二、写一个数据库程序：</p>
<p>1、在visual studio中Add connection，有两种方式：</p>
<p>* 文件方式<br />
可以选Sql server database file，然后在<br />
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data下面打开northwind.mdf<br />
（注意：vista中，要以admin身份运行visual studio！否则没有权限打开数据库。）</p>
<p>* 数据库方式<br />
用sql server的标准data source模式连接数据库，一开始不知道为啥总是看不到数据库列表。后来发现：必须打开sql server browser服务。该服务默认是关闭的。</p>
<p>2、写程序</p>
<p>最简单的方法，只要把某个data table拖到form上松开就可以了，VS会自动帮你配好datasource, dataset, tableadapter等一大堆控件。参考这个<a href="http://go.microsoft.com/fwlink/?LinkId=100478" target="_blank">视频教程</a>（MSDN上有很多类似的视频小教程，很不错）。</p>
<p>或者参考Visual Studio自带的例子程序，在\Program Files\Microsoft Visual Studio 9.0\Samples\1033目录下，是一个zip文件。（不好找啊！）这里面的例子都非常好。</p>
<p>最后，<a href="http://books.google.com/books?id=hxMiygsvOh8C&amp;pg=PA252&amp;lpg=PA252&amp;dq=ssmse+northwind&amp;source=web&amp;ots=ueUKeEmv_6&amp;sig=GyE9YjQyK6Nlt3Udixi1fgX_suI&amp;hl=en&amp;sa=X&amp;oi=book_result&amp;resnum=3&amp;ct=result#PPA14,M1" target="_blank">Beginning C# 2005 Databases：From Novice to Professional</a> 是一本不错的书，特别是前两章。《Beginning C# 2008 Databases》似乎还不如2005讲的好。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/08/howto_write_a_database_program_with_visual_studio_2008_and_sql_server_2005_express/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于GPU的一些简单概念</title>
		<link>http://www.zhaoxiangpeng.com/2008/08/some_concepts_about_gpu/</link>
		<comments>http://www.zhaoxiangpeng.com/2008/08/some_concepts_about_gpu/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 08:41:18 +0000</pubDate>
		<dc:creator>Xiangpeng</dc:creator>
				<category><![CDATA[Windows编程]]></category>

		<guid isPermaLink="false">http://www.zhaoxiangpeng.com/articles/%e5%85%b3%e4%ba%8egpu%e7%9a%84%e4%b8%80%e4%ba%9b%e7%ae%80%e5%8d%95%e6%a6%82%e5%bf%b5.html</guid>
		<description><![CDATA[最近看了一些Windows graphics的东西，顺便了解了一下GPU，学了几个显卡设置里常见的单词。Windows vista使用的半透明桌面效果，还有Win+Tab的切换效果都是基于显卡3D加速的。 shader: 不太好翻译，程序纹理着色器，或者着色程序，是一段可以改变像素、顶点和几何学特征的小程序。特点是可编程，原先的显卡里只能调用固定的函数。 vertex shader：把3D坐标变成屏幕上2D坐标（和Z-buffer） geometry shader：不清楚，一次处理一批vertex？（DirectX 10加入） rasterization：光栅化，把一个2D坐标换算成一个pixel pixel shader：对像素上色，考虑texture、光线等因素。（高度并行化，因为每个pixel都是独立的） unified shader：有利于平衡使用。一个GPU可能有128个处理器，有了unified shader后，某个时刻可以让90%的处理器做vertex shader，10%的做pixel shader；或者反之。（DirectX 10加入） 工作流程： 因为shader是可编程的，所以可以把某些CPU的计算交给GPU做，也就是所谓的general purpose GPU，这是比较时髦的技术了。 现在的GPU里有很多的处理器，也有调度器，有优先级的概念。但是还不支持page table，因此显存里放的东西都是连续的（这意味着显存里可能会有洞，浪费空间）；也不支持抢占。可以预计将来的GPU还会有更多改进。 参考文章： http://diy.pconline.com.cn/graphics/reviews/0708/1076067_1.html http://en.wikipedia.org/wiki/Shader  How GPUs work, IEEE Computer]]></description>
			<content:encoded><![CDATA[<p>最近看了一些Windows graphics的东西，顺便了解了一下GPU，学了几个显卡设置里常见的单词。Windows vista使用的半透明桌面效果，还有Win+Tab的切换效果都是基于显卡3D加速的。</p>
<p>shader: 不太好翻译，<font style="font-size: 14px">程序纹理着色器</font>，或者着色程序，是一段可以改变像素、顶点和几何学特征的小程序。特点是可编程，原先的显卡里只能调用固定的函数。</p>
<p>vertex shader：把3D坐标变成屏幕上2D坐标（和Z-buffer）</p>
<p>geometry shader：不清楚，一次处理一批vertex？（DirectX 10加入）</p>
<p>rasterization：光栅化，把一个2D坐标换算成一个pixel</p>
<p>pixel shader：对像素上色，考虑texture、光线等因素。（高度并行化，因为每个pixel都是独立的）</p>
<p>unified shader：有利于平衡使用。一个GPU可能有128个处理器，有了unified shader后，某个时刻可以让90%的处理器做vertex shader，10%的做pixel shader；或者反之。（DirectX 10加入）</p>
<p>工作流程：</p>
<p><img src="http://www.computer.org/portal/cms_docs_computer/computer/homepage/Feb07/r2how03.jpg" alt="figure 3 image" width="306" height="192" /></p>
<p>因为shader是可编程的，所以可以把某些CPU的计算交给GPU做，也就是所谓的general purpose GPU，这是比较时髦的技术了。</p>
<p>现在的GPU里有很多的处理器，也有调度器，有优先级的概念。但是还不支持page table，因此显存里放的东西都是连续的（这意味着显存里可能会有洞，浪费空间）；也不支持抢占。可以预计将来的GPU还会有更多改进。</p>
<p>参考文章：</p>
<p><a href="http://diy.pconline.com.cn/graphics/reviews/0708/1076067_1.html" target="_blank">http://diy.pconline.com.cn/graphics/reviews/0708/1076067_1.html</a></p>
<p><a href="http://en.wikipedia.org/wiki/Shader" target="_blank">http://en.wikipedia.org/wiki/Shader </a></p>
<p><a href="http://www.computer.org/portal/site/computer/menuitem.5d61c1d591162e4b0ef1bd108bcd45f3/index.jsp?&amp;pName=computer_level1_article&amp;TheCat=1055&amp;path=computer/homepage/Feb07&amp;file=howthings.xml&amp;xsl=article.xsl&amp;;jsessionid=G10s8pkpkP1K0Lk07bXx5dR0mXLSj8hXdnLDN5Kjj5GZTJtTTLZ0!1592783441" target="_blank"> How GPUs work, IEEE Computer</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhaoxiangpeng.com/2008/08/some_concepts_about_gpu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

