修改已Release的后台JOB

本文介绍了如何在SAP系统中修改已发布的后台job。通过SM37事务码选择目标job,进入更改模式,即可调整job步骤。此方法避免了删除重建的繁琐操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  以前一直认为后台job只要release以后,就不能再修改了,每次都将任务删除,然后重新建。今天在sap工作者群中,听某位大大介绍经验,才知道原来后台job也可以修改!马上登陆培训系统去小试了一把,确实可以修改~!

  首先进入sm37,选择已经release的任务(已经完成的任务当然不能修改。。。)

打上勾以后,点击上方job----change  出现任务画面以后,点击任务step

 

选中其中一个步骤,点击step --- change 便可以修改步骤了

<think>我们正在使用Go语言的go-ole库来实现打印管理功能。go-ole是一个用于在Go中操作OLE(对象链接与嵌入)的库,它允许我们与Windows的COM对象进行交互。打印管理通常涉及与Windows打印API的交互,我们可以通过OLE自动化来实现。 目标:实现打印管控功能,可能包括获取打印机列表、设置默认打印机、暂停/继续打印任务、取消打印任务等。 步骤: 1. 初始化OLE库。 2. 创建打印管理相关的COM对象(例如,使用Windows Script Host的Network对象来操作打印机,或者使用打印管理专用的COM接口)。 3. 调用相应的方法来实现功能。 4. 释放资源。 注意:由于打印管理涉及多个方面,我们可能需要使用不同的COM对象。例如: - 使用WScript.Network对象来设置默认打印机。 - 使用打印管理接口(如PrintQueue、PrintServer等)来管理打印任务,但这些通常是在.NET中使用的,在COM中可能需要使用其他接口。 实际上,Windows中管理打印机的COM接口可能较为复杂,我们可以参考微软的文档。常见的做法是使用Win32 API或.NET框架,但通过go-ole我们可以调用COM接口。 以下是一个使用WScript.Network对象设置默认打印机的示例: 但是,请注意,WScript.Network对象提供的方法有限,它只能设置默认打印机,不能管理打印任务。对于更复杂的打印任务管理,我们需要使用其他接口,如打印后台处理程序API(WinSpool)的COM版本。然而,WinSpool通常是通过Win32 API调用的(C++),但我们可以通过COM调用它,或者直接使用syscall调用Win32 API。 考虑到go-ole的特性,我们可以尝试调用WinSpool的COM接口(如果存在),或者使用OLE调用Win32 API(但OLE通常用于自动化对象,Win32 API是函数调用)。实际上,我们可能更倾向于使用syscall来调用WinSpool API,因为这是更直接的方式。但是,用户要求使用go-ole,所以我们将尝试使用OLE调用WMI(Windows Management Instrumentation)来管理打印机,因为WMI提供了丰富的管理功能,并且可以通过COM访问。 因此,我们可以有两个方向: 1. 使用WScript.Network对象进行简单的打印机设置(如设置默认打印机)。 2. 使用WMI进行更复杂的打印管理(如枚举打印机、管理打印作业等)。 下面我们分别给出示例: 一、使用WScript.Network设置默认打印机: 步骤: a. 初始化OLE b. 创建WScript.Network对象 c. 调用SetDefaultPrinter方法 示例代码: ```go package main import ( "fmt" "log" "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" ) func main() { // 初始化OLE ole.CoInitialize(0) defer ole.CoUninitialize() // 创建WScript.Network对象 unknown, err := oleutil.CreateObject("WScript.Network") if err != nil { log.Fatal(err) } defer unknown.Release() network, err := unknown.QueryInterface(ole.IID_IDispatch) if err != nil { log.Fatal(err) } defer network.Release() // 调用SetDefaultPrinter方法,设置默认打印机名称为"YourPrinterName" printerName := "YourPrinterName" res, err := oleutil.CallMethod(network, "SetDefaultPrinter", printerName) if err != nil { log.Fatal(err) } // 检查结果 fmt.Printf("SetDefaultPrinter result: %v\n", res) } ``` 二、使用WMI管理打印机(例如枚举打印机、管理打印作业) 使用WMI需要知道相应的WMI类,例如: - Win32_Printer:表示打印机 - Win32_PrintJob:表示打印作业 我们可以通过WMI执行查询或调用方法。 示例:枚举所有打印机 ```go package main import ( "fmt" "log" "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" ) func main() { // 初始化OLE ole.CoInitialize(0) defer ole.CoUninitialize() // 创建WbemScripting.SWbemLocator对象 locator, err := oleutil.CreateObject("WbemScripting.SWbemLocator") if err != nil { log.Fatal(err) } defer locator.Release() wmi, err := locator.QueryInterface(ole.IID_IDispatch) if err != nil { log.Fatal(err) } defer wmi.Release() // 连接到本地WMI服务 serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer") if err != nil { log.Fatal(err) } service := serviceRaw.ToIDispatch() defer service.Release() // 查询Win32_Printer类 resultRaw, err := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_Printer") if err != nil { log.Fatal(err) } result := resultRaw.ToIDispatch() defer result.Release() // 遍历结果 countVar, err := oleutil.GetProperty(result, "Count") if err != nil { log.Fatal(err) } count := int(countVar.Val) for i := 0; i < count; i++ { itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i) if err != nil { log.Fatal(err) } item := itemRaw.ToIDispatch() defer item.Release() name, err := oleutil.GetProperty(item, "Name") if err != nil { log.Fatal(err) } fmt.Printf("Printer: %s\n", name.ToString()) } } ``` 管理打印作业(例如暂停、继续、取消)可以通过调用Win32_PrintJob对象的方法。但是请注意,操作打印作业需要权限。 示例:取消所有打印作业 ```go // 假设我们已经获取了打印作业的集合 // 查询:SELECT * FROM Win32_PrintJob resultRaw, err := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_PrintJob") if err != nil { log.Fatal(err) } result := resultRaw.ToIDispatch() defer result.Release() countVar, err := oleutil.GetProperty(result, "Count") if err != nil { log.Fatal(err) } count := int(countVar.Val) for i := 0; i < count; i++ { itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i) if err != nil { log.Fatal(err) } item := itemRaw.ToIDispatch() defer item.Release() // 调用Delete方法取消作业 _, err = oleutil.CallMethod(item, "Delete") if err != nil { log.Fatal(err) } fmt.Println("Print job deleted") } ``` 注意:上述代码仅为示例,实际应用中需要处理错误和异常,并确保操作的安全性(例如,不要随意删除所有打印作业)。 总结: 使用go-ole,我们可以通过创建COM对象并调用其方法来实现打印管理功能。对于简单的设置默认打印机,可以使用WScript.Network;对于复杂的打印任务管理,可以使用WMI。 但是,请注意,WMI的操作可能比较慢,而且需要管理员权限。另外,对于打印任务管理,Win32 API(winspool.drv)可能是更直接和高效的方式,但go-ole并不直接支持调用Win32 API。因此,如果性能要求高,可能需要使用syscall来调用Win32 API,但这超出了go-ole的范围。 如果用户坚持使用go-ole,那么WMI是一个可行的方案。 相关问题: 1. 如何通过go-ole获取指定打印机的状态? 2. 使用go-ole如何暂停和恢复打印任务? 3. 使用WMI管理打印机时,如何提高查询效率?</think>### 使用 go-ole 实现打印管理功能 在 Windows 平台下,使用 go-ole 库可以通过 COM 接口实现打印管理功能。以下是实现步骤和关键代码示例: #### 1. **初始化 COM 库** ```go package main import ( "fmt" "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" ) func main() { // 初始化 COM 库 ole.CoInitialize(0) defer ole.CoUninitialize() // 后续代码... } ``` #### 2. **获取打印队列对象** 通过 WMI 获取打印管理对象: ```go // 创建 WMI 服务对象 wmi, err := oleutil.CreateObject("WbemScripting.SWbemLocator") if err != nil { panic(err) } defer wmi.Release() wmiObj := wmi.MustQueryInterface(ole.IID_IDispatch) defer wmiObj.Release() // 连接本地 WMI 服务 service := oleutil.MustCallMethod(wmiObj, "ConnectServer").ToIDispatch() defer service.Release() // 获取打印队列对象 printers := oleutil.MustCallMethod(service, "ExecQuery", "SELECT * FROM Win32_Printer").ToIDispatch() defer printers.Release() ``` #### 3. **打印控制功能实现** **a. 暂停/恢复打印机** ```go // 获取指定打印机对象 printer := oleutil.MustCallMethod(printers, "ItemIndex", 0).ToIDispatch() defer printer.Release() // 暂停打印机 oleutil.MustPutProperty(printer, "Paused", true) fmt.Println("打印机已暂停") // 恢复打印机 oleutil.MustPutProperty(printer, "Paused", false) fmt.Println("打印机已恢复") ``` **b. 取消所有打印任务** ```go // 获取打印任务队列 jobs := oleutil.MustCallMethod(service, "ExecQuery", "SELECT * FROM Win32_PrintJob").ToIDispatch() defer jobs.Release() count := int(oleutil.MustGetProperty(jobs, "Count").Val) for i := 0; i < count; i++ { job := oleutil.MustCallMethod(jobs, "ItemIndex", i).ToIDispatch() oleutil.MustCallMethod(job, "Delete") // 删除打印任务 job.Release() } fmt.Println("所有打印任务已取消") ``` **c. 设置打印权限** ```go // 获取打印机安全描述符 sd := oleutil.MustGetProperty(printer, "GetSecurityDescriptor").ToIDispatch() defer sd.Release() // 修改权限 (示例:禁用所有用户打印) oleutil.MustPutProperty(sd, "Permissions", 0) // 0 = 无权限 oleutil.MustCallMethod(printer, "SetSecurityDescriptor", sd) fmt.Println("打印权限已更新") ``` #### 4. **打印监控实现** ```go // 创建 WMI 事件监视器 query := "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PrintJob'" sink := oleutil.MustCallMethod(service, "ExecNotificationQuery", query).ToIDispatch() // 实时监听打印事件 for { event := oleutil.MustCallMethod(sink, "NextEvent").ToIDispatch() job := oleutil.MustGetProperty(event, "TargetInstance").ToIDispatch() jobID := oleutil.MustGetProperty(job, "JobId").ToString() user := oleutil.MustGetProperty(job, "Owner").ToString() fmt.Printf("检测到新打印任务: ID=%s, 用户=%s\n", jobID, user) job.Release() event.Release() } ``` ### 注意事项 1. **权限要求**: - 需要以管理员权限运行程序 - 操作打印服务需要 `SePrintOperatorPrivilege` 权限 2. **错误处理**: ```go if result, err := oleutil.CallMethod(printer, "Pause"); err != nil { fmt.Printf("操作失败: %v (HRESULT: 0x%x)\n", err, result.Val) } ``` 3. **COM 对象释放**: - 所有 `ToIDispatch()` 返回的对象必须调用 `Release()` - 使用 `defer` 确保资源释放 ### 实现原理 通过 Windows 的 COM 接口: 1. 使用 `Win32_Printer` WMI 类管理打印机状态 2. 通过 `Win32_PrintJob` 类控制打印任务 3. 利用 WMI 事件订阅实现实时监控 4. 使用安全描述符接口设置打印权限[^1] > **提示**:完整实现需处理打印机枚举、用户权限验证等扩展功能,可结合 Windows API 增强控制能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值