应用开发的角度上模块化是很好代码逻辑复用方法,而模块化构建实现的关键就是如何调用模块化之后的组件,最简单的思路就是像积木一样直接组合使用,这也是最传统的组件的调用方法,即加载组件到进程内存调用执行。
本地调用
常见Windows下的dll和Linux下的so文件都是编译后可复用的组件,操作系统底层传统都是使用C/C++,所以这些系统级别的组件就是C/C++语言编译的二进制文件,而对半编译和解释型的语言,它们对应的组件则是机器码或者脚本文件。
Component Call
组件的加载和调用还有一个很关键的问题在于组件的运行时(runtime),毕竟不同语言实现的代码逻辑块依赖的运行时是不同的,传统C/C++称为系统编程语言,不仅仅是因为诸如操作系统内核等底层都是由它们编写,还是因为它们实现的代码编译出来的二进制码的运行时可近似认为就是CPU这种底层逻辑硬件,所以win32 API的dll原生就需要同样依赖这种机器运行时的编译语言调用,比如Rust,Go等就可以近似原生支持调用C/C++组件,虽然编译时的适配必不可少。
Language Binding Call
稍微复杂得就是依赖于不同运行时得解释型语言之间以及解释型语言和编译型语言之间的组件调用,因为它们彼此运行时得不同,所以就需要互操作库(interop lib)来作为桥阶层(bridging layer)以接入其他运行时中调用相应得组件。
因为系统编程语言和硬件底层的交互比较繁琐,所以构建其上得应用往往是由应用编程语言和其运行时实现,比如python,Java,node.js,以及微软世界得.net,这些托管语言得特点就是依赖于运行时而不直接和硬件交互,所以比较常见得需求就是应用编程语言对系统组件的调用,比如python对Windows系统组件调用得互操作库有pywin32和pythonnet,前者是和C/C++得win32 API得桥接,后者是和.net环境得桥接。
目前Windows环境下得office应用的调用组件已经从原生得COM变为.net的C# assembly,所以需要通过pythonnet来实现对office应用得调用,以下是检查是否可以正常加载OneNote .NET Interop组件的代码。
import sys
import os
print("=== Access OneNote via .NET Interop ===\n")
# Check if pythonnet is installed
try:
import clr
print("✓ pythonnet installed\n")
except ImportError:
print("✗ pythonnet not installed")
print("Install command: pip install pythonnet")
print("\nAttempting to install...")
import subprocess
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", "pythonnet"])
print("✓ Installation successful, please rerun this script")
except:
print("✗ Installation failed, please run manually: pip install pythonnet")
sys.exit(1)
# Load OneNote Interop Assembly
try:
print("Loading OneNote Interop Assembly...")
# Method 1: Load from GAC
try:
clr.AddReference("Microsoft.Office.Interop.OneNote, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
print("✓ Loaded from GAC successfully\n")
except:
# Method 2: Load from file
print(" Failed to load from GAC, trying file path...")
assembly_path = r"C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.OneNote\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.OneNote.dll"
if os.path.exists(assembly_path):
clr.AddReference(assembly_path)
print(f"✓ Loaded from file successfully: {assembly_path}\n")
else:
print(f"✗ Assembly file not found")
sys.exit(1)
# Import required types
from Microsoft.Office.Interop.OneNote import Application, HierarchyScope
# Create OneNote Application object
print("Creating OneNote Application...")
onenote = Application()
print("✓ OneNote object created successfully\n")
# Call GetHierarchy
print("Calling GetHierarchy...")
# In pythonnet 3.0, out parameters are automatically returned
xml = onenote.GetHierarchy("", HierarchyScope.hsNotebooks)
# Check result
if xml:
print(f"✓ GetHierarchy succeeded!")
print(f" XML length: {len(xml)}")
print(f" First 500 characters:\n{xml[:500]}")
else:
print("✗ Returned empty XML")
except Exception as e:
print(f"✗ Error: {type(e).__name__}: {e}")
import traceback
traceback.print_exc()
print("\n=== Test Complete ===\n")
print("If successful, you can use this method to access OneNote!")
从检查代码中可以看出Assembly的名字和路径比较关键,可以通过Power Shell来检查
-
检查是否注册OneNote.Application ProgID
PS C:\Users\blabla> reg query "HKCR\OneNote.Application" /s
HKEY_CLASSES_ROOT\OneNote.Application
(Default) REG_SZ Application Class
HKEY_CLASSES_ROOT\OneNote.Application\CLSID
(Default) REG_SZ {DC67E480-C3CB-49F8-8232-60B0C2056C8E}
HKEY_CLASSES_ROOT\OneNote.Application\CurVer
(Default) REG_SZ OneNote.Application.15
-
检查注册的Class ID
PS C:\Users\blabla> reg query "HKCR\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}" /s
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}
(Default) REG_SZ Application2 Class
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\InprocServer32
Class REG_SZ Microsoft.Office.Interop.OneNote.Application2Class
Assembly REG_SZ Microsoft.Office.Interop.OneNote, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C
RuntimeVersion REG_SZ v2.0.50727
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\InprocServer32\15.0.0.0
Class REG_SZ Microsoft.Office.Interop.OneNote.Application2Class
Assembly REG_SZ Microsoft.Office.Interop.OneNote, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C
RuntimeVersion REG_SZ v2.0.50727
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\LocalServer32
(Default) REG_SZ C:\Program Files\Microsoft Office\Root\Office16\ONENOTE.EXE
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\ProgID
(Default) REG_SZ OneNote.Application.15
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\TypeLib
(Default) REG_SZ {0EA692EE-BB50-4E3C-AEF0-356D91732725}
HKEY_CLASSES_ROOT\CLSID\{DC67E480-C3CB-49F8-8232-60B0C2056C8E}\VersionIndependentProgID
(Default) REG_SZ OneNote.Application
从注册表打印中可以看出
- Assembly: Microsoft.Office.Interop.OneNote
- Version: 15.0.0.0
- PublicKeyToken: 71e9bce111e9429c
GAC的路径规则如下所以可以构造出路径
C:\Windows\assembly\GAC_MSIL\{AssemblyName}\{Version}__{PublicKeyToken}\{AssemblyName}.dll
此外也可以直接使用命令查询
PS C:\Users\blabla> [System.Reflection.Assembly]::ReflectionOnlyLoad("Microsoft.Office.Interop.OneNote, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C").Location
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.Office.Interop.OneNote\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.OneNote.dll
然后通过构建OneNote对象就可以使用OneNote COM API
OneNote COM API
- Application Object
from Microsoft.Office.Interop.OneNote import Application
# 创建 OneNote 应用程序对象
onenote = Application()
- GetHierarchy - 获取层次结构
from Microsoft.Office.Interop.OneNote import HierarchyScope
# 语法: GetHierarchy(startNodeID, scope)
xml = onenote.GetHierarchy(node_id, scope)
# Scope 选项:
# - HierarchyScope.hsNotebooks # 只获取笔记本列表
# - HierarchyScope.hsSections # 获取到分区级别
# - HierarchyScope.hsPages # 获取到页面级别(不含内容)
# - HierarchyScope.hsAll # 获取所有层级
# 获取所有笔记本
xml_notebooks = onenote.GetHierarchy("", HierarchyScope.hsNotebooks)
# 获取特定笔记本的所有页面
xml_pages = onenote.GetHierarchy(notebook_id, HierarchyScope.hsPages)
远端调用
所谓的远端调用就是通过消息传递的方式实现代码逻辑的调用,这种消息传递的方式往往是由所谓的通信协议来定义并由两端实现,不同端的交互自然也形成网络的概念,信息技术的发展中存在各种不同类型的网络,而其中最为知名和广泛使用的就是TCP/IP协议规范的计算机网络,此外随着web技术的发展和普及,最广泛使用的远端网络调用就是基于http的REST API,而微软把自身的应用云化之后使用统一的Microsoft Graph API对外提供服务
- What is Microsoft Graph? - Training | Microsoft Learn
- Graph Explorer | Try Microsoft Graph APIs - Microsoft Graph
这种远端API非常适应于当前前后端分离的应用架构,而这种资源调用使用token来接入访问,token属于认证和授权技术, 可参见之前相关的介绍。
Login Info
| Content | Method | Endpoint | Parameters |
| Login info | GET | https://graph.microsoft.com/v1.0/me | Authorization: f"Bearer {access_token}" |
Site ID
| Content | Method | Endpoint | Parameters |
| Site-id | GET | https://graph.microsoft.com/v1.0/sites/{your-tenant-domain}.sharepoint.com:/sites/{site-name} | Authorization: f"Bearer {access_token}" |
SharePoint
| Content | Method | Endpoint | Parameters |
| drive-id | GET | https://graph.microsoft.com/v1.0/sites/{site-id}/drives | Authorization: f"Bearer {access_token}" |
| List files | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root/children | Authorization: f"Bearer {access_token}" |
| List files | GET | https://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/root:/{folder-path}:/children | Authorization: f"Bearer {access_token}" |
| List files | GET | https://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/items/{item-id}/children | Authorization: f"Bearer {access_token}" |
| Download file | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/{item_id}/content | Authorization: f"Bearer {access_token}" |
| Upload file | PUT | https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root:/{file_path}:/content | Authorization: f"Bearer {access_token}" Content-Type: application/octet-stream Transfer-Encoding: chunked |
| Upload file | PUT | https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/{item_id}/content | Authorization: f"Bearer {access_token}" Content-Type: application/octet-stream Transfer-Encoding: chunked |
OneNote
| Content | Method | Endpoint | Parameters |
| notebooks | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooks | Authorization: f"Bearer {access_token}" |
| notebook | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooks/{notebook-id} | Authorization: f"Bearer {access_token}" |
| Sections | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooks/{notebook-id}/sections | Authorization: f"Bearer {access_token}" |
| Section | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/sections/{section-id} | Authorization: f"Bearer {access_token}" |
| pages | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/sections/{section-id}/pages | Authorization: f"Bearer {access_token}" |
| page | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/pages/{page-id} | Authorization: f"Bearer {access_token}" |
| Page content | GET | https://graph.microsoft.com/v1.0/sites/{site_id}/onenote/pages/{page-id}/content | Authorization: f"Bearer {access_token}" |
4610

被折叠的 条评论
为什么被折叠?



