2010年3月

用Yahoo Pipes制作全文输出的RSS:cnbeta全文输出方法

cnbeta的rss全文输出方法。共享一个我制作的cnbeta的全文输出feed:
http://pipes.yahoo.com/pipes/pipe.run?_id=035788f8a9608efa4e74a2f0960c2cd1&_render=rss

很多网站尤其是一些新闻类的网站虽然提供RSS输出,像我天天光顾的cb就不是全文输出,如果要看全文还要点击进去,这样总感觉不是很爽……不过现在有了Yahoo Pipes就好办了!这是Yahoo提供的一款超级强大的RSS处理工具,今天俺就教你如何用它来输出网站的全文!

第一步

先在 Yahoo Pipes 里新建一个 pipe(如图)

Create a pipe

第二步

拖入一个 Fetch Feed 模块,输入你想要全文输出的RSS地址(如图我添加的是cnbeta的RSS

第三步

然后到Operators条目下拖入一个 Loop 模块,与 Fetch Feed 相连接

再到Sources条目拖一出个 Fetch Page 模块拖进入 Loop(注意是拖进Loop里面去,如图)

设置 URL 为 item.link

第四步

这是最关键的一步!!!

随便打开你要全文输出的RSS其中一篇文章,然后等网页加载完毕后,查看这篇网页的源代码

然后查找网页源代码中正文部分,把能囊括正文的开始的地方(align="right" id="sign" onload="fixPNG(this)"/></a>)和结尾的地方(<div class="digbox">)找到。

然后分别填到Cut content from和to里面,如图

第五步

把assign项选为first,然后把results to填为item.description,将 Loop 连接到 Pipe Out,保存,大功告成!!!

最后

当然到这里已经可以全文输出cb的feed了,但还有一点不完美的地方,就是那个截取的内容前面都有align="right" id="sign" onload="fixPNG(this)"/></a>,这里我们可以插入一个regex操作,把这段字符串去掉。从左边的operators里面拖一个regex到右边来。然后在in里面选择item.description.content,replace里面填写align="right" id="sign" onload="fixPNG\(this\)"/></a>,with里面不用填(就是空着)。最后我的pipe图是这样的:

最最后

你可以点击下面的按钮和链接就行调试,不做多说了!这样获取的全文RSS肯定没有直接获取的高效,本人刚刚使用还不知道会不会出现很滞后的现象。(注:文章中有几个图片用的是别个的,懒得截图了)

一个比较全的C#写的ftp类

[code language="csharp"]
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Sockets;

/// <summary>
/// FTPClient 的摘要说明。
/// </summary>
public class FTPClient
{
#region 构造函数
/// <summary>
/// 缺省构造函数
/// </summary>
public FTPClient()
{
strRemoteHost = "";
strRemotePath = "";
strRemoteUser = "";
strRemotePass = "";
strRemotePort = 21;
bConnected = false;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="remoteHost"></param>
/// <param name="remotePath"></param>
/// <param name="remoteUser"></param>
/// <param name="remotePass"></param>
/// <param name="remotePort"></param>
public FTPClient( string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort )
{
strRemoteHost = remoteHost;
strRemotePath = remotePath;
strRemoteUser = remoteUser;
strRemotePass = remotePass;
strRemotePort = remotePort;
Connect();
}
#endregion

#region 登陆
/// <summary>
/// FTP服务器IP地址
/// </summary>
private string strRemoteHost;
public string RemoteHost
{
get
{
return strRemoteHost;
}
set
{
strRemoteHost = value;
}
}
/// <summary>
/// FTP服务器端口
/// </summary>
private int strRemotePort;
public int RemotePort
{
get
{
return strRemotePort;
}
set
{
strRemotePort = value;
}
}
/// <summary>
/// 当前服务器目录
/// </summary>
private string strRemotePath;
public string RemotePath
{
get
{
return strRemotePath;
}
set
{
strRemotePath = value;
}
}
/// <summary>
/// 登录用户账号
/// </summary>
private string strRemoteUser;
public string RemoteUser
{
set
{
strRemoteUser = value;
}
}
/// <summary>
/// 用户登录密码
/// </summary>
private string strRemotePass;
public string RemotePass
{
set
{
strRemotePass = value;
}
} /// <summary>
/// 是否登录
/// </summary>
private Boolean bConnected;
public bool Connected
{
get
{
return bConnected;
}
}
#endregion

#region 链接
/// <summary>
/// 建立连接
/// </summary>
public void Connect()
{
socketControl = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
IPEndPoint ep = new IPEndPoint( IPAddress.Parse( RemoteHost ), strRemotePort );
// 链接
try
{
socketControl.Connect( ep );
}
catch( Exception )
{
throw new IOException( "Couldn't connect to remote server" );
} // 获取应答码
ReadReply();
if( iReplyCode != 220 )
{
DisConnect();
throw new IOException( strReply.Substring( 4 ) );
} // 登陆
SendCommand( "USER " + strRemoteUser );
if( !( iReplyCode == 331 || iReplyCode == 230 ) )
{
CloseSocketConnect();//关闭连接
throw new IOException( strReply.Substring( 4 ) );
}
if( iReplyCode != 230 )
{
SendCommand( "PASS " + strRemotePass );
if( !( iReplyCode == 230 || iReplyCode == 202 ) )
{
CloseSocketConnect();//关闭连接
throw new IOException( strReply.Substring( 4 ) );
}
}
bConnected = true; // 切换到目录
ChDir( strRemotePath );
}
/// <summary>
/// 关闭连接
/// </summary>
public void DisConnect()
{
if( socketControl != null )
{
SendCommand( "QUIT" );
}
CloseSocketConnect();
}
#endregion

#region 传输模式
/// <summary>
/// 传输模式:二进制类型、ASCII类型
/// </summary>
public enum TransferType { Binary, ASCII }; /// <summary>
/// 设置传输模式
/// </summary>
/// <param name="ttType">传输模式</param>
public void SetTransferType( TransferType ttType )
{
if( ttType == TransferType.Binary )
{
SendCommand( "TYPE I" );//binary类型传输
}
else
{
SendCommand( "TYPE A" );//ASCII类型传输
}
if( iReplyCode != 200 )
{
throw new IOException( strReply.Substring( 4 ) );
}
else
{
trType = ttType;
}
}
/// <summary>
/// 获得传输模式
/// </summary>
/// <returns>传输模式</returns>
public TransferType GetTransferType()
{
return trType;
}

#endregion

#region 文件操作
/// <summary>
/// 获得文件列表
/// </summary>
/// <param name="strMask">文件名的匹配字符串</param>
/// <returns></returns>
public string[] Dir( string strMask )
{
// 建立链接
if( !bConnected )
{
Connect();
} //建立进行数据连接的socket
Socket socketData = CreateDataSocket();

//传送命令
SendCommand( "NLST " + strMask ); //分析应答代码
if( !( iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 ) )
{
throw new IOException( strReply.Substring( 4 ) );
} //获得结果
strMsg = "";
while( true )
{
int iBytes = socketData.Receive( buffer, buffer.Length, 0 );
strMsg += ASCII.GetString( buffer, 0, iBytes );
if( iBytes < buffer.Length )
{
break;
}
}
char[] seperator = { '\n' };
string[] strsFileList = strMsg.Split( seperator );
socketData.Close();//数据socket关闭时也会有返回码
if( iReplyCode != 226 )
{
ReadReply();
if( iReplyCode != 226 )
{
throw new IOException( strReply.Substring( 4 ) );
}
}
return strsFileList;
}
/// <summary>
/// 获取文件大小
/// </summary>
/// <param name="strFileName">文件名</param>
/// <returns>文件大小</returns>
private long GetFileSize( string strFileName )
{
if( !bConnected )
{
Connect();
}
SendCommand( "SIZE " + Path.GetFileName( strFileName ) );
long lSize = 0;
if( iReplyCode == 213 )
{
lSize = Int64.Parse( strReply.Substring( 4 ) );
}
else
{
throw new IOException( strReply.Substring( 4 ) );
}
return lSize;
}
/// <summary>
/// 删除
/// </summary>
/// <param name="strFileName">待删除文件名</param>
public void Delete( string strFileName )
{
if( !bConnected )
{
Connect();
}
SendCommand( "DELE " + strFileName );
if( iReplyCode != 250 )
{
throw new IOException( strReply.Substring( 4 ) );
}
}
/// <summary>
/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
/// </summary>
/// <param name="strOldFileName">旧文件名</param>
/// <param name="strNewFileName">新文件名</param>
public void Rename( string strOldFileName, string strNewFileName )
{
if( !bConnected )
{
Connect();
}
SendCommand( "RNFR " + strOldFileName );
if( iReplyCode != 350 )
{
throw new IOException( strReply.Substring( 4 ) );
}
// 如果新文件名与原有文件重名,将覆盖原有文件
SendCommand( "RNTO " + strNewFileName );
if( iReplyCode != 250 )
{
throw new IOException( strReply.Substring( 4 ) );
}
}
#endregion

#region 目录操作
/// <summary>
/// 创建目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void MkDir( string strDirName )
{
if( !bConnected )
{
Connect();
}
SendCommand( "MKD " + strDirName );
if( iReplyCode != 257 )
{
throw new IOException( strReply.Substring( 4 ) );
}
}

/// <summary>
/// 删除目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void RmDir( string strDirName )
{
if( !bConnected )
{
Connect();
}
SendCommand( "RMD " + strDirName );
if( iReplyCode != 250 )
{
throw new IOException( strReply.Substring( 4 ) );
}
}

/// <summary>
/// 改变目录
/// </summary>
/// <param name="strDirName">新的工作目录名</param>
public void ChDir( string strDirName )
{
if( strDirName.Equals( "." ) || strDirName.Equals( "" ) )
{
return;
}
if( !bConnected )
{
Connect();
}
SendCommand( "CWD " + strDirName );
if( iReplyCode != 250 )
{
throw new IOException( strReply.Substring( 4 ) );
}
this.strRemotePath = strDirName;
}

#endregion

#region 上传和下载
/// <summary>
/// 下载一批文件
/// </summary>
/// <param name="strFileNameMask">文件名的匹配字符串</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
public void Get( string strFileNameMask, string strFolder )
{
if( !bConnected )
{
Connect();
}
string[] strFiles = Dir( strFileNameMask );
foreach( string strFile in strFiles )
{
if( !strFile.Equals( "" ) )//一般来说strFiles的最后一个元素可能是空字符串
{
Get( strFile, strFolder, strFile );
}
}
}
/// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void Get( string strRemoteFileName, string strFolder, string strLocalFileName )
{
if( !bConnected )
{
Connect();
}
SetTransferType( TransferType.Binary );
if( strLocalFileName.Equals( "" ) )
{
strLocalFileName = strRemoteFileName;
}
if( !File.Exists( strLocalFileName ) )
{
Stream st = File.Create( strLocalFileName );
st.Close();
}
FileStream output = new
FileStream( strFolder + "\\" + strLocalFileName, FileMode.Create );
Socket socketData = CreateDataSocket();
SendCommand( "RETR " + strRemoteFileName );
if( !( iReplyCode == 150 || iReplyCode == 125
|| iReplyCode == 226 || iReplyCode == 250 ) )
{
throw new IOException( strReply.Substring( 4 ) );
}
while( true )
{
int iBytes = socketData.Receive( buffer, buffer.Length, 0 );
output.Write( buffer, 0, iBytes );
if( iBytes <= 0 )
{
break;
}
}
output.Close();
if( socketData.Connected )
{
socketData.Close();
}
if( !( iReplyCode == 226 || iReplyCode == 250 ) )
{
ReadReply();
if( !( iReplyCode == 226 || iReplyCode == 250 ) )
{
throw new IOException( strReply.Substring( 4 ) );
}
}
}
/// <summary>
/// 上传一批文件
/// </summary>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
public void Put( string strFolder, string strFileNameMask )
{
string[] strFiles = Directory.GetFiles( strFolder, strFileNameMask );
foreach( string strFile in strFiles )
{
//strFile是完整的文件名(包含路径)
Put( strFile );
}
}
/// <summary>
/// 上传一个文件
/// </summary>
/// <param name="strFileName">本地文件名</param>
public void Put( string strFileName )
{
if( !bConnected )
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand( "STOR " + Path.GetFileName( strFileName ) );
if( !( iReplyCode == 125 || iReplyCode == 150 ) )
{
throw new IOException( strReply.Substring( 4 ) );
}
FileStream input = new
FileStream( strFileName, FileMode.Open );
int iBytes = 0;
while( ( iBytes = input.Read( buffer, 0, buffer.Length ) ) > 0 )
{
socketData.Send( buffer, iBytes, 0 );
}
input.Close();
if( socketData.Connected )
{
socketData.Close();
}
if( !( iReplyCode == 226 || iReplyCode == 250 ) )
{
ReadReply();
if( !( iReplyCode == 226 || iReplyCode == 250 ) )
{
throw new IOException( strReply.Substring( 4 ) );
}
}
}

#endregion

#region 内部函数
/// <summary>
/// 将一行应答字符串记录在strReply和strMsg
/// 应答码记录在iReplyCode
/// </summary>
private void ReadReply()
{
strMsg = "";
strReply = ReadLine();
iReplyCode = Int32.Parse( strReply.Substring( 0, 3 ) );
} /// <summary>
/// 建立进行数据连接的socket
/// </summary>
/// <returns>数据连接socket</returns>
private Socket CreateDataSocket()
{
SendCommand( "PASV" );
if( iReplyCode != 227 )
{
throw new IOException( strReply.Substring( 4 ) );
}
int index1 = strReply.IndexOf( '(' );
int index2 = strReply.IndexOf( ')' );
string ipData =
strReply.Substring( index1 + 1, index2 - index1 - 1 );
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf = "";
for( int i = 0; i < len && partCount <= 6; i++ )
{
char ch = Char.Parse( ipData.Substring( i, 1 ) );
if( Char.IsDigit( ch ) )
buf += ch;
else if( ch != ',' )
{
throw new IOException( "Malformed PASV strReply: " +
strReply );
}
if( ch == ',' || i + 1 == len )
{
try
{
parts[partCount++] = Int32.Parse( buf );
buf = "";
}
catch( Exception )
{
throw new IOException( "Malformed PASV strReply: " +
strReply );
}
}
}
string ipAddress = parts[0] + "." + parts[1] + "." +
parts[2] + "." + parts[3];
int port = ( parts[4] << 8 ) + parts[5];
Socket s = new
Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
IPEndPoint ep = new
IPEndPoint( IPAddress.Parse( ipAddress ), port );
try
{
s.Connect( ep );
}
catch( Exception )
{
throw new IOException( "Can't connect to remote server" );
}
return s;
}
/// <summary>
/// 关闭socket连接(用于登录以前)
/// </summary>
private void CloseSocketConnect()
{
if( socketControl != null )
{
socketControl.Close();
socketControl = null;
}
bConnected = false;
}

/// <summary>
/// 读取Socket返回的所有字符串
/// </summary>
/// <returns>包含应答码的字符串行</returns>
private string ReadLine()
{
while( true )
{
int iBytes = socketControl.Receive( buffer, buffer.Length, 0 );
strMsg += ASCII.GetString( buffer, 0, iBytes );
if( iBytes < buffer.Length )
{
break;
}
}
char[] seperator = { '\n' };
string[] mess = strMsg.Split( seperator );
if( strMsg.Length > 2 )
{
strMsg = mess[mess.Length - 2];
//seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
//但也会分配为空字符串给后面(也是最后一个)字符串数组,
//所以最后一个mess是没用的空字符串
//但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
}
else
{
strMsg = mess[0];
}
if( !strMsg.Substring( 3, 1 ).Equals( " " ) )//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
return ReadLine();
}
return strMsg;
}
/// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name="strCommand">命令</param>
private void SendCommand( String strCommand )
{
//Byte[] cmdBytes =
// Encoding.ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
byte[] cmdBytes = Encoding.GetEncoding( "gb2312" ).GetBytes( ( strCommand + "\r\n" ).ToCharArray() );
socketControl.Send( cmdBytes, cmdBytes.Length, 0 );
ReadReply();
}
#endregion

#region 内部变量
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strMsg;
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strReply;
/// <summary>
/// 服务器返回的应答码
/// </summary>
private int iReplyCode;
/// <summary>
/// 进行控制连接的socket
/// </summary>
private Socket socketControl;
/// <summary>
/// 传输模式
/// </summary>
private TransferType trType;
/// <summary>
/// 接收和发送数据的缓冲区
/// </summary>
private static int BLOCK_SIZE = 512;
Byte[] buffer = new Byte[BLOCK_SIZE];
/// <summary>
/// 编码方式
/// </summary>
Encoding ASCII = Encoding.ASCII;
#endregion
}
[/code]

SQLServer添加用户:错误15023:当前数据库中已存在用户或角色

在使用SQL Server 2000时,我们经常会遇到一个情况:需要把一台服务器上的数据库转移到另外一台服务器上。而转移完成后,需要给一个"登录"关联一个"用户"时,往往会 发生错误:

错误15023:当前数据库中已存在用户或角色

这个问题非常让人头疼,几经排常找到了原因与解决方法,因为这个问题与解决方法均比较复杂,所以把这个过程中的一些经验纪录下来与大家分享,希望能对大家以后的类似操作有所帮助,原因及解决办法如下:

首先介绍一下sql server中“登录”与“用户”的区别,“登录”用于用户身份验证,而数据库“用户”帐户用于数据库访问和权限验证。登录通过安全识别符 (SID) 与用户关联。将数据库恢复到其他服务器时,数据库中包含一组用户和权限,但可能没有相应的登录或者登录所关联的用户可能不是相同的用户。这种情况被称为存 在“孤立用户”。此时是不能通过新建登录或者是对同名登录授予对应数据库的“用户”权限来解决登录问题,因为SQL Server会报出“错误15023:当前数据库中已存在用户或角色”,为了解决这个问题,需要调用系统存储过程 sp_change_users_login,具体用法如下:

[code language="sql"]Use tablename

go

sp_change_users_login 'update_one', 'junstyle', 'junstyle'
[/code]

其中tablename为存在孤立用户的数据库,update_one是存储过程的参数,表示只处理一个用户,前一个 junstyle是“用户”,后一个junstyle是“登录”,以上这个SQL表示将服务器登录“junstyle”与 tablename数据库用户“junstyle”重新连接起来。这样就可以正常使用数据库了。

gmail实验室里面的实验性功能

今天进到gmail的实验室看了一下,发现又加入了几个新功能。但也让我发现了一个很无语的功能。上图:

gmail真是贴心,有些人看到logo上的beta消失了,不安心,这个功能可以让他们安心下来。

玩转Google:Google搜索命令大全

使用谷歌搜索的时候有很多高级搜索代码,比如大家都很熟悉的site等命令,今天junstyle整理出目前所有的google高级搜索命令,供大家参考!

以下是目前所有的Google搜索命令语法,它不同于Google的帮助文档,因为这里介绍了几个Google不推荐使用的命令语法。大多数的 Google搜索命令语法有它特有的使用格式,希望大家能正确使用。

allintext: 当我们用allintext提交查询的时候,Google会限制搜索结果仅仅是在网页正文里边包含了我们所有查询关键词的网页。例[allintext: travel packing list],提交这个查询,Google仅仅会返回在一个网页包含了三个关键词”travel” “packing”和”list”的网页。

allinanchor: anchor是一处说明性的文字,它标注说明了这个链接可能跳转到其它的网页或跳转到当前网页的不同地方。当我们用allinanchor提交查询的时候,Google会限制搜索结果必须是那些在anchor文字里包含了我们所有查询关键词的网页。例[ allinanchor: best museums Sydney ] ,提交这个查询,Google仅仅会返回在网页anchor说明文字里边包含了关键词”best” “museums” 和”Sydney”的网面。

allintitle: 当我们用allintitle提交查询的时候,Google会限制搜索结果仅是那些在网页标题里边包含了我们所有查询关键词的网页。例[allintitle: detect plagiarism],提交这个查询,Google仅会返回在网页标题里边包含了”detect”和”plagiarism”这两个关键词的网页。

- 阅读剩余部分 -

google终于被墙了

昨天google宣布转战香港,cn的域名全部跳转到google.com.hk,今天早上访问google,不能搜索了,只能打开页面,显示不了搜索结果。估计要不了几天google会被彻底的墙掉了!

完全跨域单点登录实现原理

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

跨域单点登录分为以下两种:

1、跨子域单点登录。如 blog.a.com 和 news.a.com 这2个站点同属一个主域.a.com,实现跨子域单点登录很简单,可以利用cookie,设置Domain为".a.com'即可,这里就不再赘叙。

2、完成跨域单点登录。如 http://www.abc.com/ http://www.xyz.com/ 这2个站点之间实现共享一个身份验证系统,只需在一处地方登录,下面主要谈下这种方式的实现方法。

下面简单说说跨域单点登录实现原理:

当用户第一次访问web 应用系统1的时候,因为还没有登录,会被引导到认证中心进行登录;根据用户提供的登录信息,认证系统进行身份效验,如果通过效验,返回给用户一个认证的凭据;用户再访问别的web应用的时候就会将这个Token带上,作为自己认证的凭据,应用系统接受到请求之后会把Token送到认证中心进行效验,检查Token的合法性。如果通过效验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。所有应用系统共享一个身份认证系统。认证系统的主要功能是将用户的登录信息和用户信息库相比较,对用户进行登录认证;认证成功后,认证系统应该生成统一的认证标志,返还给用户。另外,认证系统还应该对Token进行效验,判断其有效性。 所有应用系统能够识别和提取Token信息要实现SSO的功能,让用户只登录一次,就必须让应用系统能够识别已经登录过的用户。应用系统应该能对Token进行识别和提取,通过与认证系统的通讯,能自动判断当前用户是否登录过,从而完成单点登录的功能。比如说,我现在有3个分站点和1个认证中心(总站)。当用户访问分站点的时候,分站点会发Token到验证中心进行验证。验证中心判断用户是否已经登录。如果未登录,则返回到验证中心登录入口进行登录,否之则返回Token验证到分站点,直接进入分站点。

C#读取Word的内容

下了一个电子书,里面居然全部都是word格式的文件,一点都不便于阅读,连个目录都不好翻,只好把它读出来,弄成html格式的。下面是读取word内容的代码,比较简单了。
[code language="csharp"]
using System;
using System.IO;
using System.Reflection;
using Word;

//----------------------------------------------------------------------
static string WordReader( string path )
{
string WordContent = "";

Word.Application app = new ApplicationClass();

object fileName = path;
object optional = Missing.Value;
object visible = true;
if( File.Exists( fileName.ToString() ) )
{
Word.Document doc = app.Documents.Open(
ref fileName,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref optional,
ref visible,
ref optional,
ref optional,
ref optional,
ref optional );

WordContent = doc.Content.Text;

object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
object originalFormat = Missing.Value;
object routeDocument = Missing.Value;
app.Quit( ref saveChanges, ref originalFormat, ref routeDocument );
}
else
{
return string.Empty;
}

return WordContent;

}
[/code]

工程中引用“Microsoft Word 11.0 object library”的Microsoft COM组件。该组件提供的类和方法来读取Word文档