如果需要登录到多个SAP系统,不同系统的账号和密码成为了很大负担。那么怎样合理记录账号密码,甚至实现免密自动登录呢?本篇就一次性把这个说清楚。
快捷方式自动登录
我的 SAP GUI 版本为 770,据说 740 以上的版本 SAP 取消了允许记录密码。所以想要实现自动登录,需要修改注册表。按下 WIN + R (运行),输入 regedit :
找到注册表的节点 HKEY_CURRENT_USER\Software\SAP\SAPShortcut\Security,将 EnablePassword 的值改为 1。
然后在桌面上创建一个快捷方式。SAP 支持在 GUI 中或者电脑某个位置创建快捷方式,但为了方便修改增加密码的值,需要放电脑某个位置。创建快捷方式大家应该都会。创建快捷方式之后,用文本编辑器工具打开快捷方式,内容如下:
增加一行 password:
这样双击快捷方式就可以进入 SAP 系统了。
sapshcut.exe 程序
在 SAP GUI 安装目录同一个文件夹下面,有一个 sapshcut.exe 应用程序,用于启动 SAP。输入 WIN + R 打开运行,输入 sapshcut.exe /?,可以查看应用程序的参数:
通过这个应用程序,我们可以按自己喜欢的方式进行配置,实现自动登录。比如放在批处理文件里面,通过编程语言调用这个应用程序,放到密码管理工具里面,放到 Microsoft Power App Desktop 里面。Power App Desktop 也提供了实现 SAP 操作自动化的方式,以后我会通过专门的博文进行讲解,不仅仅是实现自动登录。在本文中,我介绍一下批处理、编程和放到密码管理工具里面三种方法。
批处理文件
新建一个批处理文件(扩展名为 bat),命名为 vm-ecc.bat。文件的内容如下:
start sapshcut.exe -user=stone -pw=w123456 -language=ZH -SYSTEM=D01 -CLIENT=001 -sysname=VMWare-ECC -maxgui
双击就可以实现自动登录。
脚本代码
以自己想要的语言,调用 sapshcut.exe ,使用规定的command line 参数。比如,如果我想要把不同 SAP 的账号和密码放到 Excel 里,那就可以使用 VBA 来做脚本。
Function RunSAP(system As String, client As String, user As String, pw As String)
Dim command As String
command = "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\sapshcut.exe -system=" & system & " -client=" & client & " -user=" & user & " -pw=" & pw & " -language=en"
Shell command, vbNormalFocus
End Function
如果喜欢 Python,可以用下面的代码:
import subprocess
def start_sap():
command = [
"C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\sapshcut.exe",
"-system=S4H",
"-client=400",
"-user=<your_username>",
"-pw=<your_password>",
"-language=en"
]
subprocess.run(command, shell=True)
登录参数放在密码管理工具中
以个人常用的密码管理工具 KeePass 为例,在这里输入登录的 SAP 系统和账号密码:
然后在下面的 URL 中,将 url 的类型设为 cmd,输入下面的参数值:
cmd://sapshcut.exe -user={USERNAME} -pw={PASSWORD} -language=ZH -SYSTEM=D01 -CLIENT=001 -sysname=VMWare-ECC -maxgui
这样就可以自动登录 SAP 了。
Scripting 脚本实现自动登录
网上很多方法,都是在讲这种方法,但这种方法其实有一个前提,就是 SAP 应用程序需要允许用户脚本(RZ11 -> sapgui/user_scripting),如果不允许是不可能的。
如果系统允许用户脚本,可以使用如下的代码 (哪种语言都是可以的,这里以 python 为例)
import subprocess
import win32com.client
import win32com
import time
import sys
from tkinter import *
class SapGui:
def __init__(self):
self.path = r"C:\Program Files (x86)\SAP\FrontEnd\SapGui\saplogon.exe"
subprocess.Popen(self.path)
time.sleep(3)
self.SapGuiAuto = win32com.client.GetObject("SAPGUI")
application = self.SapGuiAuto.GetScriptingEngine
self.connection = application.OpenConnection("VMWare-ECC", True)
# time.sleep(3)
self.session = self.connection.Children(0)
self.session.findById("wnd[0]").maximize
def login(self):
try:
self.session.findById("wnd[0]/usr/txtRSYST-MANDT").text = "001"
self.session.findById("wnd[0]/usr/txtRSYST-BNAME").text = "STONE"
self.session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "w123456"
self.session.findById("wnd[0]/usr/pwdRSYST-BCODE").setFocus()
self.session.findById("wnd[0]/usr/pwdRSYST-BCODE").caretPosition = 7
self.session.findById("wnd[0]").sendVKey(0)
except:
print(sys.exc_info()[0])
if __name__ == '__main__':
window = Tk()
window.geometry('200x60')
btn = Button(window, text="logon to SAP (VMWare ECC)", command=lambda: SapGui().login())
btn.pack()
mainloop()
通过 saplogon.exe 登录
saplogon.exe 也就是我们常用的 SAP GUI 登录界面,如果想用编程的方式调用 saplogon.exe 实现登录,个人觉得门槛是比较高的。首先,我们需要对 Windows API 有一定的了解,会使用窗口检测工具,比如 spy++, inspect.exe 等。第二个方面,SAP 对登录界面进行了保护,通过这些检测工具看不到用户、密码这些编辑控件的 classname 。我在尝试用 pywinauto, uiautomation 等工具观察登录界面的子窗口,都是看不到的。所以最后勉强用几个 第三方python 包,实现了自动登录功能。个人觉得这个方法在效率、稳定性方面都不够,目前只是实验性的,所以对代码的实现就不展开讲解了。
代码使用了 pywin32, uiautomation 和 pyautogui 等第三方模块。
import subprocess as sp
import win32gui, win32con, win32api
import time
import uiautomation as ua
import pyautogui
# 使用 subprocess 模块打开 saplogon.exe
sp.Popen(r'C:\Program Files (x86)\SAP\FrontEnd\SapGui\saplogon.exe')
sapLogonHwnd = 0
while sapLogonHwnd== 0:
sapLogonHwnd = win32gui.FindWindow('#32770', 'SAP Logon 770')
time.sleep(0.1)
# 使用IsWindowVisible进一步确认, 直至窗口可见
isVisible = False
while isVisible == False:
time.sleep(0.1)
isVisible = win32gui.IsWindowVisible(sapLogonHwnd)
# 从多个SAP连接中选择需要登录的SAP系统,双击打开登录界面
sapLogonDialog=ua.WindowControl(searchDepth=2, Name='SAP Logon 770')
testControl=sapLogonDialog.Control(searchDepth=12, Name='VMWare-ECC')
testControl.DoubleClick()
time.sleep(1)
fw = pyautogui.getActiveWindow()
fw.maximize()
caplock = win32api.GetKeyState(win32con.VK_CAPITAL) # 获取Caps Lock键状态
with pyautogui.hold('shift'):
pyautogui.press('tab') #按下tab键
# 通过 pyautogui 输入client, user, password
pyautogui.typewrite(message='001') #键盘输入
pyautogui.press('tab') #按下tab键
pyautogui.typewrite(message='STONE') #键盘输入
pyautogui.press('tab') #按下tab键
# capslock 需要关闭
if caplock == 1:
pyautogui.press('capslock')
pyautogui.typewrite(message='w123456') #键盘输入
time.sleep(1)
pyautogui.press('enter') # press the Enter key