fix: windows识别邀请码

This commit is contained in:
speakeloudest 2026-01-19 09:04:19 -08:00
parent d60f1d3c5d
commit 6da7649720
3 changed files with 81 additions and 16 deletions

View File

@ -91,6 +91,15 @@ class KRDeviceUtil {
String? code = _kr_extractCode(executablePath);
if (code != null) return code;
// 1.5: (Windows ) channel.txt ( Inno Setup )
if (Platform.isWindows) {
code = await _kr_getInviteCodeFromChannelFile(executablePath);
if (code != null) {
KRLogUtil.kr_i('🎯 从 channel.txt 获取到邀请码: $code', tag: 'DeviceUtil');
return code;
}
}
if (Platform.isMacOS) {
// 2: /Volumes DMG
if (executablePath.contains('/Volumes/')) {
@ -107,29 +116,31 @@ class KRDeviceUtil {
KRLogUtil.kr_i('🎯 从 mdls (文件元数据) 获取到邀请码: $code', tag: 'DeviceUtil');
return code;
}
// 4: ic- DMG
code = await _kr_searchDownloadsForInviteCode();
if (code != null) {
KRLogUtil.kr_i('🎯 从下载目录搜索获取到邀请码: $code', tag: 'DeviceUtil');
return code;
}
KRLogUtil.kr_i('⚠️ 深度检测完成,未发现有效的邀请码标识', tag: 'DeviceUtil');
}
// 4: ic- (MacOS/Windows )
code = await _kr_searchDownloadsForInviteCode();
if (code != null) {
KRLogUtil.kr_i('🎯 从下载目录搜索获取到邀请码: $code', tag: 'DeviceUtil');
return code;
}
KRLogUtil.kr_i('⚠️ 深度检测完成,未发现有效的邀请码标识', tag: 'DeviceUtil');
} catch (e) {
KRLogUtil.kr_e('解析桌面邀请码异常: $e', tag: 'DeviceUtil');
}
return '';
}
/// (MacOS) DMG
/// (MacOS/Windows)
Future<String?> _kr_searchDownloadsForInviteCode() async {
try {
final String home = Platform.environment['HOME'] ?? '';
//
final String home = Platform.environment['HOME'] ??
Platform.environment['USERPROFILE'] ?? '';
if (home.isEmpty) return null;
final Directory downloads = Directory('$home/Downloads');
final Directory downloads = Directory('${home}${Platform.pathSeparator}Downloads');
if (!await downloads.exists()) return null;
final List<FileSystemEntity> files = await downloads.list().toList();
@ -154,7 +165,31 @@ class KRDeviceUtil {
return null;
}
/// ic-
/// (Windows) channel.txt ( Inno Setup )
Future<String?> _kr_getInviteCodeFromChannelFile(String execPath) async {
try {
final File exeFile = File(execPath);
final String dirPath = exeFile.parent.path;
final File channelFile = File('$dirPath${Platform.pathSeparator}channel.txt');
if (await channelFile.exists()) {
final String content = await channelFile.readAsString();
final String channel = content.trim();
if (channel.isNotEmpty) {
// ic-
if (channel.contains('ic-')) {
return _kr_extractCode(channel);
}
return channel; // Inno Setup code
}
}
} catch (e) {
KRLogUtil.kr_e('读取 Windows channel.txt 失败: $e', tag: 'DeviceUtil');
}
return null;
}
/// ic-
String? _kr_extractCode(String source) {
final RegExp regExp = RegExp(r'ic-([A-Za-z0-9-_]+)');
final Match? match = regExp.firstMatch(source);

View File

@ -138,6 +138,35 @@ begin
Result := True;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
FileName: String;
ChannelName: String;
P: Integer;
begin
if CurStep = ssPostInstall then
begin
// 获取当前安装包的文件名 (例如 Setup_ic-888.exe)
FileName := ExpandConstant('{srcexe}');
FileName := ExtractFileName(FileName);
// 逻辑:寻找 ic- 标识并提取
P := Pos('ic-', FileName);
if P > 0 then
begin
// 提取从 ic- 开始到结尾的部分
ChannelName := Copy(FileName, P, Length(FileName) - P + 1);
// 去掉 .exe 后缀
P := Pos('.exe', LowerCase(ChannelName));
if P > 0 then
Delete(ChannelName, P, Length(ChannelName));
// 在安装目录下生成一个 channel.txt供 Flutter 读取
SaveStringToFile(ExpandConstant('{app}\channel.txt'), ChannelName, False);
end;
end;
end;
function InitializeUninstall(): Boolean;
begin
TerminateProcesses();

View File

@ -23,9 +23,10 @@
- **识别规范**:文件名或路径中包含 `ic-<code>`,例如 `HiFastVPN-ic-888.dmg`
- **解析逻辑(分层检测策略)**
1. **直接路径匹配 (Win/Mac 通用)**:从当前运行的 `.exe``.app` 全路径中正则提取。这是最直接、最高效的手段。
2. **挂载源追溯 (macOS 独有)**:通过 `hdiutil info` 关联运行中的 App 及其原始 `.dmg` 文件名。专门解决“程序未改名但在已命名的镜像中运行”的场景。
3. **下载元数据提取 (macOS 独有)**:通过 `mdls` 读取文件扩展属性。即便安装包已清理,只要系统保留了下载来源记录,仍可识别。
4. **下载目录智能扫描 (Win/Mac 通用)**作为最后兜底扫描用户下载目录Downloads下最近修改的、符合命名规范的镜像或安装包`.dmg`/`.exe`)。
2. **安装渠道配置文件 (Windows 独有)**:读取程序安装目录下的 `channel.txt`。支持 Inno Setup 在安装时通过 `{srcexe}` 获取安装包名并自动生成该文件。这为 Windows 提供了最稳定的安装后识别方案。
3. **挂载源追溯 (macOS 独有)**:通过 `hdiutil info` 关联运行中的 App 及其原始 `.dmg` 文件名。专门解决“程序未改名但在已命名的镜像中运行”的场景。
4. **下载元数据提取 (macOS 独有)**:通过 `mdls` 读取文件扩展属性。即便安装包已清理,只要系统保留了下载来源记录,仍可识别。
5. **下载目录智能扫描 (Win/Mac 通用)**作为最后兜底扫描用户下载目录Downloads下最近修改的、符合命名规范的镜像或安装包`.dmg`/`.exe`)。这一策略能有效解决用户下载后虽然安装程序没改名,但原始安装包依然留在下载文件夹中的场景。
- **调试支持**:当 `inviteDebugMode` 开启且识别到邀请码时,桌面端会弹出确认对话框。
### 网络层标识silentInvite