場景
在 Windows 上執行需要訪問網路或者提供網路服務的程式,需要防火牆放行。預設情況下,在首次執行程式時,可能會有如下彈窗,只有使用者點選執行才能繼續使用網路。部分情況,可能是直接被攔截,都沒有這個提示。
Windows 防火牆規則 | Microsoft Learn
如果出現問題,手動處理的話,可以在 Windows 防火牆的高階設定中,新增入站或出站規則,或者配置 “允許應用或功能透過 Windows Defender 防火牆”。
這裡介紹的是,如果在應用安裝時(使用 NSIS 打包),自動新增防火牆規則,避免上述問題。
netsh advfirewall
基本思路是使用 netsh advfirewall
命令來進行防火牆規則的新增,
新增規則命令參考:
netsh advfirewall firewall add rule name="ruleName" program="C:\Program Files\7-Zip\7z.exe" action=allow dir=in enable=yes
移除規則命令參考(解除安裝時呼叫):
netsh advfirewall firewall delete rule name="ruleName"
關於 netsh advfirewall 的更多資料
Use netsh advfirewall firewall context - Windows Server | Microsoft Learn
在 NSIS 中整合上述 netsh 命令
在 NSIS 指令碼中,可以透過 ExecWait 直接執行命令,參考如下
#define FIREWALL_NAME "my dicom viewer"
Function .onInstSuccess
ExecWait 'netsh advfirewall firewall add rule name="${FIREWALL_NAME}" program="$INSTDIR\DicomViewer.exe" dir=in action=allow'
ExecWait 'netsh advfirewall firewall add rule name="${FIREWALL_NAME}" program="$INSTDIR\DicomViewer.exe" dir=out action=allow'
FunctionEnd
Function un.onUninstSuccess
ExecWait 'netsh advfirewall firewall delete rule name="${FIREWALL_NAME}"'
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地從您的計算機移除"
FunctionEnd
上述寫法能成功執行,但是有個問題,在執行時,會開啟 CMD 命令列視窗。看起來的效果就是會有黑框框一閃而過,如果是內部使用的工程板軟體,勉強可以接受,如果是面向使用者的軟體,這個問題還需要進一步處理。
改進 CMD 命令列視窗的閃爍
這裡使用的方式是,在 NSIS 中,呼叫 vbs 指令碼,可以做到沒有命令列視窗。
新增規則的指令碼如下
Dim arg1
arg1 = WScript.Arguments(0)
Dim shell
Set shell = CreateObject("WScript.Shell")
Dim ruleName
ruleName = "my dicom viewer"
Dim command1
command1 = "netsh advfirewall firewall add rule name=""" & ruleName & """ program=""" & arg1 & """ action=allow dir=in enable=yes"
Dim command2
command2 = "netsh advfirewall firewall add rule name=""" & ruleName & """ program=""" & arg1 & """ action=allow dir=out enable=yes"
shell.Run command1, 0, True ' 0 表示靜默,True 表示等待命令執行完成
shell.Run command2, 0, True
刪除規則的指令碼如下
Dim shell
Set shell = CreateObject("WScript.Shell")
Dim ruleName
ruleName = "my dicom viewer"
Dim command1
command1 = "netsh advfirewall firewall delete rule name=""" & ruleName & """ "
shell.Run command1, 0, True ' 0 表示靜默,True 表示等待命令執行完成
因為要在安裝或者解除安裝時呼叫,所以這個檔案要被放到安裝包中。
Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File "Script\after-install.vbs"
File "Script\after-uninstall.vbs"
SectionEnd
在安裝成功之後呼叫
; 安裝成功之後呼叫
Function .onInstSuccess
ExecWait '"wscript.exe" "$INSTDIR\after-install.vbs" "$INSTDIR\DicomViewer.exe"'
FunctionEnd
在解除安裝刪除全部檔案之前呼叫。因為這裡是呼叫安裝目錄下的檔案,所以不能放在 Function un.onUninstSuccess 中處理,因為那時候,檔案都已經被刪除了,無法被呼叫。
Section Uninstall
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\DicomViewer.exe"
ExecWait '"wscript.exe" "$INSTDIR\after-uninstall.vbs" '
Delete "$INSTDIR\*.*"
RMDir /r "$INSTDIR"
SectionEnd
注意事項
netsh advfirewall 命令操作,需要管理員許可權。通常安裝程式會以管理員身份執行,如果不是,則需要注意這個問題。
原文連結:https://www.cnblogs.com/jasongrass/p/18389183