c#批量处理word文档时遇到加密文档如何跳过

1 篇文章 0 订阅

之前写了个简单的批量处理wordexcel文档内容替换的程序给朋友用,在这里

 

后来朋友反映说是当碰到加密了的word时会跳出输入密码的对话框,因为程序是用单线程写的,所以在这种情况下就会卡在那里不处理接下去的事务了。

 

 

 

一开始我也觉得这个应该挺简单的,事先判断一下有没有密码就行了。而且的确有Word.Document.HasPassword属性。不幸的是这个document一定要打开后才能获取到这个属性。

 

之后想着,在打开word文档的时候有个变量就是传密码的“PasswordDocument”,没密码的文档应该不会去用到这个变量,有密码的文档在尝试用这个变量之后,应该会报错然后被try...catch块捕捉到,然后返回就可以了。

 

Word.Application _myWord = new Word.Application();

 

object missing = Type.Missing;

object filepath = filePath as object;

object testPassword = "123";

object visible = false;

Word.Document myDoc = null;

 

try

{

    myDoc = _myWord.Documents.Open(ref filepath, ref missing, ref missing, ref missing, ref testPassword , ref missing,

                                                 ref missing, ref missing, ref missing, ref missing, ref missing,

                                                 ref visible, ref missing, ref missing, ref missing, ref missing);

}

catch (COMException ex)

{

    Console.WriteLine(ex.Message);

    Console.WriteLine();

    return;

}

 

但是不幸的是那个要求输密码的对话框还是跳了出来,只有在点了取消之后才会抛出密码错误异常然后被捕捉到。

(之后在修改excel部分程序的时候,发现这招对excel有用)。

  

在网上搜了些文章,好像VB中这招是可行的,可我只会c#。之后又看到一篇文章(现在找不到在哪了,要不也不会找了那么久),说是可以把那个密码框关掉。

  

于是我尝试了一下,在弹出密码框时候关闭密码框也是会抛出密码错误的异常的。接下去目标就明确了,调用API获取密码框的句柄,然后尝试关闭。

 

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]

internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

 

[DllImport("User32.dll ", EntryPoint = "FindWindowEx", SetLastError = true)]

internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

 

[DllImport("User32.dll ", EntryPoint = "SendMessage", SetLastError = true)]

internal static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam);

 

 

先加几个API方法,第一、第二个可以通过类名和标题来获取所需窗口的句柄,第三个方法可以通过发送消息来关闭窗口。

 

之后需要的是加个:

private System.Windows.Forms.Timer timer1;

 

然后在替换开始的时候设置:

timer1.Enabled = true;

 

并且在Tick事件中进行捕捉:

private void timer1_Tick(object sender, EventArgs e)

{

   IntPtr passworHwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, "密码");

   if (passworHwnd != IntPtr.Zero)

   {

      //0x0010 WM_CLOSE的值

      SendMessage(passworHwnd, 0x0010, IntPtr.Zero, "0");

   }

}

 

对于中文版的office,那个窗口的标题就是“密码”,要是有别的窗口也叫“密码”的话,那就不幸了。那就再增加个类名也可以,这里有个小工来获取类名(网上也很多)。至于具体想怎么找就根据自己不同的需要扩展吧。反正思路就是这样,在成功获取句柄之后我们就能通过发送关闭窗口指令的消息来关闭窗口了。

 

测试证明成功关闭并且捕获到异常,这样就可以顺利的跳过有密码的word文档处理接下去的事务了。有个不足之处就是窗口会闪一下。

 

如果各位有更好的办法的话请大家指教。源码全部在这

 

对于office开发VB的确是好用多了,因为可以录制宏,当然c#也能照着写。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值