首页
> 计算机技术
> 后端开发
> Nim
POS-ERP零售系统集成安装程序的完整实现代码
原创 lihf8515于2025年02月16日 12:54发表
来源:本站 阅读:177
一、缘起
由于笔者所在公司的POS-ERP零售系统是第三方软件公司开发,后来由于市场环境和信息技术的更新,后期添加了很多的补丁。这种情况下,若是业务电脑系统损坏,重新安装系统,那么这个POS-ERP零售系统安装起来就非常麻烦,没有一定的计算机技术知识,还真没办法完成。
为此,笔者开发了《POS-ERP零售系统集成安装程序》和《POS-ERP零售系统配置管理器》。
二、项目简介
1、目标:开发《POS-ERP零售系统配置管理器》和《POS-ERP零售系统集成安装程序》打包集成相关补丁,方便安装维护,节省大量人力。
2、主要集成完整程序和相关补丁(POS-ERP零售系统配置管理器、.NET1.1框架、读写卡器的链接库、机构树补丁、无法创建挂勾补丁、设计器登录报system.net.dns错误补丁)。
3、《POS-ERP零售系统配置管理器》可根据需要重新配置所需要公司配置信息,方便了维护。
其中,《POS-ERP零售系统配置管理器》使用Nim语言开发实现,由此可见Nim语言的强大和快捷。《POS-ERP零售系统集成安装程序》使用Inno Setup打包实现。
三、完整实现代码
1、POS-ERP零售系统配置管理器
import wNim/[wApp, wFrame, wPanel, wImage, wStaticText, wCombobox, wButton, wPaintDc, wIcon] | |
import wNim/private/winimx | |
import std/[strutils, os] | |
import parseini | |
const style = wAlignCentre or wAlignMiddle | |
let app = App(wSystemDpiAware) | |
const logo = staticRead(r"res/hlogo.bmp") | |
let image = Image(logo) | |
let wndSize = (image.width, 260) | |
let mainFrame* = Frame(title="集团POS-ERP零售系统配置管理器", size=wndSize, style=wDefaultDialogStyle or wStayOnTop) | |
mainFrame.icon = Icon("", 0) | |
let panel = Panel(mainFrame) | |
let textCompany = StaticText(panel, label="要登录的公司", style=style) | |
let textCopyright = StaticText(panel, label="宿州公司信息技术部 李海峰 2017-2024", style=style) | |
let buttonOk = Button(panel, label="确定") | |
let comboboxCompany = Combobox(panel, value="", choices=[], style=wCbDropDown or wCbReadOnly) | |
proc layout() = | |
panel.layout: | |
comboboxCompany: | |
centerX == panel.centerX | |
centerY == panel.centerY | |
WEAK: | |
width == panel.width / 3 | |
height == textCompany.height | |
STRONG: | |
width <= 200 | |
height <= 100 | |
textCompany: | |
height == comboboxCompany.height | |
top == comboboxCompany.top | |
right + 8 == comboboxCompany.left | |
buttonOk: | |
width == 80 | |
height == comboboxCompany.height | |
top == comboboxCompany.top | |
left == comboboxCompany.right + 8 | |
textCopyright: | |
left == textCompany.left | |
right == buttonOk.right | |
top == panel.bottom - textCompany.height - 10 | |
proc initData() = | |
let cfg = loadConfig(getAppDir() / "config.ini") | |
let names: seq[string] = split(cfg.get("company","name"), ",") | |
for index,item in names: | |
comboboxCompany.append(item) | |
panel.wEvent_Paint do (event: wEvent): | |
var dc = PaintDC(panel) | |
dc.drawImage(image) | |
buttonOk.wEvent_Button do (): | |
let selectedText = comboboxCompany.getValue() | |
if selectedText=="": | |
MessageBox(mainFrame.getHandle(), "请选择您所属的公司", "系统提示", MB_OK or MB_ICONWARNING) | |
else: | |
try: | |
copyFile(getAppDir() / "connect" / $selectedText & ".xml", "C:\\Congou\\myshop\\bin\\connect.xml") | |
copyFile(getAppDir() / "tnsnames" / $selectedText & ".ora", "C:\\Congou\\OracleClient\\NETWORK\\ADMIN\\tnsnames.ora") | |
MessageBox(mainFrame.getHandle(), "配置成功!\n你现在可以登录" & $selectedText & "的POS-ERP零售系统了!", "系统提示", MB_OK or MB_ICONINFORMATION) | |
except OSError: | |
MessageBox(mainFrame.getHandle(), getCurrentExceptionMsg(), "系统提示", MB_OK or MB_ICONSTOP) | |
layout() | |
initData() | |
mainFrame.center() | |
mainFrame.show() | |
app.mainLoop() |
2、POS-ERP零售系统集成安装程序
; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档! | |
[ | ]|
AppName=集团POS-ERP零售系统集成安装包7.0 | |
AppVerName=集团POS-ERP零售系统集成安装包7.0 | |
VersionInfoVersion=7.0 | |
AppCopyright=Copyright (C) 2017-2024 | |
AppPublisher=宿州公司信息技术部 李海峰 | |
AppPublisherURL=http://www.hfsoft.top/ | |
AppSupportURL=http://www.hfsoft.top/ | |
AppUpdatesURL=http://www.hfsoft.top/ | |
DisableDirPage=yes | |
DefaultDirName=C:\Congou | |
DefaultGroupName=集团POS-ERP零售系统 | |
DisableProgramGroupPage=yes | |
LicenseFile=D:\集团POS-ERP零售系统集成安装包源文件\Congou\lhf\readme.txt | |
OutputDir=D:\ | |
OutputBaseFilename=集团POS-ERP零售系统集成安装包7.0 | |
Compression=lzma | |
SolidCompression=yes | |
WizardImageFile=D:\集团POS-ERP零售系统集成安装包源文件\WizModernImage-IS.bmp | |
WizardSmallImageFile=D:\集团POS-ERP零售系统集成安装包源文件\wxm.bmp | |
;no为不重启Yes为重启 | |
AlwaysRestart=no | |
ChangesEnvironment=true | |
[ | ]|
Name: "chinese"; MessagesFile: "compiler:Default.isl" | |
[ | ]|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone | |
Name: modifypath; Description: &添加正常运行必须的环境变量; Flags: checkablealone | |
[ | ]|
Source: "D:\集团POS-ERP零售系统集成安装包源文件\Congou\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs | |
Source: "D:\集团POS-ERP零售系统集成安装包源文件\Congou\OracleClient\bin\OraOLEDB11.dll"; DestDir: "{app}\OracleClient\bin"; Flags:ignoreversion regserver | |
Source: "D:\集团POS-ERP零售系统集成安装包源文件\sp\*"; DestDir: "{tmp}"; Flags: ignoreversion recursesubdirs createallsubdirs | |
Source: "D:\集团POS-ERP零售系统集成安装包源文件\mywinsock_dns.reg"; DestDir: "{tmp}"; Flags: ignoreversion recursesubdirs createallsubdirs | |
Source: "D:\集团POS-ERP零售系统集成安装包源文件\mywinsock2_dns.reg"; DestDir: "{tmp}"; Flags: ignoreversion recursesubdirs createallsubdirs | |
; 注意: 不要在任何共享系统文件上使用“Flags: ignoreversion” | |
[ | ]|
Name: "{userdesktop}\集团POS-ERP零售系统"; Filename: "{app}\myshop\bin\mySHOP.exe"; Tasks: desktopicon ;WorkingDir: "{app}" | |
Name: "{group}\集团POS-ERP零售系统"; Filename: "{app}\myshop\bin\mySHOP.exe" ;WorkingDir: "{app}" | |
Name: "{group}\集团POS-ERP零售系统配置管理器"; Filename: "{app}\lhf\congouconfig.exe" ;WorkingDir: "{app}" | |
Name: "{group}\{cm:UninstallProgram, 集团POS-ERP零售系统}"; Filename: "{uninstallexe}"; | |
[ | ]|
BeveledLabel=宿州公司信息技术部 李海峰 | |
[ | ]|
;用来指定程序完成安装后、在安装程序显示最终对话框之前要执行的程序。 | |
Filename: {tmp}\dotnetfx1.1.exe; Parameters: "/Q:U /C:""install /L /QB"""; Check:IsNeedInstall; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在安装 Microsoft.NET1.1运行环境 请稍候... | |
Filename: {tmp}\langpack.exe; Parameters: "/Q:U /C:""inst /L /QB"""; Check:IsNeedInstall; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在安装 Microsoft.NET1.1运行环境中文语言包 请稍候... | |
Filename: {tmp}\NDP1.1sp1-KB867460-X86.exe; Parameters: "/I /Q"; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在安装 NDP1.1sp1-KB867460-X86 请稍候... | |
Filename: {tmp}\ndp1.1sp1-kb925168-x86.exe; Parameters: "/I /Q"; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在安装 ndp1.1sp1-kb925168-x86 请稍候... | |
Filename: "regedit.exe"; Parameters: "/s {tmp}\mywinsock_dns.reg"; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在写入 winsock注册表 请稍候... | |
Filename: "regedit.exe"; Parameters: "/s {tmp}\mywinsock2_dns.reg"; Flags:runhidden; WorkingDir: {tmp}; StatusMsg: 正在写入 winsock2注册表 请稍候... | |
Filename: {app}\lhf\congouconfig.exe; Description: &运行集团POS-ERP零售系统配置管理器; Flags: postinstall; | |
[ | ]|
Root: HKLM; SubKey: SOFTWARE\ORACLE; ValueType: string; ValueName: ORACLE_HOME; ValueData: c:\congou\oracleclient | |
Root: HKLM; SubKey: SOFTWARE\ORACLE\KEY_OraDb11g_home1; ValueType: string; ValueName: ORACLE_HOME; ValueData: c:\congou\oracleclient | |
Root: HKLM; SubKey: SOFTWARE\ORACLE\KEY_OraDb11g_home1; ValueType: string; ValueName: ORACLE_HOME_NAME; ValueData: OraDb11g_home1 | |
Root: HKLM; SubKey: SOFTWARE\ORACLE\KEY_OraDb11g_home1; ValueType: string; ValueName: ORACLE_HOME_KEY; ValueData: SOFTWARE\ORACLE\KEY_OraDb11g_home1 | |
Root: HKLM; SubKey: SOFTWARE\ORACLE\KEY_OraDb11g_home1; ValueType: string; ValueName: NLS_LANG; ValueData: SIMPLIFIED CHINESE_CHINA.ZHS16GBK | |
[ | ]|
//***************************************************************************************************** | |
//检测并安装.Net 1.1 | |
function IsNeedInstall():Boolean; | |
begin | |
if RegKeyExists(HKLM, 'Software\Microsoft\.NETFramework\policy\v1.1') then | |
begin | |
Result := false; | |
end | |
else | |
Result := true; | |
end; | |
//***************************************************************************************************** | |
//修改环境变量 | |
const | |
ModPathName = 'modifypath'; | |
ModPathType = 'system'; | |
function ModPathDir(): TArrayOfString; | |
begin | |
setArrayLength(Result, 1); | |
Result[0] := ExpandConstant('{app}\OracleClient\bin'); | |
end; | |
//****** | |
procedure ModPath(); | |
var | |
oldpath: String; | |
newpath: String; | |
updatepath: Boolean; | |
pathArr: TArrayOfString; | |
aExecFile: String; | |
aExecArr: TArrayOfString; | |
i, d: Integer; | |
pathdir: TArrayOfString; | |
regroot: Integer; | |
regpath: String; | |
begin | |
// Get constants from main script and adjust behavior accordingly | |
// ModPathType MUST be 'system' or 'user'; force 'user' if invalid | |
if ModPathType = 'system' then | |
begin | |
regroot := HKEY_LOCAL_MACHINE; | |
regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; | |
end | |
else | |
begin | |
regroot := HKEY_CURRENT_USER; | |
regpath := 'Environment'; | |
end; | |
// Get array of new directories and act on each individually | |
pathdir := ModPathDir(); | |
for d := 0 to GetArrayLength(pathdir)-1 do | |
begin | |
updatepath := true; | |
// Modify WinNT path | |
if UsingWinNT() = true then | |
begin | |
// Get current path, split into an array | |
RegQueryStringValue(regroot, regpath, 'Path', oldpath); | |
oldpath := oldpath + ';'; | |
i := 0; | |
while (Pos(';', oldpath) > 0) do | |
begin | |
SetArrayLength(pathArr, i+1); | |
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); | |
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); | |
i := i + 1; | |
// Check if current directory matches app dir | |
if pathdir[d] = pathArr[i-1] then | |
begin | |
// if uninstalling, remove dir from path | |
if IsUninstaller() = true then | |
begin | |
continue; | |
end | |
// if installing, flag that dir already exists in path | |
else | |
begin | |
updatepath := false; | |
end; | |
end; | |
// Add current directory to new path | |
if i = 1 then | |
begin | |
newpath := pathArr[i-1]; | |
end | |
else | |
begin | |
newpath := newpath + ';' + pathArr[i-1]; | |
end; | |
end; | |
// Append app dir to path if not already included | |
if (IsUninstaller() = false) AND (updatepath = true) then | |
newpath := newpath + ';' + pathdir[d]; | |
// Write new path | |
RegWriteStringValue(regroot, regpath, 'Path', newpath); | |
end | |
else | |
// Modify Win9x path | |
begin | |
// Convert to shortened dirname | |
pathdir[d] := GetShortName(pathdir[d]); | |
// If autoexec.bat exists, check if app dir already exists in path | |
aExecFile := 'C:\AUTOEXEC.BAT'; | |
if FileExists(aExecFile) then | |
begin | |
LoadStringsFromFile(aExecFile, aExecArr); | |
for i := 0 to GetArrayLength(aExecArr)-1 do | |
begin | |
if IsUninstaller() = false then | |
begin | |
// If app dir already exists while installing, skip add | |
if (Pos(pathdir[d], aExecArr[i]) > 0) then | |
updatepath := false; | |
break; | |
end | |
else | |
begin | |
// If app dir exists and = what we originally set, then delete at uninstall | |
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then | |
aExecArr[i] := ''; | |
end; | |
end; | |
end; | |
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path | |
if (IsUninstaller() = false) AND (updatepath = true) then | |
begin | |
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); | |
// If uninstalling, write the full autoexec out | |
end | |
else | |
begin | |
SaveStringsToFile(aExecFile, aExecArr, False); | |
end; | |
end; | |
end; | |
// Write file to flag modifypath was selected | |
// Workaround since IsTaskSelected() cannot be called at uninstall and AppName and AppId cannot be "read" in Code section | |
if IsUninstaller() = false then | |
SaveStringToFile(ExpandConstant('{app}') + '\uninsTasks.txt', WizardSelectedTasks(False), False); | |
end; | |
procedure CurStepChanged(CurStep: TSetupStep); | |
var | |
taskname: String; | |
begin | |
taskname := ModPathName; | |
if CurStep = ssPostInstall then | |
if IsTaskSelected(taskname) then | |
ModPath(); | |
end; | |
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); | |
var | |
appdir: String; | |
//aSelectedTasks: TArrayOfString; | |
aSelectedTasks:String; | |
//i: Integer; | |
taskname: String; | |
begin | |
taskname := ModPathName; | |
appdir := ExpandConstant('{app}') | |
if CurUninstallStep = usUninstall then | |
begin | |
if LoadStringFromFile(appdir + '\uninsTasks.txt', aSelectedTasks) then | |
begin | |
if ( pos(taskname,aSelectedTasks) > 0 ) then ModPath(); | |
end; | |
DeleteFile(appdir + '\uninsTasks.txt'); | |
//删除 {app} 文件夹及其中所有文件 | |
DelTree(appdir, True, True, True); | |
end; | |
end; | |
//***************************************************************************************************** | |
//初始化向导 | |
procedure InitializeWizard(); | |
begin | |
WizardForm.LICENSEACCEPTEDRADIO.Checked := true; | |
end; |
阅读排行榜