# NSIS 制作32+64安装包

单位有个企业网上申报客户端软件,是有两个dll文件是有32和64区分的,想利用NSIS脚本自动判断系统的位数,然后自动去选择不同的dll文件安装。先是让开发商解决,过了好久得不到解决,现在自己把这个问题解决了,下面是我查阅参考的内容:


# NSIS判断系统32位&64位

使用NSIS做安装包有时需要判断系统是32位还是64位进行不同的操作,比如安装某个驱动要分不同位数进行安装。 首先需要包含这个

!include "x64.nsh"  ;---64位文件头
1

必须要有这个,不然各种报错,之前网上查到用法,有些人没说明这个,用起来各种报错,一脸懵逼下面是用法

Section
;64位系统
  ${If} ${RunningX64}
;这里进行相应的操作
  ${Else}
;这里进行相应的操作
  ${EndIf}
SectionEnd
1
2
3
4
5
6
7
8

原文: (opens new window)


参考:

# nsis判断32或64位怎么写

因为有两个dll文件是有32和64区分的,用nsis脚本自动判断是多少位的系统,然后自动去选择不同的dll文件安装。
现在在NSIS的教程里找到下面代码:

!include x64.nsh ;---64位文件头
Function .onInit
       ;64位系统。
        ${If} ${RunningX64} 
        ${EnableX64FSRedirection} 
        
        ${else}
        MessageBox MB_OK "Sorry this application runs only on x64 machines"
        Abort
        ${EndIf}
FunctionEnd

Section -un
       Detailprint '$SYSDIR'
       DetailPrint '$WINDIR'
       DetailPrint '$PROGRAMFILES'
SectionEnd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# NSIS检测x64 or x86问题

想共同维护一个NSIS脚本文件的,不想搞两个版本的脚本文件了。开始想到了!if语句,没试过,不知道行不行得通。
后来google了一下。可以用两个头文件搞定。参照下面链接。

Reference 参考1: http://stackoverflow.com/questions/11126629/use-one-nsis-installer-to-install-32-bit-binaries-on-32-bit-os-and-64-bit-binari (opens new window)
使用一个NSIS安装程序可以在32位操作系统上安装32位二进制文​​件,在64位操作系统上安装64位二进制文​​件吗?
我目前有两个WIX安装程序用于我维护的产品。一个用于32位操作系统,一个用于64位操作系统。我想将它们组合成一个NSIS安装程序,而不是维护两个单独的安装程序,它可以“确定”操作系统的“位数”,然后将相应的二进制文件复制到程序目录中。有没有人有这方面的经验,并可以提供NSIS可用于制作安装程序的工作示例脚本?
我确实看了这个,它将允许我确定操作系统的位数,但我仍然遇到问题,我需要告诉安装程序要安装哪些文件。我目前有一个“部分”包含这个:SetOutPath ${PROGRAMINSTALL} File /r build\\*所以我不确定x64模块会在这种情况下有所帮助.
另外,我不是在64位系统上安装32位二进制文​​件......我在64位操作系统上安装64位文件,在32位操作系统上安装32位文件.
这确实告诉系统要安装哪些文件。如果您放入64位文件build\64和32位文件build\32。如果您还需要根据体系结构更改安装目录,那么您可以放入SetOutPathIf / Else -

Function .onInit
StrCpy $instdir $programfiles32\MyApp
${If} ${RunningX64}
  StrCpy $instdir $programfiles64\MyApp
${EndIf}
FunctionEnd
...
Section
Setoutpath $instdir
${If} ${RunningX64}
  File /r build\64\*
${Else}
  File /r build\32\*
${EndIf}
SectionEnd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

我相信我弄清楚了......我还没有测试过这个,但它应该有效......
答案是为每组文件创建两个“部分”。SEC0000适用于32位和SEC0001适用于 64位文件。然后,

!include x64.nsh
Function .onInit
  #Determine the bitness of the OS and enable the correct section
  ${if} ${RunningX64}
    SectionSetFlags ${SEC0001} 17
    SectionSetFlags ${SEC0000} 16
  ${else}
    SectionSetFlags ${SEC0001} 16
    SectionSetFlags ${SEC0000} 17
  ${endif}
FunctionEnd
1
2
3
4
5
6
7
8
9
10
11

我相信un.onInit函数中也需要相同的逻辑,因此卸载程序知道要删除哪些文件...
使用sections.nsh中的帮助宏来选择/取消选择部分
对于使用3.0a0的简单通用安装程序,我通过一些实验发现以下内容对我有用:

!include x64.nsh
Function .onInit
  #Determine the bitness of the OS and enable the correct section
  ${If} ${RunningX64}
    SectionSetFlags ${SEC0000}  ${SECTION_OFF}
    SectionSetFlags ${SEC0001}  ${SF_SELECTED}
  ${Else}
    SectionSetFlags ${SEC0001}  ${SECTION_OFF}
    SectionSetFlags ${SEC0000}  ${SF_SELECTED}
  ${EndIf}
FunctionEnd
1
2
3
4
5
6
7
8
9
10
11

我只需要记住在引用的部分之后放置函数。我的每个部分都简单地在它们各自的32位/ 64位/目录中引用了同名的.exe,因此我的卸载程序不需要任何特殊处理。我没有在32位系统上测试它,但它确实适用于64位系统。
例:

section "64-bit" SEC0001
  messageBox MB_OK "64-BIT!"
  File "C:\foo\64-bit\some-utility.exe"
sectionEND
1
2
3
4

为此你需要!include "Sections.nsh"在你的脚本中SF_SELECTED选择的是Sections.nsh


Reference 参考2:
http://stackoverflow.com/questions/21822044/merge-32bit-and-64bit-installer-into-one-installer-using-nsis (opens new window)

使用NSIS将32位和64位安装程序合并到一个安装程序中
我使用NSIS创建了一个简单的安装程序。我希望安装程序应该检测客户端正在使用的操作系统。如果客户端使用的是32位操作系统,则应将所有文件复制到Program Files(32位)文件夹,否则如果他/她使用64 -bit操作系统,所有文件都应该复制到64位。任何人都可以帮我解决这个问题。
以下代码将完成任务。

!include "x64.nsh"
...
var copyDir
section ""

${If} ${RunningX64}
strcpy $copyDir "C:\\Program Files(x64)\\Foo"
${else}
strcpy $copyDir "C:\\Program Files\\Foo"
sectionend
1
2
3
4
5
6
7
8
9
10

虽然它只是检测Program Files目录,但我认为$ProgramFiles会根据OS位自动检测默认的Program Files目录。
与上面相同(不要忘记包含LogicLib.nsh 和 x64.nsh)

Function .onInit
    ${If} ${RunningX64}
        StrCpy $INSTDIR "$PROGRAMFILES64\myProduct"
    ${Else}
        StrCpy $INSTDIR "$PROGRAMFILES\myProduct" ; $PROGRAMFILES32 also works
    ${EndIf}
FunctionEnd
1
2
3
4
5
6
7

(可选)您还可以设置注册表视图(请参阅SetRegView (opens new window)


Reference 参考3: http://stackoverflow.com/questions/7152689/problem-using-runningx64-in-nsis (opens new window)
在NSIS中使用$ {RunningX64}的问题 ?
我在我的脚本的几个部分使用下面的代码。

${If} ${RunningX64}
; 64bit bits go here
${Else}
; 32bit bits go here
${EndIf}
1
2
3
4
5

在一个函数中它运行得很好,但是除非在正确执行的初始调用之后使用它们,否则其他调用将不起作用。
我无法找到这种行为的任何合理原因。我已经包含了LogicLib.nshx64.nsh 文件,但是它通过了64位部分。
我这样使用GetVersion插件:

Var WINDOWS_ARCHITECTURE

GetVersion::WindowsPlatformArchitecture
Pop $WINDOWS_ARCHITECTURE ; 32 or 64
1
2
3
4

Reference 参考4: http://www.cppblog.com/Mumoo/archive/2012/05/11/174542.aspx (opens new window)
NSIS IF与WHILE的使用

逻辑语句的宏文件: !include logiclib.nsh
IF语句:
   ${If} $0 == 'some value'
      MessageBox MB_OK '$$0 is some value'
   ${ElseIf} $0 == 'some other value'
      MessageBox MB_OK '$$0 is some other value'
   ${Else}
      MessageBox MB_OK '$$0 is "$0"'
     ${EndIf}

while循环:
   StrCpy $R1 0   ;----字符串赋值为整型
   ${While} $R1 < 5
   IntOp $R1 $R1 + 1
   DetailPrint $R1  ;----打印字符串
${EndWhile}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

此文章只是简单的将32和64的安装脚本组合在一起制作的安装包,会根据系统选择性地安装对应的东西到对应路径下。

; 该脚本使用 HM VNISEdit 脚本编辑器向导产生
; 安装程序初始定义常量
RequestExecutionLevel admin  ;------针对UAC进行权限请求
!define PRODUCT_NAME "xxx"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\xxx.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"

SetCompressor /SOLID lzma
SetCompressorDictSize 32

; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------


;--------------x64安装定义----------------------------
!include "MUI.nsh"
!include "x64.nsh" #---------加入64位头文件----------
!include "Library.nsh"
!define LIBRARY_X64
;-----------------------------------------------------

; MUI 预定义常量
!define MUI_ABORTWARNING
!define MUI_ICON "E:\xxx\logo.ico"
!define MUI_UNICON "E:\xxx\modern-uninstall.ico"

; 语言选择窗口常量设置
!define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language"

; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 安装目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 开始菜单设置页面
; -------------------定义语言字符串变量-----------------------------
LangString LANG_PRODUCT_FLODER 1033 "xxx English"
LangString LANG_PRODUCT_FLODER 2052 "xxx 简中"
LangString LANG_PRODUCT_FLODER 1028 "xxx 繁中"
LangString LANG_PRODUCT_NAME 1033 "xxx English"
LangString LANG_PRODUCT_NAME 2052 "xxx 简中"
LangString LANG_PRODUCT_NAME 1028 "xxx 繁中"
; ------------------------------------------------------------------
var ICONS_GROUP
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "$(LANG_PRODUCT_FLODER)\$(LANG_PRODUCT_NAME)\xxx"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面
!define MUI_FINISHPAGE_RUN "$INSTDIR\xxx.exe"
!insertmacro MUI_PAGE_FINISH

; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES

; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "TradChinese"

; 安装预释放文件
!insertmacro MUI_RESERVEFILE_LANGDLL
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Setup.exe"

InstallDir "$PROGRAMFILES64\xxx\xxx"
InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
ShowInstDetails show
ShowUnInstDetails show

Section "MainSection" SEC01
${IF} ${RunningX64}
;-----------------------------------
!ifdef LIBRARY_X64
${DisableX64FSRedirection}
!endif
;--------------------------------------
  SetOutPath "$SYSDIR"
  SetOverwrite ifnewer
  File "E:\xxx\xxx"
  File "E:\xxx\xxx"
  ExecWait "$SYSDIR\xxx"
  SetOutPath "$INSTDIR"
  File "E:\xxx\xxx.exe"
  
  SetOutPath "C:\Windows\SysWOW64"
  SetOverwrite ifnewer
  File "E:\xxx\xxx"
  File "E:\xxx\xxx"
  File "E:\xxx\xxx"
; --------------------------------------------------------

;----------与后面指令对应--------------
  SetShellVarContext all
;--------------------------------------

${Else}
Call .inFirefox
  SetOutPath "$SYSDIR"
  SetOverwrite ifnewer
  File "E:\xxx\xxx"
  File "E:\xxx\xxx"
  File "E:\xxxx\xxx"
  ExecWait "$SYSDIR\xxx"
SetOutPath "$INSTDIR"
  File "E:\xxx\xxx.exe"
; --------------------------------------------------------
${EndIf}

; 创建开始菜单快捷方式
  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application

  CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\xxx.lnk" "$INSTDIR\xxx.exe"
  CreateShortCut "$DESKTOP\Techshino.lnk" "$INSTDIR\xxx.exe"
  !insertmacro MUI_STARTMENU_WRITE_END
SectionEnd

Section -AdditionalIcons
  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe"
  !insertmacro MUI_STARTMENU_WRITE_END
SectionEnd

Section -Post
${IF} ${RunningX64}
;----------给x64注册表访问权限-----------
  !ifdef LIBRARY_X64
  SetRegView 64
  !endif
;----------------------------------------
  WriteUninstaller "$INSTDIR\uninst.exe"
  ;创建自启动
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "xxx" "$INSTDIR\xxx.exe"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\xxx.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\xxx.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
;----------结束x64注册表访问权限-----------
  !ifdef LIBRARY_X64
  SetRegView Lastused
  !endif
;----------------------------------------
${Else}
WriteUninstaller "$INSTDIR\uninst.exe"
  ;创建自启动
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "CNCBUK2TESOMon" "$INSTDIR\xxx.exe"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\xxx.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\xxx.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
${EndIf}
SectionEnd

#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#  
; ------判断是否安装Firefox代码如下:-------------------  
Var Firefox
Function .inFirefox
ClearErrors
 ReadRegStr $Firefox HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe" "Path"

IfErrors 0 ExitCheckFirefox
Goto NoFirefox
ExitCheckFirefox:
  SetOutPath "$Firefox\plugins"
  SetOverwrite ifnewer
  File "E:\xxx\xxx"
NoFirefox:
FunctionEnd

/******************************
 *  以下是安装程序的卸载部分  *
 ******************************/
#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#

;卸载菜单语言设置
; -------------------设置多语言字符串显示-----------------------------
LangString UNINSTALL_MESSAGE 1033 "Are you sure you want to completely remove [Techshino] and all of its components?"
LangString UNINSTALL_MESSAGE 2052 "你确实要完全移除 [xxx] ,及其所有的组件?"
LangString UNINSTALL_MESSAGE 1028 "妳確實要完全移除 [xxx] ,及其所有的組件?"
LangString UNINSTALL_MESSAGE_OK 1033 "[xxx] was successfully removed from your computer."
LangString UNINSTALL_MESSAGE_OK 2052 "[xxx] 已成功地从你的计算机移除。"
LangString UNINSTALL_MESSAGE_OK 1028 "[xxx] 已成功地從妳的計算機移除。"
; --------------------------------------------------------------------

Section Uninstall
${IF} ${RunningX64}
;-------消除安装路径转向---------------
!ifdef LIBRARY_X64
${DisableX64FSRedirection}
!endif
;-------删除64系统system 32下文件----------------------
  !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
  nsProcess::_KillProcess "xxx.exe"
  Delete "$INSTDIR\uninst.exe"
  Delete /rebootok "$INSTDIR\xxx.exe"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
 ;----------删除64系统SysWOW64下文件-----------------------
  Delete "C:\Windows\SysWOW64\xxx"
  Delete "C:\Windows\SysWOW64\xxx"
  Delete "C:\Windows\SysWOW64\xxx"
  Delete "C:\Windows\SysWOW64\xxx"
  Delete "C:\Windows\SysWOW64\xxx"
    
;-------------用于删除开始菜单快捷图标-----------
  SetShellVarContext all
;------------------------------------------------
  Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk"
  Delete "$DESKTOP\xxx.lnk"
  Delete "$SMPROGRAMS\$ICONS_GROUP\xxx.lnk"
  RMDir "$SMPROGRAMS\$ICONS_GROUP"
  RMDir "$SMPROGRAMS\$(LANG_PRODUCT_FLODER)\$(LANG_PRODUCT_NAME)"
  RMDir "$SMPROGRAMS\$(LANG_PRODUCT_FLODER)"
  RMDir /rebootok "$INSTDIR"
  RMDir /rebootok "$PROGRAMFILES64\xxx\xxx"
  RMDir /rebootok "$PROGRAMFILES64\xxx"
;----------给x64注册表访问权限-----------
  !ifdef LIBRARY_X64
  SetRegView 64
  !endif
;----------------------------------------
  DeleteRegKey HKCU "Software\Microsoft\SystemCertificates\My\PhysicalStores"
  DeleteRegKey HKLM "Software\Microsoft\Cryptography\Defaults\Provider\xxx"
  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "xxx"
  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
  DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
;----------结束x64注册表访问权限-----------
  !ifdef LIBRARY_X64
  SetRegView Lastused
  !endif
;----------------------------------------
  SetAutoClose true
${Else}
Call un.Firefox
  !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
  KillProcDLL::KillProc "xxx.exe"
  Delete "$INSTDIR\uninst.exe"
  Delete /rebootok "$INSTDIR\xxx.exe"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
  Delete "$SYSDIR\xxx"
  Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk"
  Delete "$DESKTOP\xxx.lnk"
  Delete "$SMPROGRAMS\$ICONS_GROUP\xxx.lnk"
  RMDir "$SMPROGRAMS\$ICONS_GROUP"
  RMDir "$SMPROGRAMS\$(LANG_PRODUCT_FLODER)\$(LANG_PRODUCT_NAME)"
  RMDir "$SMPROGRAMS\$(LANG_PRODUCT_FLODER)"
  RMDir /rebootok "$INSTDIR"
  RMDir /rebootok "$PROGRAMFILES\xxx\xxx"
  RMDir /rebootok "$PROGRAMFILES\xxx"
  DeleteRegKey HKCU "Software\Microsoft\SystemCertificates\My\PhysicalStores"
  DeleteRegKey HKLM "SOFTWARE\Microsoft\Cryptography\Defaults\Provider\xxx"
  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "xxx"
  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
  DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
  SetAutoClose true
${EndIf}
SectionEnd
Function un.Firefox
; ------判断是否安装Firefox并删除DLL文件-------------------
ClearErrors
 ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe" "Path"
IfErrors 0 unExitCheckFirefox
Goto unNoFirefox
  unExitCheckFirefox:
  Delete "$0\plugins\xxx"
RMDIR "$0\plugins"
unNoFirefox:
FunctionEnd
; ----------------------------------------------------------

Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "$(UNINSTALL_MESSAGE)" IDYES +2
  Abort
FunctionEnd

Function un.onUninstSuccess
  HideWindow
  MessageBox MB_ICONINFORMATION|MB_OK "$(UNINSTALL_MESSAGE_OK)"
FunctionEnd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

原文: (opens new window)

更新时间: 2023-1-29 18:57:07