本地调用和远端调用

应用开发的角度上模块化是很好代码逻辑复用方法,而模块化构建实现的关键就是如何调用模块化之后的组件,最简单的思路就是像积木一样直接组合使用,这也是最传统的组件的调用方法,即加载组件到进程内存调用执行。

本地调用

常见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对外提供服务

这种远端API非常适应于当前前后端分离的应用架构,而这种资源调用使用token来接入访问,token属于认证和授权技术, 可参见之前相关的介绍。

Login Info

ContentMethodEndpointParameters
Login infoGEThttps://graph.microsoft.com/v1.0/meAuthorization: f"Bearer {access_token}"

Site ID

ContentMethodEndpointParameters
Site-idGEThttps://graph.microsoft.com/v1.0/sites/{your-tenant-domain}.sharepoint.com:/sites/{site-name}Authorization: f"Bearer {access_token}"

SharePoint

ContentMethodEndpointParameters
drive-idGEThttps://graph.microsoft.com/v1.0/sites/{site-id}/drivesAuthorization: f"Bearer {access_token}"
List filesGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root/childrenAuthorization: f"Bearer {access_token}"
List filesGEThttps://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/root:/{folder-path}:/childrenAuthorization: f"Bearer {access_token}"
List filesGEThttps://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/items/{item-id}/childrenAuthorization: f"Bearer {access_token}"
Download fileGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/{item_id}/contentAuthorization: f"Bearer {access_token}"
Upload filePUThttps://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root:/{file_path}:/contentAuthorization: f"Bearer {access_token}"
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Upload filePUThttps://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/{item_id}/contentAuthorization: f"Bearer {access_token}"
Content-Type: application/octet-stream
Transfer-Encoding: chunked

OneNote

ContentMethodEndpointParameters
notebooksGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooksAuthorization: f"Bearer {access_token}"
notebookGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooks/{notebook-id}Authorization: f"Bearer {access_token}"
SectionsGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/notebooks/{notebook-id}/sectionsAuthorization: f"Bearer {access_token}"
SectionGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/sections/{section-id}Authorization: f"Bearer {access_token}"
pagesGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/sections/{section-id}/pagesAuthorization: f"Bearer {access_token}"
pageGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/pages/{page-id}Authorization: f"Bearer {access_token}"
Page contentGEThttps://graph.microsoft.com/v1.0/sites/{site_id}/onenote/pages/{page-id}/contentAuthorization: f"Bearer {access_token}"
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值