<?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>浏忙大爆炸 &#187; Windows</title>
	<atom:link href="http://blog.waterlin.org/articles/tag/windows/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.waterlin.org</link>
	<description>源于理工科男的烂笔头情结</description>
	<lastBuildDate>Fri, 03 Feb 2012 08:35:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>C# 引用 C++ 链接库</title>
		<link>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html</link>
		<comments>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 08:35:37 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html</guid>
		<description><![CDATA[最近在尝试用新的方式来写一个新的 Windows 客户端，当作练习。主要是用 C++ 把复杂的算法写成链接库，然后用 C# 做界面前端，从 C# 调用用 C++ 写好的非托管代码。 尝试通过这种方式解决两个问题： C# 的计算效率问题，虽然从各种资料来看，好像 C# 的托管代码对效率的影响并没有想象的夸张，但不管怎么样，有些东西用 C++ 写就是方便一些； 用 C++ 可以方便地链接现有的代码库、算法库。 其实，这种架构可以看成是一种 C/S 架构的简化版，但是省去了 Socket 通信这一层。 我采用的是最简单的 P/Invokes 的方式来实现 C# 调用 C++ 链接库，详细的教程，可以看一下 Using dumpbin.exe as an Aid for Declaring P/Invokes 这篇文章。 这里先简单说说两点和代码无关的问题 如果 C++ 链接库的计算很耗时，一定要在 C# 客户端里开一个线程来处理，否则容易造成死机，这和 MFC 之类的原理一样。 为了测试你从 C# 链接 C++ 链接库是否成功，可以用 [...]]]></description>
			<content:encoded><![CDATA[<p>最近在尝试用新的方式来写一个新的 Windows 客户端，当作练习。主要是<a href="http://cn.waterlin.org/Microsoft/visual-studio-dll-project.html">用 C++ 把复杂的算法写成链接库</a>，然后用 C# 做界面前端，从 C# 调用用 C++ 写好的非托管代码。</p>
<p>尝试通过这种方式解决两个问题：</p>
<ol>
<li>C# 的计算效率问题，虽然从各种资料来看，好像 C# 的托管代码对效率的影响并没有想象的夸张，但不管怎么样，有些东西用 C++ 写就是方便一些；</li>
<li>用 C++ 可以方便地链接现有的代码库、算法库。</li>
</ol>
<p>其实，这种架构可以看成是一种 C/S 架构的简化版，但是省去了 Socket 通信这一层。</p>
<p>我采用的是最简单的 P/Invokes 的方式来实现 C# 调用 C++ 链接库，详细的教程，可以看一下 <a href="http://msdn.microsoft.com/en-us/library/aa446532.aspx">Using dumpbin.exe as an Aid for Declaring P/Invokes</a> 这篇文章。</p>
<div class="outline-3">
<h3 id="sec-1.1">这里先简单说说两点和代码无关的问题</h3>
<div class="outline-text-3">
<ol>
<li>如果 C++ 链接库的计算很耗时，一定要在 C# 客户端里开一个线程来处理，否则容易造成死机，这和 MFC 之类的原理一样。</li>
<li>为了测试你从 C# 链接 C++ 链接库是否成功，可以用 C# 新建一个命令行工程专门测试，用这种方式来测试更加直接与有效。</li>
</ol></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.2">再谈几点有关技术实现细节的问题，也是我折腾了很久的困惑之处</h3>
<div class="outline-text-3">
<div class="outline-4">
<h4 id="sec-1.2.1">1. 有关 C++ 链接库 EntryPoint 的名称</h4>
<div class="outline-text-4">
<p>我在刚开始从 C# 里链接 C++ 链接库的 API 时，想当然地以为就是函数名称。但是这样操作无论如何也调用不成功，<a href="http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx#pinvoke_callingdllexport">需要在 C++ 链接库里添加一个 extern 关键字</a>，否则链接库编译出来的 API 名称，是混淆过的，不方便你在 C# 里作为 EntryPoint 来书写。</p>
<p>比如说，有如下 C++ 链接库的 API 函数（建议链接库给外面调用的 API 最好用 C 风格来实现，方便减少头文件依赖关系）：</p>
<pre>
<span>extern</span> <span>"C"</span> <span>__declspec</span>(dllexport) <span>bool</span> <span>Function1</span>(<span>const</span> <span>char</span>* <span>param1</span>,
                                                <span>const</span> <span>char</span>* <span>param2</span>,
                                                <span>const</span> <span>char</span>* <span>param3</span>);
</pre>
<p>翻译成 C# 函数则如下：</p>
<pre>
[DllImport(<span>"Example.dll"</span>, EntryPoint = <span>"Function1"</span>, ExactSpelling = <span>false</span>]
[<span>return</span>: MarshalAs(UnmanagedType.U1)]
<span>public</span> <span>static</span> <span>extern</span> <span>bool</span> Function1([MarshalAs(UnmanagedType.LPStr)] String param1,
                                    [MarshalAs(UnmanagedType.LPStr)] String param2,
                                    [MarshalAs(UnmanagedType.LPStr)] String param3);
</pre>
<p>这里注意，找 EntryPoint 一定要准确，否则不容易找到。为了明确地找到 API 函数的 EntryPoint 名称，可以使用 Dumpbin.exe 工具。</p>
<p>dumpbin.exe 工具默认在以下目录：</p>
<pre>
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin
</pre>
<p>如果从这个目录里运行 dumpbin.exe 会提示找不到动态链接库 mspdb80.dll 的错误，可以把 dumpbin.exe 拷贝到目录</p>
<pre>
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE
</pre>
<p>，并从这个目录下运行 dumpbin.exe 来解决这个问题。</p>
<p>运行命令</p>
<pre>
dumpbin.exe /EXPORTS dllname.dll
</pre>
<p>后，你会看到很多 ? @ 混合在一起的名称，所以，为了使你在 C# 里的代码可读性比较强，需要改造这些名称。在链接库里，我们可以通过用 extern 关键字来标明，这样生成的链接库 EntryPoint 依然会是原始的名称。</p>
</p></div>
</p></div>
<div class="outline-4">
<h4 id="sec-1.2.2">2. C# 程序运行时提示说找不到链接库</h4>
<div class="outline-text-4">
<p>如果按上述方法编写好了代码，一运行 C# 程序却提示说：</p>
<pre>
未处理的"System.DllNotFoundException"类型的异常出现在 example.exe 中。

其他信息: 无法加载 DLL"cppexample.dll": 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
</pre>
<p>这个时候，你需要找一找你的 dll 是否在可执行目录下，或是你写的 dll 是否依赖于其它第三方dll，一定要确保所有的 dll 都能顺利被找到。</p>
</p></div>
</p></div>
<div class="outline-4">
<h4 id="sec-1.2.3">3. 参数的映射办法</h4>
<div class="outline-text-4">
<p>你的函数肯定有若干个参数，那这些参数应该和 C# 里的类型如何一一对应呢？在 C# 里，<a href="http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx#pinvoke_defaultmarshaling">这种映射关系叫做 marshal</a>。</p>
<p>类型映射，需要仔细检查一下手册，比如说，const char* 就应该这样映射：</p>
<pre>
[MarshalAs(UnmanagedType.LPStr)]
</pre>
<p><a href="http://msdn.microsoft.com/en-us/library/2x8kf7zx(v=vs.80).aspx">Using C++ Interop</a> 文章的未尾，有列出一大串的类型映射列表。</p>
</p></div>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.3">小结</h3>
<div class="outline-text-3">
<p>初步用 C# 来写界面，感觉更方便、快速，起码比 MFC 来得简单、直接；从 C# 里直接调用 C++ 链接库，也很方便。但这两者结合起来写应用，稳定性还有待进一步测试。</p>
</p></div>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio 2008 环境变量的配置</title>
		<link>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html</link>
		<comments>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html#comments</comments>
		<pubDate>Mon, 31 Oct 2011 07:43:48 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html</guid>
		<description><![CDATA[在调试 Visual Studio 2008 程序时，经常有一些动态链接库（即 dll 文件）需要加载到工程里，这样才能依赖第三方库进行程序调试。 这些动态链接库，往往都是测试版本或是开发中的版本，或者会有若干个版本；这个时候，如果直接把 dll 所在目录加到 PATH 里，则会有潜在冲突的危险；如果直接拷贝到 Visual Studio 的目录下，假如测试工程太多，每次有新版本的动态链接库更新时，你需要更新若干次，拷贝、粘贴苦不堪言。 在开发过程中，究竟怎样来让 Visual Studio 链接这些 lib 及 dll 文件会比较好呢？ 总体上来说，有几种方法可以改变 Visual Studio 的环境变量设置： 直接添加到系统的 PATH 变量里： 这个方法最简单，也最直接，但是坏处是会影响全局的 PATH 设置，尤其是你包含着大量测试用的 dll 时。 在 Visual Studio 全局设置里，把 dll 所在目录添加到 PATH 里： 通过 Visual Studio 菜单 ==&#62; 工具 ==&#62; 选项 ==&#62; 项目和解决方案 ==&#62; VC++目录，在下拉框里选择&#8221;可执行文件&#8221;，然后把 [...]]]></description>
			<content:encoded><![CDATA[<p>在调试 Visual Studio 2008 程序时，经常有一些动态链接库（即 dll 文件）需要加载到工程里，这样才能依赖第三方库进行程序调试。</p>
<p>这些动态链接库，往往都是测试版本或是开发中的版本，或者会有若干个版本；这个时候，如果直接把 dll 所在目录加到 PATH 里，则会有潜在冲突的危险；如果直接拷贝到 Visual Studio 的目录下，假如测试工程太多，每次有新版本的动态链接库更新时，你需要更新若干次，拷贝、粘贴苦不堪言。</p>
<p><strong>在开发过程中，究竟怎样来让 Visual Studio 链接这些 lib 及 dll 文件会比较好呢？</strong></p>
<p>总体上来说，有几种方法可以改变 Visual Studio 的环境变量设置：</p>
<ol>
<li>直接添加到<a href="http://blog.waterlin.org/articles/setting-emacs-home-directory.html">系统的 PATH 变量里</a>：
<p>这个方法最简单，也最直接，但是坏处是会影响全局的 PATH 设置，尤其是你包含着大量测试用的 dll 时。</p>
</li>
<li>在 Visual Studio 全局设置里，把 dll 所在目录添加到 PATH 里：
<p>通过 Visual Studio 菜单 ==&gt; 工具 ==&gt; 选项 ==&gt; 项目和解决方案 ==&gt; VC++目录，在下拉框里选择&#8221;可执行文件&#8221;，然后把 dll 所在路径添加进去。</p>
</li>
<li>直接把所有 dll 拷贝到 Visual Studio 工程目录下，或是拷贝到生成可执行文件的文件夹（默认情况下是 Debug 或 Release 目录）下：
<p>这个方法也很简单，但是当你有若干个工程时，你每次更新 SDK 及其 dll 文件，你就要把所有的工程都更新，这个不符合文件唯一性的工程性准则。</p>
</li>
<li>在调试程序时，让 Visual Studio 帮你切换当前工作目录到 dll 相应的目录下：
<p>在 Visual Studio ==&gt; Project ==&gt; Properties ==&gt; Select Configuration ==&gt; Configuration Properties ==&gt; Debugging ==&gt; Working directory 里填上 dll 所在目录，这样当在调试程序时，Visual Studio 会把当前工作目录切换到这个目录下，从而会自动读取本目录下的 dll 文件。</p>
<p>这个方法的优点很明显，简单！副作用也很明显，在你切换了当前工作目录后，你可能会找不到程序的配置文件，在程序里写的诸如&#8221;./config.ini&#8221;全部都找不到了；另外，你要把所有的 dll 都放到这个工作目录里，否则一样会提示说找不到 xxx.dll 的问题。</p>
</li>
<li>最后一个方法，也是我认为最好的一个方法，在 Visual Studio 工程属性里把一个目录临时添加到 PATH 环境变量里：
<p>MSDN 上也有类似的介绍：<a href="http://msdn.microsoft.com/en-us/library/ms173406.aspx">How to: Set Environment Variables for Projects</a>，方法很简单，在 &#8220;工程属性&#8221; ==&gt; &#8220;调试&#8221; ==&gt; &#8220;环境&#8221;里，添加类似如下所示的内容：</p>
<pre>
PATH=%PATH%;$(TargetDir)\DLLS
</pre>
<p>这样就可以把 $(TargetDir)\DLLS 临时添加到该工程所属的系统 PATH 里。</p>
</li>
</ol>
<p>大家可以根据项目的实际情况，灵活选用以上方法。</p>
<p>注：本文撰写时参考了 StackOverflow 上的讨论话题：<a href="http://stackoverflow.com/questions/428085/how-do-i-set-a-path-in-visual-studio">How do I set a path in visual studio?</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Berkeley DB 头文件的类型定义与 MFC 冲突的问题</title>
		<link>http://blog.waterlin.org/articles/the-problem-to-compile-berkeley-db-with-mfc.html</link>
		<comments>http://blog.waterlin.org/articles/the-problem-to-compile-berkeley-db-with-mfc.html#comments</comments>
		<pubDate>Mon, 05 Sep 2011 09:37:57 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/the-problem-to-compile-berkeley-db-with-mfc.html</guid>
		<description><![CDATA[在 Visual Studio 2008 MFC 工程中，利用 Berkeley DB 来构建数据存储引擎时，在编译 db.h 文件时出现编译错误，错误提示内容如下： 错误 3 error C2143: 语法错误 : 缺少"}"(在"("的前面) e:\water\berkeleydb\include\db.h 1226 微软的 MSDN 上有对 error C2143 的编译器错误进行解释，不过基本上没有太多可读性、可借鉴性，大意应该是一些宏定义、命名出错等。 最后，还是通过万能的 Google 大神找到了解答方法。错误的原因是 DB_TYPE, DB_UNKNOWN 类型已经在 MFC 系统头文件中被定义过，解决办法之一是在 db.h 中定义 DB_TYPE, DB_UNKNOWN 的语句之前加上如下语句即可： #ifdef DB_UNKNOWN #undef DB_UNKNOWN #endif #ifdef DBTYPE #undef DBTYPE #else #define DBTYPE BDBTYPE #endif 看来，C 和 [...]]]></description>
			<content:encoded><![CDATA[<p>在 Visual Studio 2008 MFC 工程中，利用 Berkeley DB 来构建数据存储引擎时，在编译 db.h 文件时出现编译错误，错误提示内容如下：</p>
<pre>
错误    3       error C2143: 语法错误 : 缺少"}"(在"("的前面)        e:\water\berkeleydb\include\db.h        1226
</pre>
<p>微软的 <a href="http://msdn.microsoft.com/en-us/library/0afb82ta.aspx">MSDN 上有对 error C2143 的编译器错误进行解释</a>，不过基本上没有太多可读性、可借鉴性，大意应该是一些宏定义、命名出错等。</p>
<p>最后，还是通过万能的 Google 大神找到了解答方法。错误的原因是 DB_TYPE, DB_UNKNOWN 类型已经在 MFC 系统头文件中被定义过，解决办法之一是在 db.h 中定义 DB_TYPE, DB_UNKNOWN 的语句之前加上如下语句即可：</p>
<pre>
<span>#ifdef</span> DB_UNKNOWN
<span>#undef</span> DB_UNKNOWN
<span>#endif</span>
<span>#ifdef</span> DBTYPE
<span>#undef</span> DBTYPE
<span>#else</span>
<span>#define</span> <span>DBTYPE</span> BDBTYPE
<span>#endif</span>
</pre>
<p>看来，C 和 C++ 混在一块，命名、类型定义真是一个大问题。以后碰到类似的问题，也可以采用类似的解决办法。</p>
<p>参考资料：</p>
<ol>
<li><a href="http://www.cppblog.com/fwxjj/archive/2010/08/10/122975.html">解决在vs2008的mfc工程中编译BerkeleyDB出错问题</a></li>
<li><a href="http://blog.csdn.net/dananhai/article/details/1694770">VS2005中的MFC程序使用BerkeleyDB</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/0afb82ta.aspx">MSDN Visual Studio 2010 Compiler Error C2143</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/the-problem-to-compile-berkeley-db-with-mfc.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用 MFC 来发起 FTP 请求</title>
		<link>http://blog.waterlin.org/articles/using-mfc-with-ftp.html</link>
		<comments>http://blog.waterlin.org/articles/using-mfc-with-ftp.html#comments</comments>
		<pubDate>Mon, 22 Aug 2011 06:45:38 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/using-mfc-with-ftp.html</guid>
		<description><![CDATA[在写客户端的时候，经常要传输一些文件，有一些服务器就是用 FTP 来搭建的，这个时候，如何用客户端来发起 FTP 网络连接呢？ 如果是用 MFC 来发起 FTP 文件传输请求，和使用 MFC 来发起 HTTP 请求类似，非常简单。理论基础可以仔细阅读 MSDN 上的官方文档 Steps in a Typical FTP Client Application，浏忙绪绪在这里，就贴上我自己写的代码，与大家分享一下。 样例代码如下： /* * 通过 ftp 方式来拿文件 * @param relativePath, 服务器保存该视频摘要文件夹、相对于 ftp 跟路径的相对路径 * @notice relativePath 应该是类似于 /test 这样相对于 ftp 根路径的相对路径 * 应该以 / 开头 * @param savePath, 从远程服务器下载文件后，在本地保存的文件夹路径 */ BOOL CGetRemoteFile::GetFtpfiles(CString relativePath, [...]]]></description>
			<content:encoded><![CDATA[<p>在写客户端的时候，经常要传输一些文件，有一些服务器就是用 FTP 来搭建的，这个时候，如何用客户端来发起 FTP 网络连接呢？</p>
<p>如果是用 MFC 来发起 FTP 文件传输请求，和<a href="http://cn.waterlin.org/Microsoft/MFC-HTTP-request.html">使用 MFC 来发起 HTTP 请求</a>类似，非常简单。理论基础可以仔细阅读 MSDN 上的官方文档 <a href="http://msdn.microsoft.com/en-us/library/hf9x9wb4(v=VS.80).aspx">Steps in a Typical FTP Client Application</a>，<a href="http://blog.waterlin.org">浏忙绪绪</a>在这里，就贴上我自己写的代码，与大家分享一下。</p>
<p>样例代码如下：</p>
<pre>
<span>/*</span><span>
 * 通过 ftp 方式来拿文件
 * @param  relativePath, 服务器保存该视频摘要文件夹、相对于 ftp 跟路径的相对路径
 * @notice relativePath 应该是类似于 /test 这样相对于 ftp 根路径的相对路径
 *                      应该以 / 开头
 * @param  savePath, 从远程服务器下载文件后，在本地保存的文件夹路径
 */</span>
<span>BOOL</span> <span>CGetRemoteFile</span>::<span>GetFtpfiles</span>(<span>CString</span> <span>relativePath</span>, <span>CString</span> <span>savePath</span>)
{
    <span>//</span><span>通过 http GET 协议来获取并保存文件
</span>    <span>CString</span> <span>remotefile</span>   = L<span>""</span>;
    <span>CString</span> <span>saveFilename</span> = L<span>""</span>;

    <span>CInternetSession</span> <span>session</span>;
    session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 1000 * 20);
    session.SetOption(INTERNET_OPTION_CONNECT_BACKOFF, 1000);
    session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);

    <span>/* </span><span>替换成相应的 FTP 用户名和密码 */</span>
    <span>CFtpConnection</span>* <span>pFtp</span> = session.GetFtpConnection( m_strServerIP,
                                                     m_strUsername,
                                                     m_strPassword,
                                                     (<span>INTERNET_PORT</span>)m_iSeverPort);

    <span>bool</span> <span>result</span> = pFtp-&gt;SetCurrentDirectory(relativePath);

    <span>if</span> (!result)
    {
        AfxMessageBox(L<span>"Can't get ftp file"</span>);
        <span>return</span> <span>false</span>;
    }

    <span>CFtpFileFind</span> <span>finder</span>(pFtp);
    <span>BOOL</span> <span>bFind</span> = finder.FindFile( L<span>"*"</span>, INTERNET_FLAG_RELOAD );
    <span>while</span> (bFind)
    {
        bFind = finder.FindNextFile();
        <span>CString</span> <span>strPath</span> = (<span>LPCTSTR</span>)finder.GetFileURL();
        <span>CString</span> <span>strFile</span> = (<span>LPCTSTR</span>)finder.GetFileName();
        <span>CString</span> <span>ftpPath</span>;
        ftpPath.Format(L<span>"正在下载文件：%s/%s\n"</span>, strPath, strFile);
        TRACE(ftpPath);

        <span>CInternetFile</span>* <span>pFile</span> = pFtp-&gt;OpenFile(strFile);<span>//</span><span>注意，这里只需要传文件名
</span>
        <span>int</span> <span>len</span> = pFile-&gt;GetLength();
        <span>char</span> <span>buf</span>[2000];
        <span>int</span> <span>numread</span>;

        <span>CString</span> <span>filepath</span>;
        filepath.Format(L<span>"%s\\%s"</span>, savePath, strFile);
        TRACE(L<span>"保存为文件%s"</span>,filepath);

        <span>CFile</span> <span>myfile</span>( filepath, <span>CFile</span>::modeCreate|<span>CFile</span>::modeWrite|<span>CFile</span>::typeBinary);
        <span>while</span> ((numread = pFile-&gt;Read(buf,<span>sizeof</span>(buf))) &gt; 0)
        {
            strFile += buf;
            myfile.Write(buf, numread);
        }
        myfile.Close();

        pFile-&gt;Close();
        <span>delete</span> pFile;
    }

    session.Close();

    <span>return</span> <span>true</span>;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/using-mfc-with-ftp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VC++2008 编译出来的文件为什么不能在别的电脑上运行？</title>
		<link>http://blog.waterlin.org/articles/vc-exe-can-not-run-on-other-computers.html</link>
		<comments>http://blog.waterlin.org/articles/vc-exe-can-not-run-on-other-computers.html#comments</comments>
		<pubDate>Fri, 17 Jun 2011 14:42:58 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/vc-exe-can-not-run-on-other-computers.html</guid>
		<description><![CDATA[最近被一个问题折磨了好几天，VC++2008 编译出来的 Debug 版本程序，拷到目标机器上，没有办法运行。我用 VC++2008 编译的文件在自己电脑上可以运行，可一放到别人电脑上就显示程序配置有问题，试了几台电脑都这样，拿到另一台装了 VC++2008 的电脑上又正常了。以前用 VC++6.0 的时候没这么多事，这是怎么回事呢？ 类似这种情况下，按理说应该是少了某个动态链接库，但是我确定第三方的动态链接库都拷贝到目标机器上了。 在目标机器上安装 Microsoft Visual C++ 2008 Redistributable Package (x86) 后，程序依然不能运行。但是如果我装给目标机器装上 VS2008 ，程序就可以顺利执行。 这个问题和 Debug 版本有关吗？还是 VS2008 的问题？编译成 Release 版本能不能解决这个问题呢？ 我用静态编译的方式，编译出的 release 版本就更奇怪了，在我自己的电脑上运行，都提示如下错误： "无法启动程序，因为计算机中丢失 MSVCP90.dll。尝试重新安装该程序以解决此问题。 这个库我怎么可能会没有？ 上 MSDN 仔细找了找原因，出现类似上面的问题，有以下几点需要注意： 按道理来说，编译成 release 版本后，只要在目标机器上安装相应版本的 vc_redist 就可以了； 对于 VS2008 版本，光把编译生成的可执行文件及 Dll 拷贝到目标机器上是不行的，要加上 manifest 文件； 动态链接的程序，需要在文件目录里复制 MFC90.dll, MSVCR90.dll 和 manifest [...]]]></description>
			<content:encoded><![CDATA[<p>最近被一个问题折磨了好几天，VC++2008 编译出来的 Debug 版本程序，拷到目标机器上，没有办法运行。我用 VC++2008 编译的文件在自己电脑上可以运行，可一放到别人电脑上就显示程序配置有问题，试了几台电脑都这样，拿到另一台装了 VC++2008 的电脑上又正常了。以前用 VC++6.0 的时候没这么多事，这是怎么回事呢？</p>
<p>类似这种情况下，按理说应该是少了某个动态链接库，但是我确定第三方的动态链接库都拷贝到目标机器上了。</p>
<p>在目标机器上安装 Microsoft Visual C++ 2008 Redistributable Package (x86) 后，程序依然不能运行。但是如果我装给目标机器装上 VS2008 ，程序就可以顺利执行。</p>
<p>这个问题和 Debug 版本有关吗？还是 VS2008 的问题？编译成 Release 版本能不能解决这个问题呢？</p>
<p>我用静态编译的方式，编译出的 release 版本就更奇怪了，在我自己的电脑上运行，都提示如下错误：</p>
<pre>
"无法启动程序，因为计算机中丢失 MSVCP90.dll。尝试重新安装该程序以解决此问题。
</pre>
<p>这个库我怎么可能会没有？</p>
<p><a href="http://msdn.microsoft.com/en-us/library/ms235317(v=VS.90).aspx">上 MSDN 仔细找了找原因</a>，出现类似上面的问题，有以下几点需要注意：</p>
<ol>
<li>按道理来说，编译成 release 版本后，只要在目标机器上安装相应版本的 vc_redist 就可以了；</li>
<li>对于 VS2008 版本，光把编译生成的可执行文件及 Dll 拷贝到目标机器上是不行的，要加上 manifest 文件；</li>
<li>动态链接的程序，需要在文件目录里复制 MFC90.dll, MSVCR90.dll 和 manifest 文件，不加上这个 manifest 是运行不了滴。</li>
</ol>
<p>在寻找答案的过程中，也在 StackOverflow 里提问获得了帮助，原文是 <a href="http://stackoverflow.com/questions/3380885/where-is-msvcp90d-dll-supposed-to-come-from">Where is msvcp90d.dll supposed to come from?</a>，笔记一下以备查阅。</p>
<p>如果需要检测程序依赖的动态链接库有哪些，可以使用 <a href="http://www.dependencywalker.com/">Dependency Walker</a> 这个工具。</p>
<p>PS: 看来 Stackoverflow 里，问题的回答质量是相当高的，以后可以尝试多用。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/vc-exe-can-not-run-on-other-computers.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>巧用 Windows7 的索引机制</title>
		<link>http://blog.waterlin.org/articles/windows7-index-usage.html</link>
		<comments>http://blog.waterlin.org/articles/windows7-index-usage.html#comments</comments>
		<pubDate>Sat, 14 May 2011 08:18:58 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/windows7-index-usage.html</guid>
		<description><![CDATA[如何对笔记进行索引是个大问题，尤其是像 Emacs Org 这种对搜索支持得不太好的编辑器而言，笔记的搜索是个特别烦恼的问题。我之前也讨论过《Emacs 笔记本全文搜索方法介绍》，如果你用的是 Windows7 操作系统，则可以用 Windows7 的索引机制，来方便地检索你的笔记目录，具体的方法如下： 在某个文件夹上，点右键，选&#8221;包含到库中&#8221;即可把当前目录添加到某个索引库里； 像我，就把 Emacs org 笔记、Onenote 笔记全拉进去了，这样搜索起来一点都不吃亏。 在&#8221;包含到库中&#8221;里，如果你要新建一个库来组织某一主题的文档，点击&#8221;新建库即可&#8221;。 以后你需要搜索你的笔记时，只要在这个库里进行搜索就可以得到你想要的东西，在文件浏览器的左边，会有一个&#8221;库&#8221;的文件夹类别，点它进行任何操作即可。 不知道 Windows7 在进行库搜索的时候，是否还支持一些基本的正则表达式、语义搜索之类的操作，比如说&#8221;TRACE + MFC&#8221;等。 Windows7 索引常见问题可以参看微软的官方文档，很全很强大。]]></description>
			<content:encoded><![CDATA[<p>如何对笔记进行索引是个大问题，尤其是像 Emacs Org 这种对搜索支持得不太好的编辑器而言，笔记的搜索是个特别烦恼的问题。我之前也讨论过<a href="http://blog.waterlin.org/articles/five-ways-to-search-in-emacs-notes.html">《Emacs 笔记本全文搜索方法介绍》</a>，如果你用的是 Windows7 操作系统，则可以用 Windows7 的索引机制，来方便地检索你的笔记目录，具体的方法如下：</p>
<ol>
<li>在某个文件夹上，点右键，选&#8221;包含到库中&#8221;即可把当前目录添加到某个索引库里；
<p>像我，就把 Emacs org 笔记、Onenote 笔记全拉进去了，这样搜索起来一点都不吃亏。</p>
</li>
<li>在&#8221;包含到库中&#8221;里，如果你要新建一个库来组织某一主题的文档，点击&#8221;新建库即可&#8221;。</li>
<li>以后你需要搜索你的笔记时，只要在这个库里进行搜索就可以得到你想要的东西，在文件浏览器的左边，会有一个&#8221;库&#8221;的文件夹类别，点它进行任何操作即可。</li>
</ol>
<p>不知道 Windows7 在进行库搜索的时候，是否还支持一些基本的正则表达式、语义搜索之类的操作，比如说&#8221;TRACE + MFC&#8221;等。</p>
<p><a href="http://windows.microsoft.com/en-US/windows7/Improve-Windows-searches-using-the-index-frequently-asked-questions">Windows7 索引常见问题</a>可以参看微软的官方文档，很全很强大。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/windows7-index-usage.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Visual Studio 2008 编译程序时的 mt.exe 返回错误</title>
		<link>http://blog.waterlin.org/articles/visual-studio-2008-mt-exe-return-error.html</link>
		<comments>http://blog.waterlin.org/articles/visual-studio-2008-mt-exe-return-error.html#comments</comments>
		<pubDate>Mon, 04 Apr 2011 04:11:15 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/visual-studio-2008-mt-exe-return-error.html</guid>
		<description><![CDATA[今天早上碰到一个很奇怪的事情，昨天明明还能在 Visual Studio 2008 里顺利编译的代码，今天编译的时候，就提示如下错误： 错误 171 错误的结果 -1073741819 (从"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe"返回)。 项目 用英文版的 Visual Studio 2008 应该是显示类似如下的错误信息： Project : error PRJ0002 : Error result 31 returned from 'C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe'. 这是怎么回事呢？原因我不是很清楚，但是可以用下面的方法来解决： 右键点击工程，选&#8221;属性&#8221;==&#62;&#8221;配置属性&#8221;==&#62;&#8221;链接器&#8221;==&#62;&#8221;清单文件&#8221;==&#62;&#8221;生成清单&#8221;==&#62;设为&#8221;否&#8221; 英文版的 Visual Studio 2008 应该是如下路径： Properties ==&#62; Configuration Properties ==&#62; Linker ==&#62; Manifest File, set Generate Manifest to No. 知其然更要知其所以然，有谁知道原因的？]]></description>
			<content:encoded><![CDATA[<p>今天早上碰到一个很奇怪的事情，昨天明明还能在 Visual Studio 2008 里顺利编译的代码，今天编译的时候，就提示如下错误：</p>
<pre>
错误    171     错误的结果 -1073741819 (从"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe"返回)。   项目
</pre>
<p>用英文版的 Visual Studio 2008 应该是显示类似如下的错误信息：</p>
<pre>
Project : error PRJ0002 : Error result 31 returned from 'C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe'.
</pre>
<p>这是怎么回事呢？原因我不是很清楚，但是可以用下面的方法来解决：</p>
<p>右键点击工程，选&#8221;属性&#8221;==&gt;&#8221;配置属性&#8221;==&gt;&#8221;链接器&#8221;==&gt;&#8221;清单文件&#8221;==&gt;&#8221;生成清单&#8221;==&gt;设为&#8221;否&#8221;</p>
<p>英文版的 Visual Studio 2008 应该是如下路径：</p>
<p>Properties ==&gt; Configuration Properties ==&gt; Linker ==&gt; Manifest File, set Generate Manifest to No.</p>
<p>知其然更要知其所以然，有谁知道原因的？</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/visual-studio-2008-mt-exe-return-error.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>微软 DirectShow 的自摆乌龙</title>
		<link>http://blog.waterlin.org/articles/qedit-problem-in-windows-directshow.html</link>
		<comments>http://blog.waterlin.org/articles/qedit-problem-in-windows-directshow.html#comments</comments>
		<pubDate>Sat, 04 Sep 2010 09:48:08 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/qedit-problem-in-windows-directshow.html</guid>
		<description><![CDATA[在使用有关 DirectShow 东西的时候，使用了头文件 #include &#60;qedit.h&#62; 结果，编译的时候提示如下错误： 错误 1 fatal error C1083: 无法打开包括文件:"dxtrans.h": No such file or directory c:\program files\microsoft sdks\windows\v6.0a\include\qedit.h 498 这个真是奇怪了，为啥微软自己 SDK 里的东西，都会出现找不到头文件的问题呢？ 解决办法可以有两种： (1) 从其它地方把 dxtrans.h 这个文件拷过来，例如从 Program Files\Windows Mobile 5.0 SDK R2\PocketPC\Include\Armv4i\dxtrans.h Program Files\Windows Mobile 5.0 SDK R2\Smartphone\Include\Armv4i\dxtrans.h D:\Program Files\Windows Mobile 6 SDK\PocketPC\Include\Armv4i D:\Program Files\Windows Mobile 6 SDK\Smartphone\Include\Armv4i 里拷 dxtrans.h 这个文件出来。 (2) [...]]]></description>
			<content:encoded><![CDATA[<p>在使用有关 DirectShow 东西的时候，使用了头文件</p>
<pre>
<span>#include</span> <span>&lt;qedit.h&gt;</span>
</pre>
<p>结果，编译的时候提示如下错误：</p>
<pre>
错误    1       fatal error C1083: 无法打开包括文件:"dxtrans.h": No such file or directory    c:\program files\microsoft sdks\windows\v6.0a\include\qedit.h   498
</pre>
<p>这个真是奇怪了，为啥微软自己 SDK 里的东西，都会出现找不到头文件的问题呢？</p>
<p>解决办法可以有两种：</p>
<p>(1) 从其它地方把 dxtrans.h 这个文件拷过来，例如从</p>
<pre>
Program Files\Windows Mobile 5.0 SDK R2\PocketPC\Include\Armv4i\dxtrans.h
Program Files\Windows Mobile 5.0 SDK R2\Smartphone\Include\Armv4i\dxtrans.h
D:\Program Files\Windows Mobile 6 SDK\PocketPC\Include\Armv4i
D:\Program Files\Windows Mobile 6 SDK\Smartphone\Include\Armv4i
</pre>
<p>里拷 dxtrans.h 这个文件出来。</p>
<p>(2) 或者在引用 qedit.h 头文件的时候，加上这么几句：</p>
<pre>
<span>#pragma</span> include_alias( <span>"dxtrans.h"</span>, <span>"qedit.h"</span> )
<span>#define</span> <span>__IDxtCompositor_INTERFACE_DEFINED__</span>
<span>#define</span> <span>__IDxtAlphaSetter_INTERFACE_DEFINED__</span>
<span>#define</span> <span>__IDxtJpeg_INTERFACE_DEFINED__</span>
<span>#define</span> <span>__IDxtKey_INTERFACE_DEFINED__</span>
<span>#include</span> <span>"Qedit.h"</span>
</pre>
<p>也可以。</p>
<p>微软的<a href="http://social.msdn.microsoft.com/forums/en-US/windowssdk/thread/ed097d2c-3d68-4f48-8448-277eaaf68252/">MSDN上还有对这个问题的讨论</a>，看来真是微软自摆乌龙了。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/qedit-problem-in-windows-directshow.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows SDK 6.0A: unknwn.idl compilation error</title>
		<link>http://blog.waterlin.org/articles/windows-sdk-60a-unknwn-idl-compilation-error.html</link>
		<comments>http://blog.waterlin.org/articles/windows-sdk-60a-unknwn-idl-compilation-error.html#comments</comments>
		<pubDate>Thu, 02 Sep 2010 11:09:36 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/windows-sdk-60a-unknwn-idl-compilation-error.html</guid>
		<description><![CDATA[不知道为什么，之前还能在 Visual Studio 2005 下编译得好好的工程，今天突然就碰到下面的问题： Error 1 error MIDL2025 : syntax error : expecting ] or , near "annotation" C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\unknwn.idl 108 Error 2 error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\unknwn.idl 108 这个是 MIDL 编译器相关的问题，当你给新版本的 Windows SDK 头文件使用旧版本的 MIDL 编译器时，就会有这个问题。 解决的办法，就是把你新版本的 MIDL 编译器添加到 Visual Studio 的包含目录里。微软 Mike [...]]]></description>
			<content:encoded><![CDATA[<p>不知道为什么，之前还能在 Visual Studio 2005 下编译得好好的工程，今天突然就碰到下面的问题：</p>
<pre>
Error    1    error MIDL2025 : syntax error : expecting ] or , near "annotation"    C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\unknwn.idl    108
Error    2    error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation     C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\unknwn.idl    108
</pre>
<p>这个是 MIDL 编译器相关的问题，当你给新版本的 Windows SDK 头文件使用旧版本的 MIDL 编译器时，就会有这个问题。</p>
<p>解决的办法，就是把你新版本的 MIDL 编译器添加到 Visual Studio 的包含目录里。微软 <a href="http://blogs.msdn.com/b/mikewasson">Mike Wasson</a> 的博客 <a href="http://blogs.msdn.com/b/mikewasson/archive/2006/10/02/midl-error_3a00_-_2700_annotation_2700_.aspx">MIDL error: &#8216;annotation&#8217;</a> 对此有着详细的解释，内容摘要如下：</p>
<pre>
A colleage recently got this error while compiling unknown.idl:

1&gt;C:\Program Files\Microsoft SDKs\Windows\v6.0\Include\unknwn.idl(108) : error MIDL2025 : syntax error : expecting ] or , near "annotation"
1&gt;C:\Program Files\Microsoft SDKs\Windows\v6.0\Include\unknwn.idl(108) : error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation

If you get this error, you are using a new version of the Windows headers with an older version of the MIDL compiler.

Fix:

1. Make sure you installed the MIDL compiler when you installed the latest Windows SDK. It should appear under "Program Files\Microsoft SDKs\Windows\v6.0\Bin".

Note: To install the MIDL compiler, you need to select Developer Tools / Windows Development Tools / Win32 Development Tools in the Windows SDK setup wizard. (At least, as of RC1.)

2. In Visual Studio, under Tools &gt; Options &gt; Projects and Solutions &gt; VC++ Directories &gt; Executable Files, add

    x:\Program Files\Microsoft SDKs\Windows\v6.0\bin

to the top of the list.
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/windows-sdk-60a-unknwn-idl-compilation-error.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Installer 把安装目录写到注册表里的方法</title>
		<link>http://blog.waterlin.org/articles/windows-installer-sets-installation-path-dynamicly.html</link>
		<comments>http://blog.waterlin.org/articles/windows-installer-sets-installation-path-dynamicly.html#comments</comments>
		<pubDate>Wed, 25 Aug 2010 08:24:45 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/windows-installer-sets-installation-path-dynamicly.html</guid>
		<description><![CDATA[在用 Visual Studio 2005 建立生成安装文件的工程时，因为应用程序的需要，在安装的时候要求 Windows Installer 把用户选择的安装路径写到注册表里。这个时候，有什么解决办法呢？ 可以在生成安装文件的工程里，手动插入一个系统预留的属性值（即需要转义的字符串），在 Windows Installer 安装程序的时候，会自动把这些属性值替换掉。可以用 [] 或 {} 来把该属性值括起来。 例如，右键点击&#8221;安装工程名称 ==&#62; 视图 ==&#62; 编辑器 ==&#62; 注册表&#8221;，这时，可以添加如下注册表项： HKEY_CURRENT_USER&#124;HKEY_LOCAL_MACHINE\Software\[Manufacturer]\ 这样，在 Windows Installer 安装程序的时候， [Manufacturer] 就会自动转义为实际的值。当然，如果没有对应的系统预留属性值，则转义为空值( blank )。 系统预留的属性值有很多个，例如对于安装目录来说，是 [TARGETDIR] ，即 [TARGETDIR] 会根据安装时用户选择的安装路径赋值。当你在注册表里，需要填写程序安装路径的时候，就可以用这个属性值来占位。Windows Installer 在安装的时候，自然会把它替换为实际路径。安装后，会显示为类似于下面的路径： C:\Program Files\TestApp\TestAppFirstPart\ 如果你需要在注册表里指定相应的可执行文件或动态链接库，比如说，你要在注册表里插入下面的路径： C:\Program Files\TestApp\TestAppFirstPart\test.dll 这时，你就应该在工程里把属性值设为： [TARGETDIR]test.dll 注意 [TARGETDIR] 生成的目录会有最后一个 \ 号。 更多 Windows Installer 使用技巧可以看 [...]]]></description>
			<content:encoded><![CDATA[<p>在用 Visual Studio 2005 建立生成安装文件的工程时，因为应用程序的需要，在安装的时候要求 <a href="http://msdn.microsoft.com/en-us/library/19x10e5c.aspx">Windows Installer</a> 把用户选择的安装路径写到<a href="http://msdn.microsoft.com/en-us/library/Aa371168">注册表</a>里。这个时候，有什么解决办法呢？</p>
<p>可以在生成安装文件的工程里，手动插入一个系统预留的<a href="http://blog.waterlin.org/articles/more-discussion-about-windows-registry.html">属性值（即需要转义的字符串）</a>，在 Windows Installer 安装程序的时候，会自动把这些属性值替换掉。可以用 <strong>[]</strong> 或 <strong>{}</strong> 来把该属性值括起来。</p>
<p>例如，右键点击&#8221;安装工程名称 ==&gt; 视图 ==&gt; 编辑器 ==&gt; 注册表&#8221;，这时，可以添加如下注册表项：</p>
<pre>
HKEY_CURRENT_USER|HKEY_LOCAL_MACHINE\Software\[Manufacturer]\
</pre>
<p>这样，在 Windows Installer 安装程序的时候， <strong>[Manufacturer]</strong> 就会自动转义为实际的值。当然，如果没有对应的系统预留属性值，则转义为空值( blank )。</p>
<p><a href="http://msdn.microsoft.com/en-us/library/aa368609">系统预留的属性值有很多个</a>，例如对于安装目录来说，是 <strong>[TARGETDIR]</strong> ，即 <strong>[TARGETDIR]</strong> 会根据安装时用户选择的安装路径赋值。当你在<a href="http://blog.waterlin.org/articles/more-discussion-about-windows-registry.html">注册表</a>里，需要填写程序安装路径的时候，就可以用这个属性值来占位。Windows Installer 在安装的时候，自然会把它替换为实际路径。安装后，会显示为类似于下面的路径：</p>
<pre>
C:\Program Files\TestApp\TestAppFirstPart\
</pre>
<p>如果你需要在注册表里指定相应的可执行文件或动态链接库，比如说，你要在注册表里插入下面的路径：</p>
<pre>
C:\Program Files\TestApp\TestAppFirstPart\test.dll
</pre>
<p>这时，你就应该在工程里把属性值设为：</p>
<pre>
[TARGETDIR]test.dll
</pre>
<p>注意 <strong>[TARGETDIR]</strong> 生成的目录会有最后一个 <strong>\</strong> 号。</p>
<p>更多 Windows Installer 使用技巧可以看 <a href="http://robertdickau.com/msi_tips.html">Windows Installer (MSI) Tips and Notes</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/windows-installer-sets-installation-path-dynamicly.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

