前言
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:ToolsDocTest 1.docx" "D:ToolsDocTest 1.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);
}