首页
> 计算机技术
> 后端开发
> Nim
POS-ERP零售系统集成安装程序的完整实现代码
原创 lihf8515于2025年02月16日 12:54发表
来源:本站 阅读:175
一、缘起
由于笔者所在公司的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
{.link:"res/app.res".}
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 脚本文件的详细资料请查阅帮助文档!
[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
[Languages]
Name: "chinese"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone
Name: modifypath; Description: &添加正常运行必须的环境变量; Flags: checkablealone
[Files]
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”
[Icons]
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}";
[Messages]
BeveledLabel=宿州公司信息技术部 李海峰
[Run]
;用来指定程序完成安装后、在安装程序显示最终对话框之前要执行的程序。
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;
[Registry]
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
[Code]
//*****************************************************************************************************
//检测并安装.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;
阅读排行榜