Fix Windows auto-update to replace Navis.exe in place (1.8.1).
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -61,6 +61,7 @@ func main() {
|
|||||||
if update.MaybeFinishUpdate(os.Args[1:]) {
|
if update.MaybeFinishUpdate(os.Args[1:]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
update.CleanupStaleDownloads()
|
||||||
|
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
|
||||||
@@ -342,11 +343,9 @@ func (a *app) applyUpdate() (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_ = a.mgr.Disconnect()
|
_ = a.mgr.Disconnect()
|
||||||
|
// Hard-exit so Windows unlocks Navis.exe; do not wait on webview.Terminate (can hang).
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(400 * time.Millisecond)
|
time.Sleep(300 * time.Millisecond)
|
||||||
if a.webview != nil {
|
|
||||||
a.webview.Terminate()
|
|
||||||
}
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
return "Устанавливается v" + latest + "… Navis перезапустится.", nil
|
return "Устанавливается v" + latest + "… Navis перезапустится.", nil
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+6
-6
@@ -1,28 +1,28 @@
|
|||||||
{
|
{
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"notes": "Автообновление с перезапуском + AmneziaWG 2.0 (вставка .conf / awg://)",
|
"notes": "Исправлено автообновление: замена текущего Navis.exe на месте без .new",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"mandatory": false,
|
"mandatory": false,
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"windows-amd64": {
|
"windows-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "e7df0d9d7dd6d9ad53768ffb250bedd8c1dcca7ba085847737dd378bf2aadbd6",
|
"sha256": "9a1f9d99b930cde479f9d28ef37b0f1472ab033f6e9f28da5781617639c17d54",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64"
|
"arch": "arm64"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
"sha256": "21583e6085e7d4d1b5800c21f5de356dc0f1c68c9658e58c0bd6557a390325cf",
|
"sha256": "9c036f9022761a117021af37778ecd293a3fc2b7438eaf26f804bb01ef4943f1",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+6
-6
@@ -1,28 +1,28 @@
|
|||||||
{
|
{
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"notes": "Автообновление с перезапуском + AmneziaWG 2.0 (вставка .conf / awg://)",
|
"notes": "Исправлено автообновление: замена текущего Navis.exe на месте без .new",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"mandatory": false,
|
"mandatory": false,
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"windows-amd64": {
|
"windows-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "e7df0d9d7dd6d9ad53768ffb250bedd8c1dcca7ba085847737dd378bf2aadbd6",
|
"sha256": "9a1f9d99b930cde479f9d28ef37b0f1472ab033f6e9f28da5781617639c17d54",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64"
|
"arch": "arm64"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
"sha256": "21583e6085e7d4d1b5800c21f5de356dc0f1c68c9658e58c0bd6557a390325cf",
|
"sha256": "9c036f9022761a117021af37778ecd293a3fc2b7438eaf26f804bb01ef4943f1",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CurrentVersion is the shipped client version.
|
// CurrentVersion is the shipped client version.
|
||||||
const CurrentVersion = "1.8.0"
|
const CurrentVersion = "1.8.1"
|
||||||
|
|
||||||
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
||||||
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
||||||
@@ -250,7 +250,10 @@ func prepareDownload(ctx context.Context, manifestURL string) (latest, url, sha,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", "", "", err
|
return "", "", "", "", "", err
|
||||||
}
|
}
|
||||||
tmp := exe + ".new"
|
tmp := filepath.Join(filepath.Dir(exe), ".navis-update-download")
|
||||||
|
_ = os.Remove(tmp)
|
||||||
|
// Also clear legacy leftover from older updaters.
|
||||||
|
_ = os.Remove(exe + ".new")
|
||||||
if err := downloadFile(ctx, st.URL, tmp); err != nil {
|
if err := downloadFile(ctx, st.URL, tmp); err != nil {
|
||||||
return "", "", "", "", "", err
|
return "", "", "", "", "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,3 +49,14 @@ func Apply(ctx context.Context, manifestURL string) (string, error) {
|
|||||||
func shellQuote(s string) string {
|
func shellQuote(s string) string {
|
||||||
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
|
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CleanupStaleDownloads removes leftover update temps from failed/old runs.
|
||||||
|
func CleanupStaleDownloads() {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exe, _ = filepath.Abs(exe)
|
||||||
|
_ = os.Remove(exe + ".new")
|
||||||
|
_ = os.Remove(filepath.Join(filepath.Dir(exe), ".navis-update-download"))
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ func Apply(ctx context.Context, manifestURL string) (string, error) {
|
|||||||
_ = manifestURL
|
_ = manifestURL
|
||||||
return "", fmt.Errorf("автообновление пока только для Windows и macOS")
|
return "", fmt.Errorf("автообновление пока только для Windows и macOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CleanupStaleDownloads is a no-op on unsupported platforms.
|
||||||
|
func CleanupStaleDownloads() {}
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ import (
|
|||||||
|
|
||||||
const finishUpdateFlag = "--navis-finish-update"
|
const finishUpdateFlag = "--navis-finish-update"
|
||||||
|
|
||||||
// Apply downloads the new exe and starts it to replace the running binary after exit.
|
// Apply downloads the new build and replaces the running Navis.exe after this process exits.
|
||||||
// Avoids writing .bat self-replacer scripts (common AV false-positive pattern).
|
|
||||||
func Apply(ctx context.Context, manifestURL string) (string, error) {
|
func Apply(ctx context.Context, manifestURL string) (string, error) {
|
||||||
latest, _, _, exe, tmp, err := prepareDownload(ctx, manifestURL)
|
latest, _, _, exe, tmp, err := prepareDownload(ctx, manifestURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -30,24 +29,34 @@ func Apply(ctx context.Context, manifestURL string) (string, error) {
|
|||||||
if err := os.Rename(tmp, pending); err != nil {
|
if err := os.Rename(tmp, pending); err != nil {
|
||||||
if err2 := copyFile(tmp, pending); err2 != nil {
|
if err2 := copyFile(tmp, pending); err2 != nil {
|
||||||
_ = os.Remove(tmp)
|
_ = os.Remove(tmp)
|
||||||
return "", err2
|
return "", fmt.Errorf("prepare updater: %w", err2)
|
||||||
}
|
}
|
||||||
_ = os.Remove(tmp)
|
_ = os.Remove(tmp)
|
||||||
}
|
}
|
||||||
_ = os.Chmod(pending, 0o755)
|
_ = os.Chmod(pending, 0o755)
|
||||||
|
_ = os.Remove(exe + ".new")
|
||||||
|
|
||||||
cmd := exec.Command(pending, finishUpdateFlag, strconv.Itoa(os.Getpid()), exe)
|
cmd := exec.Command(pending, finishUpdateFlag, strconv.Itoa(os.Getpid()), exe)
|
||||||
cmd.Dir = filepath.Dir(exe)
|
cmd.Dir = filepath.Dir(exe)
|
||||||
const createNoWindow = 0x08000000
|
const (
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: createNoWindow}
|
createNewProcessGroup = 0x00000200
|
||||||
|
detachedProcess = 0x00000008
|
||||||
|
createNoWindow = 0x08000000
|
||||||
|
)
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
CreationFlags: createNewProcessGroup | detachedProcess | createNoWindow,
|
||||||
|
HideWindow: true,
|
||||||
|
}
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
|
_ = os.Remove(pending)
|
||||||
return "", fmt.Errorf("start updater: %w", err)
|
return "", fmt.Errorf("start updater: %w", err)
|
||||||
}
|
}
|
||||||
|
_ = cmd.Process.Release()
|
||||||
return latest, nil
|
return latest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaybeFinishUpdate handles: Navis-pending.exe --navis-finish-update <pid> <targetExe>
|
// MaybeFinishUpdate handles: Navis-pending.exe --navis-finish-update <pid> <targetExe>
|
||||||
// Returns true if this process was the updater and should exit.
|
// Replaces targetExe in-place with this binary, then relaunches it.
|
||||||
func MaybeFinishUpdate(args []string) bool {
|
func MaybeFinishUpdate(args []string) bool {
|
||||||
if len(args) < 3 || args[0] != finishUpdateFlag {
|
if len(args) < 3 || args[0] != finishUpdateFlag {
|
||||||
return false
|
return false
|
||||||
@@ -64,21 +73,18 @@ func MaybeFinishUpdate(args []string) bool {
|
|||||||
self, _ = filepath.Abs(self)
|
self, _ = filepath.Abs(self)
|
||||||
target, _ = filepath.Abs(target)
|
target, _ = filepath.Abs(target)
|
||||||
|
|
||||||
waitPIDExit(uint32(pid), 90*time.Second)
|
waitPIDExit(uint32(pid), 120*time.Second)
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(400 * time.Millisecond)
|
||||||
|
|
||||||
backup := target + ".bak"
|
if err := replaceExecutable(self, target); err != nil {
|
||||||
_ = os.Remove(backup)
|
|
||||||
if err := os.Rename(target, backup); err != nil {
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
_ = os.Rename(target, backup)
|
if err2 := replaceExecutable(self, target); err2 != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := copyFile(self, target); err != nil {
|
|
||||||
_ = os.Rename(backup, target)
|
_ = os.Remove(target + ".bak")
|
||||||
return true
|
_ = os.Remove(target + ".new")
|
||||||
}
|
|
||||||
_ = os.Chmod(target, 0o755)
|
|
||||||
_ = os.Remove(backup)
|
|
||||||
_ = os.Remove(self)
|
_ = os.Remove(self)
|
||||||
|
|
||||||
cmd := exec.Command(target)
|
cmd := exec.Command(target)
|
||||||
@@ -87,6 +93,73 @@ func MaybeFinishUpdate(args []string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CleanupStaleDownloads removes leftover update temps from failed/old runs.
|
||||||
|
func CleanupStaleDownloads() {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exe, _ = filepath.Abs(exe)
|
||||||
|
dir := filepath.Dir(exe)
|
||||||
|
base := filepath.Base(exe)
|
||||||
|
_ = os.Remove(exe + ".new")
|
||||||
|
_ = os.Remove(filepath.Join(dir, base+".new"))
|
||||||
|
_ = os.Remove(filepath.Join(dir, "Navis-update.part"))
|
||||||
|
_ = os.Remove(filepath.Join(dir, ".navis-update-download"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceExecutable(src, dst string) error {
|
||||||
|
backup := dst + ".bak"
|
||||||
|
_ = os.Remove(backup)
|
||||||
|
|
||||||
|
var last error
|
||||||
|
for i := 0; i < 40; i++ {
|
||||||
|
if err := os.Rename(dst, backup); err == nil {
|
||||||
|
last = nil
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
last = err
|
||||||
|
time.Sleep(250 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if last != nil {
|
||||||
|
staged := dst + ".stage"
|
||||||
|
_ = os.Remove(staged)
|
||||||
|
if err := copyFile(src, staged); err != nil {
|
||||||
|
return fmt.Errorf("stage new exe: %w", err)
|
||||||
|
}
|
||||||
|
if err := moveFileReplace(staged, dst); err != nil {
|
||||||
|
_ = os.Remove(staged)
|
||||||
|
return fmt.Errorf("replace locked exe: %w (also: %v)", err, last)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := copyFile(src, dst); err != nil {
|
||||||
|
_ = os.Rename(backup, dst)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_ = os.Chmod(dst, 0o755)
|
||||||
|
_ = os.Remove(backup)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveFileReplace(src, dst string) error {
|
||||||
|
from, err := windows.UTF16PtrFromString(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
to, err := windows.UTF16PtrFromString(dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
const (
|
||||||
|
moveFileReplaceExisting = 0x1
|
||||||
|
moveFileWriteThrough = 0x8
|
||||||
|
)
|
||||||
|
return windows.MoveFileEx(from, to, moveFileReplaceExisting|moveFileWriteThrough)
|
||||||
|
}
|
||||||
|
|
||||||
func waitPIDExit(pid uint32, timeout time.Duration) {
|
func waitPIDExit(pid uint32, timeout time.Duration) {
|
||||||
const synchronize = 0x00100000
|
const synchronize = 0x00100000
|
||||||
h, err := windows.OpenProcess(synchronize, false, pid)
|
h, err := windows.OpenProcess(synchronize, false, pid)
|
||||||
|
|||||||
+6
-6
@@ -1,28 +1,28 @@
|
|||||||
{
|
{
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"notes": "Автообновление с перезапуском + AmneziaWG 2.0 (вставка .conf / awg://)",
|
"notes": "Исправлено автообновление: замена текущего Navis.exe на месте без .new",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"mandatory": false,
|
"mandatory": false,
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"windows-amd64": {
|
"windows-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||||
"sha256": "cc656a2c9c026c1c0f068eb7b05785965d7b7bc9fc42b5b13f0e6e7ada3dde97",
|
"sha256": "7265ace71fdd58b86c0c9acf8ee05d3f0182623201987c9d119d9d1ab328f500",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "e7df0d9d7dd6d9ad53768ffb250bedd8c1dcca7ba085847737dd378bf2aadbd6",
|
"sha256": "9a1f9d99b930cde479f9d28ef37b0f1472ab033f6e9f28da5781617639c17d54",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64"
|
"arch": "arm64"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
"sha256": "21583e6085e7d4d1b5800c21f5de356dc0f1c68c9658e58c0bd6557a390325cf",
|
"sha256": "9c036f9022761a117021af37778ecd293a3fc2b7438eaf26f804bb01ef4943f1",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "amd64"
|
"arch": "amd64"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"FixedFileInfo": {
|
"FixedFileInfo": {
|
||||||
"FileVersion": { "Major": 1, "Minor": 8, "Patch": 0, "Build": 0 },
|
"FileVersion": { "Major": 1, "Minor": 8, "Patch": 1, "Build": 0 },
|
||||||
"ProductVersion": { "Major": 1, "Minor": 8, "Patch": 0, "Build": 0 },
|
"ProductVersion": { "Major": 1, "Minor": 8, "Patch": 1, "Build": 0 },
|
||||||
"FileFlagsMask": "3f",
|
"FileFlagsMask": "3f",
|
||||||
"FileFlags": "00",
|
"FileFlags": "00",
|
||||||
"FileOS": "40004",
|
"FileOS": "40004",
|
||||||
@@ -11,12 +11,12 @@
|
|||||||
"StringFileInfo": {
|
"StringFileInfo": {
|
||||||
"CompanyName": "EvilFox",
|
"CompanyName": "EvilFox",
|
||||||
"FileDescription": "Navis VPN client (NaiveProxy / Hysteria 2 / AmneziaWG 2.0)",
|
"FileDescription": "Navis VPN client (NaiveProxy / Hysteria 2 / AmneziaWG 2.0)",
|
||||||
"FileVersion": "1.8.0.0",
|
"FileVersion": "1.8.1.0",
|
||||||
"InternalName": "Navis",
|
"InternalName": "Navis",
|
||||||
"LegalCopyright": "Copyright (c) EvilFox",
|
"LegalCopyright": "Copyright (c) EvilFox",
|
||||||
"OriginalFilename": "Navis.exe",
|
"OriginalFilename": "Navis.exe",
|
||||||
"ProductName": "Navis",
|
"ProductName": "Navis",
|
||||||
"ProductVersion": "1.8.0.0",
|
"ProductVersion": "1.8.1.0",
|
||||||
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
||||||
},
|
},
|
||||||
"VarFileInfo": {
|
"VarFileInfo": {
|
||||||
|
|||||||
Reference in New Issue
Block a user