Rust调用WPS转换Word为PDF

2023-04-27 15:19:16 浏览数 (2)

前言

https://crates.io/crates

COM接口名

MS控件名

name

WPS文字

KWPS.Aplication

WPS的Excel

KET.Application

WPS的演示文档

KWPP.Application

Word

Word.Application

Excel

Excel.Application

Powerpoint

Powerpoint.Application

概念

ActiveX、OLE、COM 之间的关系到底是什么样的?

COM是一套语言无关的二进制接口规范,它定义了一套实现面向对象的组件的规则。

GUID,IID,IUnknow,IDL,都是COM规范定义的概念,它规定了对象接口如何声明,对象如何创建销毁,对象生命周期如何管理,接口如何继承和聚合。

OLE 2(OLE1已经死了)是基于COM接口的一套应用程序直接实现数据交换和协作的规范,主要用于Office系列。

ActiveX是基于COM接口的UI 组件规范,主要用来实现语言无关的可视控件,多用于浏览器和快速应用开发领域比如 VB。

此外还有几个基于COM的框架,比如 DirectX,Media Foundation等。

OLE是一个通讯规范。OLE 1.0的时候COM还不存在,通讯的时候用的是DDE,所以OLE曾经不是基于COM的。

OLE 2.0就是基于COM了。考虑到OLE 1.0现在已经基本没人用了,说OLE是基于COM也没有什么问题。微软目前提到OLE的时候一般是特指复合文档(比如在WordPad里面插入MSPaint这样),除非加一个2.0后缀。一些人继续用OLE这个名称称呼所有OLE旗下的技术(ActiveX,剪贴板对象,拖放支持等等)。

ActiveX控件是OLE 2.0的简化版本,但是微软市场部又用ActiveX这个名字推广了Active Scripting和Active Document等等其他浏览器扩展技术,所以造成歧义。

现在提到ActiveX,一般是特指面向Internet Explorer网页开发者而开发,和java小程序有竞争的控件。广义的ActiveX就是所有COM对象了。

midl.exe

midl.exe是Microsoft的接口定义语言(Interface Definition Language,IDL)编译器,用于从IDL文件生成C/C 头文件和导入库,以供COM客户端和服务器使用。 midl.exe通常随Visual Studio和Windows SDK一起发布。

主要有以下三种获取方式:

(1) Visual Studio安装目录下。一般路径为:

C:Program Files (x86)Microsoft Visual Studio2019CommunityVCToolsMSVC14.24.28314binHostX86x86midl.exe

(2) Windows SDK安装目录。路径为:

C:Program Files (x86)Windows Kits10bin<arch>midl.exe <arch>为x86、x64、arm或arm64,对应不同平台。

(3) 在Visual Studio的“开发人员命令提示”工具中直接运行midl命令。这会自动调用Visual Studio安装的midl.exe。 所以通常使用Visual Studio的此命令提示工具是使用midl.exe的最简单方式。

简单调用COM示例

https://kennykerr.ca/rust-getting-started/windows-or-windows-sys.html

https://github.com/microsoft/windows-rs

添加依赖

代码语言:javascript复制
[dependencies.windows]
version = "0.48"
features = [
    "Win32_System_Com",
]

示例代码

代码语言:javascript复制
use windows::{core::*, Win32::System::Com::*};

fn main() -> Result<()> {
    unsafe {
        let uri = CreateUri(w!("https://www.psvmc.cn"), Uri_CREATE_CANONICALIZE, 0)?;
        let domain = uri.GetDomain()?;
        let port = uri.GetPort()?;

        println!("{domain} ({port})");
        Ok(())
    }
}

调用WPS的COM接口

生成IDL文件

以WPS文字为例,我们在类厂中可以找到kwps.Application

找到{000209FF-0000-4b30-A977-D214852036FF}

打开

代码语言:javascript复制
HKEY_CLASSES_ROOTWOW6432NodeCLSID{000209FF-0000-4b30-A977-D214852036FF}TypeLib

找到对应的值{00020905-0000-4b30-A977-D214852036FF}

我们通过TypeLib的CLSID,找到了WPS文字的idl生成的接口二进制文件的存放位置:

代码语言:javascript复制
HKEY_CLASSES_ROOTWOW6432NodeTypeLib{00020905-0000-4B30-A977-D214852036FF}

可以看到WPS文字的API接口信息,保存在wpsapi.dll

wpsapi.dll不仅包含了代码信息,也将tlb嵌入了它的资源中。我们通过oleview.exe -> File ->View TypeLib,可以查看到WPS文字所有的API接口,对于微软Office亦是如此。不仅我们可以看到它的接口,甚至还可以看到其反编译生成的idl代码:

D:Program FilesWPS OfficeWPS Office11.1.0.14036office6wpsapi.dll

获取IDL文件并生成Rust接口定义。

使用oleview生成idl文件

oleview的位置,双击打开

D:Windows Kits10bin10.0.17763.0x64oleview.exe

找到WPS目录下的wpsapi.dll

D:Program FilesWPS OfficeWPS Office11.1.0.14036office6wpsapi.dll

使用oleview.exe打开后另存文件wpsapi.IDL

添加依赖

代码语言:javascript复制
[dependencies.windows]
version = "0.48"
features = [
    "Win32_System_Com",
    "Win32_System_Ole"
]

代码

尚未实现。

文档转PDF程序

WPS转PDF命令行

https://github.com/lm3515/WPSToPDF

微软Office转PDF

https://github.com/cognidox/OfficeToPDF

这个只支持微软的Office。

下载后执行

代码语言:javascript复制
OfficeToPDF.exe "D:ToolsDocTest1.docx" "D:ToolsDocTest1.pdf"

调用本地EXE

代码语言:javascript复制
use std::process::Command;

fn main() {
    let output = Command::new("cmd.exe")
        .arg("/C chcp 65001 & ipconfig | findstr /i ipv4")
        .output()
        .expect("failed to execute process");
    let stdout = String::from_utf8_lossy(&output.stdout)
        .to_string()
        .replace("rn", ";");

    println!("{:?}", stdout);
}

0 人点赞