为 3D 打印机启用自定义 USB 接口
本主题中所述的体系结构支持 v3 和 v4 打印生态系统中的自定义 USB 接口 3D 打印机。 标准端口监视器 3dmon.dll 会将 3D 打印作业命令转发到使用本地服务凭据运行的 Windows 3DPrintService。 该服务加载合作伙伴 DLL 并与其通信,以执行 3D 打印作业所需的自定义命令。 合作伙伴 DLL 以及 3dmon.dll 和 3dprintservice.exe 可再发行组件由设备的 USB 驱动程序包安装。 合作伙伴 DLL 必须实现并导出一组函数才能与 3DPrintService 通信。 与打印后台处理程序服务交互所需的其余功能在 3dmon.dll 中实现。
注意
此体系结构要求合作伙伴 DLL 多实例线程安全。
架构决策
3DPrintService Windows 服务用于在打印工作流期间在合作伙伴提供的 DLL 中加载和调用特定定义的 API。 这些 API 允许与打印机通信。
KMDF USB 筛选器驱动程序包发布在 Windows 更新 上,以便通过 PnP 安装受支持的 3D 打印机。 KMDF 驱动程序安装合作伙伴软件并创建 3D 打印机设备节点。 3D 打印机设备节点是使用来自 Windows 更新的合作伙伴发布的 v4 打印驱动程序安装的。
打包决策
二进制文件和二进制依赖项
该体系结构使用硬件制造商在 Windows 更新上发布的驱动程序。 此驱动程序包括以下 Microsoft 提供的可再发行二进制文件及其依赖项:
3dmon.dll
3dprintservice.exe
ms3dprintusb.sys
内核模式 USB 筛选器驱动程序
KMDF 驱动程序由合作伙伴发布,由下图中所示的组件组成。 这与设备与硬件 ID(通常为 VID 和 PID)匹配。 驱动程序在安装时创建一个 3D 打印机设备节点,这会触发打印队列和切片器驱动程序的安装。 合作伙伴为创建的 3D 打印机设备节点提供 v4 打印机驱动程序。
MS3DPrintUSB.sys
内核模式设备驱动程序,用于在 Enum\3DPrint 下创建 3D 打印机开发节点。 PnP 子系统通过根据 Winusb.sys 创建的设备节点直接匹配 VID 和 PID 来调用它。 驱动程序 .inf 文件设置用于设置 3DPrintService 的自定义 DLL(如果尚未安装在系统上)。
3dmon.dll
3DMon.dll 是一个 Microsoft 发布的端口监视器,由后台处理程序调用以与 3D 打印机通信的可再发行二进制文件。
3dprintservice.exe
3DPrintService.exe 是在驱动程序安装过程中作为 Windows 服务安装的 Microsoft 发布的二进制文件。 3DMon 与此服务通信,以使用 3D 打印机执行打印、双向等操作。
Partnerimpl.dll
Partnerimp.dll 是合作伙伴对已发布的 Microsoft 接口的实现。 DLL 使用其协议与合作伙伴的设备通信。 3DPrintService.exe 会子啊运行时加载此 DLL,以驱动 3D 打印机设备的操作。
打印机使用顺序
后台处理程序与向 3DPrintService windows 服务发送命令的 3dmon.dll 通信
3DPrintService.exe 使用 NetworkService 的帐户凭据运行
只要使用 3D 打印机,后台处理程序就会通过 3dmon.dll 向 3DPrintService 发送命令
3DPrintService 会处理命令并在运行时在合作伙伴提供的实现 DLL 上调用 API
3DPrintService 将合作伙伴提供的 DLL 的响应移交回后台处理程序
接口和交互
合作伙伴 DLL 必须导出以下 API 函数:
HRESULT Install([in] LPCWSTR args)
此 API 是可选的,制造商可以使用此 API 为其设备安装自定义软件或注册。 例如,安装设备驱动程序包中包含的建模。 此 API 使用 SYSTEM 凭据调用以启用安装。
DWORD PrintApiSupported()
第三方制造商使用此 API 来指示支持的 3D 打印服务 API 的版本。 下面的 API 与 3DPrintService 版本 1 兼容。
HRESULT InitializePrint(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)
在开始初始化打印机的打印事件之前调用此 API。 打印机可以在 ppPartnerData 参数中保存作业特定状态。 此调用类似于 StartDocPort 调用。
jobId - 用于跟踪作业的作业 ID
portName - 3D 打印机的端口名称
printerName - 此打印作业要发送到的打印机的名称
ppPartnerData - 指向可用于存储任何作业特定数据的指针的指针
HRESULT PrintFile([in] DWORD jobId, [in] LPWSTR portName, [in] LPWSTR printerName, [in] LPWSTR pathToRenderedFile,[in]LPVOID* ppPartnerData)
第三方制造商使用此 API 在其打印机上打印文档。
jobId - 用于跟踪作业的作业 ID
portName - 3D 打印机的端口名称
printerName - 打印作业要发送到的打印机的名称
pathToRenderedFile - 执行呈现后到后台处理程序文件位置的 UNC 路径。 第三方制造商从此位置处理文件,并在其设备上打印文档
ppPartnerData - 指向在 InitializePrint API 调用期间发出用于存储合作伙伴特定数据设置的指针的指针。
可以使用端口名称从注册表获取 printerName。 第三方制造商可能无法使用端口名称与其设备通信。 打印机名称在 Windows 计算机上是唯一的,其软件将能够识别要打印作业的打印机。 可在以下注册表项中找到计算机上处于活动状态的所有打印机:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers
HRESULT Query(_In_ LPCWSTR command, _In_ LPCWSTR commandData, _Out_ LPWSTR resultBuffer, _Out_ resultBufferSize, , _In_ LPVOID* ppPartnerData)
command - 作为查询发送的字符串命令
commandData - 命令参数(可选)
resultBuffer - 调用查询参数的结果>
resultBufferSize - 结果缓冲区字符串的大小
ppPartnerData - 指向当前合作伙伴 DLL 实例的指针
3Dprint 服务调用伙伴 DLL,以获取要为命令分配的缓冲区的大小。
分配内存以保存响应字符串后,将再次调用 DLL 以获取实际结果。
DLL 可以使用先前 IntializePrint() 调用中的实例数据与设备通信,而无需每次调用 Query() 函数时都打开新的通道。
此 API 用于与打印机通信,以获取有关设备配置、打印进度的信息,或通知合作伙伴 DLL 设备拔出事件。
制造商必须支持以下命令:
命令 | CommandData | 输出 | 注释 |
---|---|---|---|
\\Printer.3DPrint:JobStatus | Job Commenced = {"Status": "ok"}, Status to be used on Completion {"Status": "Completed"} | 后台处理程序将在打印队列 UI 中显示任何返回的值。 这样,设备就可以在打印队列 UI 上的打印过程中显示相关信息。 设备可以在此处返回任意字符串(例如“Busy”或“33%complete”),这将在打印队列作业状态中逐字显示。 | |
\\Printer.3DPrint:JobCancel | {"Status": "Completed"} | 当用户取消打印时,后台处理程序将调用此命令。 当取消成功且句柄和线程已关闭时,合作伙伴 DLL 将返回此值。 | |
\\Printer.Capabilities:Data | 符合 PrintDeviceCapabilites (PDC) 架构的 XML 字符串。 | PDC 查询由希望获取有关打印机的详细信息的应用调用。 数据用于描述设备的功能,如果驱动程序依赖于 Microsoft 切片器,则可以包含切片器设置。 有关 PDC 示例,请参见下文。 | |
\\Printer.3DPrint:Disconnect | {"Status": "OK"} | 每当打印机设备发生 PnP 断开连接时,就会触发此查询。 合作伙伴可以执行任何所需的操作,例如关闭任何打开的句柄以允许正确重新连接。 | |
\\Printer.3DPrint:Connect | {"Status":"OK"} | 每当打印机设备发生 PnP 连接时,就会触发此查询。 合作伙伴可以执行任何必需的操作。 |
打印设备功能 XML
以下打印设备功能 XML 可用作示例:
<?xml version="1.0"?>
<PrintDeviceCapabilities
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="https://www.w3.org/2001/XMLSchema"
xmlns:xml="https://www.w3.org/XML/1998/namespace"
xmlns:psk="https://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"
xmlns:psk3d="https://schemas.microsoft.com/3dmanufacturing/2013/01/pskeywords3d"
xmlns:psk3dx="https://schemas.microsoft.com/3dmanufacturing/2014/11/pskeywords3dextended"
xmlns:pskv="https://schemas.microsoft.com/3dmanufacturing/2014/11/pskeywordsvendor"
xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:psf2="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
xmlns="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
version="2">
<CapabilitiesChangeID xsi:type="xsd:string">{9F58AF07-DCB6-4865-8CA3-A52EA5DCB05F}</CapabilitiesChangeID>
<psk3d:Job3DOutputArea psf2:psftype="Property">
<psk3d:Job3DOutputAreaWidth>150001</psk3d:Job3DOutputAreaWidth>
<psk3d:Job3DOutputAreaDepth>150001</psk3d:Job3DOutputAreaDepth>
<psk3d:Job3DOutputAreaHeight>150001</psk3d:Job3DOutputAreaHeight>
</psk3d:Job3DOutputArea>
<psk3d:Job3DMaterials psf2:psftype="Property">
<psk3dx:MaterialPLA>
<psk:DisplayName>PLA</psk:DisplayName>
<psk3d:Job3DMaterialType>psk3d:PLA</psk3d:Job3DMaterialType>
<psk3d:MaterialColor>#FFFFFFFF</psk3d:MaterialColor>
<psk3dx:platformtemperature>0</psk3dx:platformtemperature>
<psk3dx:filamentdiameter>1750</psk3dx:filamentdiameter>
<psk3dx:filamentcalibrationoverride>1.0</psk3dx:filamentcalibrationoverride>
<psk3dx:extrudertemperature>207</psk3dx:extrudertemperature>
<psk3dx:SpeedFactor>1.0</psk3dx:SpeedFactor>
<psk3dx:SetupCommands>
<!-- Executed during pre-commands: nozzle pre-heating, priming, etc -->
<psk3dx:command>M104 S207 T1</psk3dx:command>
<psk3dx:command>M140 S50</psk3dx:command>
</psk3dx:SetupCommands>
<psk3dx:SelectCommands>
<!-- Executed during printing: T0/T1 selection, nozzle wiping sequence,turn fan on/off/gradual, retract the material, temperature, etc-->
<psk3dx:command>; PLA on</psk3dx:command>
<psk3dx:command>M108 T1</psk3dx:command>
</psk3dx:SelectCommands>
<psk3dx:DeselectCommands>
<!-- Executed during printing: retract the material, park the nozzle, reduce temperature, etc -->
<psk3dx:command>; PLA off</psk3dx:command>
</psk3dx:DeselectCommands>
</psk3dx:MaterialPLA>
</psk3d:Job3DMaterials>
<psk3dx:customStatus>Slicing</psk3dx:customStatus>
<psk3dx:userprompt>Confirm the 3D printer is calibrated and ready for the next print</psk3dx:userprompt>
<!— Additional Slicer settings follow (optional) -->
</PrintDeviceCapabilities>
对于没有板载显示和按钮的 3D 打印机,允许用户在打印开始时与设备交互,我们主张返回具有适当用户提示消息集的 PDC xml,如 psdk3dx:userPrompt 中所示。 这是为了防止在现有打印的顶部启动新打印。 自定义状态消息 <psk3dx:customStatus> 用于在切片期间显示任何消息。
HRESULT Cleanup(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)
dwJobId - 用于跟踪后台处理程序中的作业的作业 ID
pPortName - 3D 打印机的端口名称
pPrinterName - 此打印作业要发送到的打印机的名称
ppPartnerData - 指向在 InitializePrint API 调用期间保存作业特定数据的指针的指针
在打印作业成功完成或打印作业上的取消查询完成时调用清理。 它为合作伙伴 DLL 提供了清理为此打印初始化的资源的机会。
HRESULT UnInstall([in]LPCWSTR args)
卸载 3D 打印机设备时会调用此 API,并提供一种机制供制造商卸载他们可能已安装的软件。