golang实现Windows OLE自动化操作的插件库go-ole的使用
golang实现Windows OLE自动化操作的插件库go-ole的使用
Go OLE
Go OLE是用于Windows COM的Go语言绑定库,使用共享库而不是cgo实现。由Yasuhiro Matsumoto开发。
安装
要实验go-ole,可以编译并运行示例程序:
go get github.com/go-ole/go-ole
cd /path/to/go-ole/
go test
cd /path/to/go-ole/example/excel
go run excel.go
示例代码
下面是一个使用go-ole操作Excel的完整示例:
package main
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"log"
)
func main() {
// 初始化COM库
ole.CoInitialize(0)
defer ole.CoUninitialize()
// 创建Excel应用程序对象
unknown, err := oleutil.CreateObject("Excel.Application")
if err != nil {
log.Fatal(err)
}
excel, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer excel.Release()
// 设置Excel可见
oleutil.PutProperty(excel, "Visible", true)
// 添加工作簿
workbooks := oleutil.MustGetProperty(excel, "Workbooks").ToIDispatch()
workbook := oleutil.MustCallMethod(workbooks, "Add").ToIDispatch()
defer workbook.Release()
// 获取活动工作表
sheet := oleutil.MustGetProperty(excel, "ActiveSheet").ToIDispatch()
defer sheet.Release()
// 在单元格A1中写入数据
oleutil.MustPutProperty(sheet, "Cells", 1, 1, "Hello, World!")
// 保存工作簿
oleutil.MustCallMethod(workbook, "SaveAs", "C:\\test.xlsx")
// 关闭Excel
oleutil.PutProperty(excel, "DisplayAlerts", false)
oleutil.MustCallMethod(workbook, "Close")
oleutil.MustCallMethod(excel, "Quit")
}
多线程处理
处理多线程时有两种解决方案:
- 可以将函数或goroutine锁定到单个线程:
runtime.LockOSThread()
defer runtime.UnlockOSThread()
任何解决方案的关键是必须为每个CoInitialize()
调用CoUninitialize()
。
测试
- 从go-ole/test-com-server下载一个发布版本
- 注册COM服务器
- Windows 32位:
c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /nologo c:\path\to\TestCOMServer.dll
- Windows 64位:
c:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /codebase /nologo c:\path\to\TestCOMServer.dll
- Windows 32位:
- 运行
go test
持续集成
已添加Travis-CI和AppVeyor的持续集成配置。
Travis-CI
用于检查Linux上的构建,确保交叉编译时go get
能正常工作。
AppVeyor 用于在Windows上构建,使用(开发中的)测试COM服务器。目前仅用于测试构建并确保代码在Windows上工作。
版本控制
Go OLE使用语义化版本控制进行版本编号,类似于Go语言的版本约定。这意味着主版本将始终与次版本保持向后兼容性。次版本只添加新的功能和更改。修复总是出现在补丁中。
这个约定应该允许你升级到新的次版本和补丁版本,而不会破坏或修改现有代码。
许可证
MIT许可证
更多关于golang实现Windows OLE自动化操作的插件库go-ole的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现Windows OLE自动化操作的插件库go-ole的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go语言实现Windows OLE自动化操作 - go-ole库使用指南
go-ole是一个用于Go语言与Windows OLE/COM对象交互的库,允许Go程序调用Windows COM组件和自动化对象(如Excel、Word等)。下面详细介绍其使用方法。
安装go-ole
go get github.com/go-ole/go-ole
go get github.com/go-ole/go-ole/oleutil
基础使用示例
1. 初始化OLE
package main
import (
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"log"
)
func main() {
// 初始化COM库
err := ole.CoInitialize(0)
if err != nil {
log.Fatal(err)
}
defer ole.CoUninitialize()
// 其他操作...
}
2. 创建COM对象实例
// 创建Internet Explorer实例
func createIE() {
unknown, err := oleutil.CreateObject("InternetExplorer.Application")
if err != nil {
log.Fatal(err)
}
defer unknown.Release()
ie, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer ie.Release()
// 设置IE可见
oleutil.PutProperty(ie, "Visible", true)
// 导航到网页
oleutil.CallMethod(ie, "Navigate", "https://www.example.com")
}
常用操作示例
1. 操作Excel
func excelExample() {
// 创建Excel应用
unknown, err := oleutil.CreateObject("Excel.Application")
if err != nil {
log.Fatal(err)
}
defer unknown.Release()
excel, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer excel.Release()
// 设置Excel可见
oleutil.PutProperty(excel, "Visible", true)
// 获取工作簿集合
workbooks := oleutil.MustGetProperty(excel, "Workbooks").ToIDispatch()
defer workbooks.Release()
// 添加新工作簿
workbook := oleutil.MustCallMethod(workbooks, "Add").ToIDispatch()
defer workbook.Release()
// 获取活动工作表
sheet := oleutil.MustGetProperty(workbook, "ActiveSheet").ToIDispatch()
defer sheet.Release()
// 在A1单元格写入数据
oleutil.MustPutProperty(sheet, "Cells", 1, 1, "Hello from Go!")
// 保存工作簿
oleutil.MustCallMethod(workbook, "SaveAs", "C:\\test.xlsx")
// 关闭Excel
oleutil.MustCallMethod(workbook, "Close", false)
oleutil.MustCallMethod(excel, "Quit")
}
2. 操作Word
func wordExample() {
// 创建Word应用
unknown, err := oleutil.CreateObject("Word.Application")
if err != nil {
log.Fatal(err)
}
defer unknown.Release()
word, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer word.Release()
// 设置Word可见
oleutil.PutProperty(word, "Visible", true)
// 获取文档集合
documents := oleutil.MustGetProperty(word, "Documents").ToIDispatch()
defer documents.Release()
// 添加新文档
document := oleutil.MustCallMethod(documents, "Add").ToIDispatch()
defer document.Release()
// 获取内容范围
content := oleutil.MustGetProperty(document, "Content").ToIDispatch()
defer content.Release()
// 插入文本
oleutil.MustPutProperty(content, "Text", "This is a test document created from Go!")
// 保存文档
oleutil.MustCallMethod(document, "SaveAs", "C:\\test.docx")
// 关闭Word
oleutil.MustCallMethod(document, "Close", false)
oleutil.MustCallMethod(word, "Quit")
}
高级用法
1. 处理事件
func eventExample() {
// 创建IE实例
unknown, err := oleutil.CreateObject("InternetExplorer.Application")
if err != nil {
log.Fatal(err)
}
defer unknown.Release()
ie, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer ie.Release()
// 设置事件接收器
eventSink := &ole.IEventSink{
OnInvoke: func(disp *ole.IDispatch, dispid int, lcid uint32, flags int16, params *ole.DISPPARAMS) (result *ole.VARIANT, err error) {
if dispid == 0x000000fc { // DocumentComplete事件
url := oleutil.MustGetProperty(disp, "LocationURL").ToString()
log.Printf("Document loaded: %s", url)
}
return nil, nil
},
}
// 连接事件
oleutil.ConnectObject(ie, eventSink, &ole.GUID{0x34A715A0, 0x6587, 0x11D0, [8]byte{0x92, 0x4A, 0x00, 0x20, 0xAF, 0xC7, 0xAC, 0x4D}})
// 导航网页
oleutil.PutProperty(ie, "Visible", true)
oleutil.CallMethod(ie, "Navigate", "https://www.example.com")
// 等待用户关闭IE
select {}
}
2. 调用带命名参数的方法
func namedParamsExample() {
// 创建WScript.Shell对象
unknown, err := oleutil.CreateObject("WScript.Shell")
if err != nil {
log.Fatal(err)
}
defer unknown.Release()
shell, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal(err)
}
defer shell.Release()
// 使用命名参数调用Popup方法
// 等价于VBScript: WScript.Shell.Popup "Hello", 5, "Title", 64
result := oleutil.MustCallMethod(
shell,
"Popup",
"Hello", // 消息
5, // 等待时间(秒)
"Title", // 标题
64, // 按钮类型(0=OK,64=Information图标)
)
defer result.Clear()
log.Printf("Popup returned: %d", result.Val)
}
注意事项
- 线程模型: OLE操作必须在同一线程中完成,不要在goroutine中直接调用OLE方法
- 资源释放: 确保所有创建的COM对象都正确释放(使用Release())
- 错误处理: 检查所有可能返回错误的操作
- 初始化: 必须调用ole.CoInitialize()和ole.CoUninitialize()
通过go-ole库,Go程序可以方便地与Windows平台上的各种COM组件交互,实现强大的自动化功能。