2019-03-11更新:原来NSIS脚本也可以禁用64位文件操作重定向的!

1、在安装脚本的开始处定义 LIBRARY_X64。

!include "MUI.nsh"
!include "Library.nsh"

;如果做32位安装包就把下句注释。
!define LIBRARY_X64

2、在调用涉及目标机器上系统目录(即$SYSDIR)的函数前用 ${DisableX64FSRedirection}。

在安装包的第一个Section中调用一次即可。
!ifdef  LIBRARY_X64
 ${DisableX64FSRedirection}
!endif

之前问题主要在于64位重定向问题,所以自己用python写了个脚本。找到了NSIS禁用重定向方法就可以无论32位还是64位都可以使用NSIS来写脚本了。

原文:

前些天自己做了一年多的软件成功交付客户,客户提出些完善意见,其中一条就是要一个软件安装脚本。

这个之前也尝试python做过,只不过当时有更紧急的任务,最后就没深入尝试。

这次我就捡起了之前的python工程,继续做做。

整个过程很简单:

1,把软件解压到客户选择的目录

2,把一个dll程序复制到windows\system32目录

3,创建一个桌面快捷方式

因为就这么几步,所以我以为很容易搞,就选择了久违的python自己写,而没有选择一些成熟的自动生成脚本工具。

首先肯定要有个界面吧,主要是要用户选择安装目录。我用Tkinter写了个简陋的界面,这个不多说。

解压压缩包的话,python有很好的库zipfile:

def unzip(zipFilePath, destDir):
zfile = zipfile.ZipFile(zipFilePath)
for name in zfile.namelist():
(dirName, fileName) = os.path.split(name)
if fileName == '':
# directory
newDir = destDir + '/' + dirName
if not os.path.exists(newDir):
os.mkdir(newDir)
else:
# file
fd = open(destDir + '/' + name, 'wb')
fd.write(zfile.read(name))
fd.close()
zfile.close()

创建桌面快捷方式python肯定也有库,但我最后选择了使用bat脚本。

set Program=这里要写快捷方式对应的程序目录,且必须是绝对路径。

在python里将这个路径填写上,然后程序里运行bat脚本即可。

@ echo off

set Program=

set LnkName=manager software

set WorkDir=

set Desc=soft

if not defined WorkDir call:GetWorkDir "%Program%"
(echo Set WshShell=CreateObject("WScript.Shell"^)
echo strDesKtop=WshShell.SpecialFolders("DesKtop"^)
echo Set oShellLink=WshShell.CreateShortcut(strDesKtop^&"\%LnkName%.lnk"^)
echo oShellLink.TargetPath="%Program%"
echo oShellLink.WorkingDirectory="%WorkDir%"
echo oShellLink.WindowStyle=
echo oShellLink.Description="%Desc%"
echo oShellLink.Save)>makelnk.vbs
echo SUCCESS
makelnk.vbs
del /f /q makelnk.vbs
exit
goto :eof
:GetWorkDir
set WorkDir=%~dp1
set WorkDir=%WorkDir:~,-%
goto :eof

上面都算顺利,最后竟然在本以为很简单的复制文件到系统目录上出了问题。

不管怎样努力,都没法将文件复制到windows\system32目录下。

一开始本以为是权限问题。

在程序开始前加入这样的代码:

def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False if is_admin():
#主程序代码
else:
# Re-run the program with admin rights
ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)

这样在运行前就会弹窗要求获取管理员权限。

按道理这样程序就已经有了管理员权限了,可还是没有复制到system32目录下。

后来在同事帮我看这个问题,他弄了一会,发现其实是64位系统下,系统自动重定向到C:\Windows\SysWOW64目录下了!

所以一定要在复制操作前,禁止重定向。

    with disable_file_system_redirection():
shutil.copy2('sdfp_lib.dll',os.getenv("SystemDrive")+'\\windows\\system32')

上述,便是用python写我的软件自动安装脚本的全过程,后面会附上我的全部代码。

我先再讲下要实现这种软件自动安装脚本需求 最常用最合适的实现方法。

其实用工具自动生成就好了!

这个HM NIS Edit工具。

点击文件,选择新建脚本向导。

然后按照向导一般的安装,基本的安装需求都可以简单实现。

重点是这一步:

左边可以添加分组,右边可以给每个分组添加安装指令,可以给组添加单独的文件,也可以给组添加主程序目录。每个组再配置安装目标目录。这个目标目录有很多选择,包括系统目录、用户选择目录…………不赘述。

这个工具编译好脚本,就生成了一个Setup.exe文件。这就是安装程序。要安装的软件文件都包含在这个exe里了,很厉害。

按道理,只要用这个工具就可以完成我的需求了,但在64位系统还有些问题,那就是依然会有系统重定向现象。本来要复制到system32目录下的dll还是会被复制到C:\Windows\SysWOW64下。

最后我就决定,做两个版本。

32位的安装程序用HM NIS Edit工具自动生成。

64位我自己用python写。

另外,python转化成exe文件的写法,之前文章介绍过:

https://www.cnblogs.com/rixiang/p/7274026.html

附上py完整代码:

# -*- coding: utf-8 -*-
from __future__ import print_function
from Tkinter import *
import os
import sys
import subprocess
import shutil reload(sys)
defaultencoding = 'utf-8'
import ctypes import tkFileDialog as filedialog
import zipfile
from shutil import copyfile class disable_file_system_redirection:
_disable = ctypes.windll.kernel32.Wow64DisableWow64FsRedirection
_revert = ctypes.windll.kernel32.Wow64RevertWow64FsRedirection
def __enter__(self):
self.old_value = ctypes.c_long()
self.success = self._disable(ctypes.byref(self.old_value))
def __exit__(self, type, value, traceback):
if self.success:
self._revert(self.old_value) def unzip(zipFilePath, destDir):
zfile = zipfile.ZipFile(zipFilePath)
for name in zfile.namelist():
(dirName, fileName) = os.path.split(name)
if fileName == '':
# directory
newDir = destDir + '/' + dirName
if not os.path.exists(newDir):
os.mkdir(newDir)
else:
# file
fd = open(destDir + '/' + name, 'wb')
fd.write(zfile.read(name))
fd.close()
zfile.close() def choose_directory():
global dir_choosen
global dir_choosen2
dir_choosen = filedialog.askdirectory(initialdir='C:')
# unzip my program to directory choosen
dir_choosen2 = dir_choosen
dir_choosen = dir_choosen + '/tgsoft'
if not os.path.exists(dir_choosen):
os.makedirs(dir_choosen)
entryText.set(dir_choosen) def install():
if dir_choosen2.strip()=='' or dir_choosen.strip()=='':
return -1
unzip('tgsoft.zip',dir_choosen)
with disable_file_system_redirection():
shutil.copy2('sdfp_lib.dll',os.getenv("SystemDrive")+'\\windows\\system32')
str_bat = ''
f = open('CREATE_SHORTCUT.bat', 'r')
line = f.readline()
while line:
str_bat+=line
line = f.readline()
f.close()
nPos=str_bat.index('=')+1
str_bat = str_bat[:nPos]+dir_choosen2+"\\tgsoft\\ManagerSoftware.exe"+str_bat[nPos:]
f = open('CREATE_SHORTCUT2.bat', 'w') # 若是'wb'就表示写二进制文件
f.write(str_bat)
f.close()
child = subprocess.Popen('CREATE_SHORTCUT2.bat',shell=False)
# reset the window
file_label.destroy()
file_entry.destroy()
file_btn.destroy()
b2.destroy()
w = Label(master, text="安装成功\n感谢使用")
w.grid(row=0) def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False if is_admin():
global master
master = Tk()
master.title('指静脉注册软件安装程序')
master.geometry('400x100')
global file_label
file_label = Label(master, text="选择软件安装路径")
file_label.grid(row=0)
global entryText
entryText = StringVar()
global file_entry
file_entry = Entry(master,textvariable=entryText)
file_entry.grid(row=0, column=1)
global file_btn
file_btn = Button(master, text='点击选择路径', command=choose_directory)
file_btn.grid(row=0,column=2)
global b1
b1 = Button(master, text=' 退 出 ', command=master.quit)
b1.grid(row=1,column=0)
global b2
b2 = Button(master, text=' 确 定 ', command=install)
b2.grid(row=1,column=1)
mainloop()
else:
# Re-run the program with admin rights
ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1)

用python & bat写软件安装脚本 + HM NIS Edit自动生成软件安装脚本的更多相关文章

  1. [python] [转]如何自动生成和安装requirements.txt依赖

    [转]如何自动生成和安装requirements.txt依赖 在查看别人的Python项目时,经常会看到一个requirements.txt文件,里面记录了当前程序的所有依赖包及其精确版本号.这个文件 ...

  2. HM NIS Edit 2.0.3 Win32 Error. Code:740.请求的操作需要提升

    使用NSIS安装向导,生成脚本后,按F9后,居然提示:HM NIS Edit 2.0.3 Win32 Error. Code:740.请求的操作需要提升 一开始就出错了,还真不顺. 在网上搜索了一下, ...

  3. 如何利用pip自动生成和安装requirements.txt依赖

    在查看别人的Python项目时,经常会看到一个requirements.txt文件,里面记录了当前程序的所有依赖包及其精确版本号.这个文件有点类似与Rails的Gemfile.其作用是用来在另一台PC ...

  4. 如何自动生成和安装requirements.txt依赖

    在查看别人的Python项目时,经常会看到一个requirements.txt文件,里面记录了当前程序的所有依赖包及其精确版本号.这个文件有点类似与Rails的Gemfile.其作用是用来在另一台PC ...

  5. 自动生成和安装requirements.txt依赖

    在查看别人的Python项目时,经常会看到一个requirements.txt文件,里面记录了当前程序的所有依赖包及其精确版本号.这个文件有点类似与Rails的Gemfile.其作用是用来在另一台PC ...

  6. atitit.自动生成数据库结构脚本,或者更换数据库,基于hibernate4

    atitit.自动生成数据库结构脚本,或者更换数据库,基于hibernate4 目前近况:: 更换数据库,但是是使用spring集成的. <!-- hibernate配置文件路径 --> ...

  7. 使用pip命令自动生成项目安装依赖清单

    Python项目中经常会带requirements.txt文件,里面是项目所依赖的包的列表,也就是依赖关系清单,这个清单也可以使用pip命令自动生成. pip命令: 1 pip freeze > ...

  8. Matlab中使用脚本和xml文件自动生成bus模块

    帮一个老师写的小工具 在一个大工程中需要很多bus来组织信号,而为了规范接口,需要定义很多BusObject,用Matlab语言手写这些BusObject比较费工夫 所以用xml配置文件来写,也便于更 ...

  9. CSS雪碧图自动生成软件

    下载地址 http://www.99css.com/1524/ 包含详细的下载地址.下载步骤以及使用教程 亮点:自动合成雪碧图+自动生成雪碧图background-position代码 简单过程 下载 ...

随机推荐

  1. java 替换json字符串中间的引号保留两边的引号,避免json校验失败

    一.json概要 JSON(JavaScript Object Notation, JS 对象标记)-一种轻量级的数据交换标准(相对xml),独立于编程语言.具体以逗号分隔的key:value键值对的 ...

  2. 第二十一篇:基​于​W​D​M​模​型​的​A​V​S​t​r​e​a​m​驱​动​架​构​研​究

    基​于​W​D​M​模​型​的​A​V​S​t​r​e​a​m​驱​动​架​构​研​ 这篇论文2006年早就发表, 与当时开发这个驱动正好几乎相同的时间. 近期实际项目须要, 又回过头来将AVStre ...

  3. Linux 增值服务中删除,自己主动和国家执行

    CAMS 在自己主动参加相关的服务安装过程.在最后的安装过程中会提示用户是否启动该服务,这样的服务才能生效,需要注意的是一个服务并不意味着系统启动过程中被添加到该服务后,会自己主动执行,只可用于ser ...

  4. 关于Vuex可直接修改state问题

    下面的代码证明不通过mutation,而直接修改state修改确实生效了.这样子多人协作岂不是很容易出问题.对于这个问题,在创建 store 的时候传入 strict: true, 开启严格模式,那么 ...

  5. 世界卫生组织(WHO)发出最新警告:埃博拉疫情应急响应

    10月14r日.世界卫生组织(WHO)发出警告:在未来两个月内,西非国家将面对"could face up to 10 thousand new Ebola cases a week wit ...

  6. mongose TypeError: Cannot read property 'findOne' of undefined

    最近在node的一个项目中,需要在model的一个数据表中写一个钩子函数去调用另外一个文件中的方法,一开始我采用了将此方法放入到global中,直接从global.meteod这样去获取.后来我又尝试 ...

  7. 推荐一些C#相关的网站和书籍

    1.http://msdn.microsoft.com/zh-CN/ 微软的官方网站,C#程序员必去的地方.那里有API开发文档,还有各种代码.资源下载. 2.http://social.msdn.m ...

  8. java 多线程以及线程池

    1.多线程可以使程序反应更快,交互性更强,执行效率最高. 2.创建一个线程:  要实现Runnable 接口,创建Thread类的对象,用start开始执行线程. 3.使用Thread中的yield( ...

  9. Android中WebView的相关使用

    近期做的项目中,遇到个非常棘手的问题: 客户给我的数据是有限制的,因此,在返回某条详细页面内容的时候,他仅仅能给我一个html片段,里面包括 文字,图片以及附件的下载地址.假设网页模版规范的爱比較好说 ...

  10. 简明Python3教程 5.第一步

    介绍 我们现在来看看如何在Python中运行传统的”Hello world”程序.这会教你如何写.保存以及运行Python程序. 有两种办法来运行您的Python程序——使用交互式的解释器提示符或者源 ...