feat: 支持离线运行时(runtime 目录)+ 动态生成自启 vbs
- FindNodeExe/FindDshBinJs/FindNpmCli:标准安装或应用旁 runtime 目录均可 - WriteServiceVbs 按当前环境动态生成(跨设备路径正确),启动时刷新 - .gitignore 增加 EBWebView/(WebView2 用户数据,避免误提交缓存)
This commit is contained in:
1 parent
deba852624
commit
0b868418cb
4 files changed
+115
-19
No files matched your search
@@ -6,3 +6,6 @@ start-error.log
|
|||||||
# 临时文件
|
# 临时文件
|
||||||
*.tmp
|
*.tmp
|
||||||
*.log.*
|
*.log.*
|
||||||
|
|
||||||
|
# WebView2 用户数据(仓库根下的缓存目录)
|
||||||
|
EBWebView/
|
||||||
Binary file not shown.
+111
-17
@@ -21,8 +21,9 @@ static class Program
|
|||||||
private const string RunKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
private const string RunKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
||||||
private const string RunValueName = "DeepSeekHarnessService";
|
private const string RunValueName = "DeepSeekHarnessService";
|
||||||
|
|
||||||
private const string NodeExe = @"C:\Program Files\nodejs\node.exe";
|
// 标准安装路径(联网安装的 Node 默认位置);离线包使用应用旁的 runtime 目录
|
||||||
private const string NpmCli = @"C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js";
|
private const string StdNodeExe = @"C:\Program Files\nodejs\node.exe";
|
||||||
|
private const string StdNpmCli = @"C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js";
|
||||||
|
|
||||||
private static Process serviceProcess; // 本应用拉起的 dsh 服务进程
|
private static Process serviceProcess; // 本应用拉起的 dsh 服务进程
|
||||||
private static bool startedByUs; // 服务是否由本应用启动
|
private static bool startedByUs; // 服务是否由本应用启动
|
||||||
@@ -175,6 +176,9 @@ static class Program
|
|||||||
// 后台检查 DSH 版本更新(有新版才提示,不阻塞启动)
|
// 后台检查 DSH 版本更新(有新版才提示,不阻塞启动)
|
||||||
CheckUpdateAsync();
|
CheckUpdateAsync();
|
||||||
|
|
||||||
|
// 刷新开机自启启动器(路径随当前环境,跨设备可用)
|
||||||
|
try { WriteServiceVbs(Path.Combine(AppDir(), "start-dsh-service.vbs")); } catch { }
|
||||||
|
|
||||||
Application.Run(mainForm);
|
Application.Run(mainForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +187,62 @@ static class Program
|
|||||||
return Path.GetDirectoryName(Application.ExecutablePath);
|
return Path.GetDirectoryName(Application.ExecutablePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 应用根目录(AppDir 的上一级,离线包布局 <root>/app、<root>/runtime)
|
||||||
|
static string AppRoot()
|
||||||
|
{
|
||||||
|
string d = AppDir();
|
||||||
|
return d != null ? Path.GetDirectoryName(d) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 运行时查找(标准安装 或 离线包 runtime 目录)----
|
||||||
|
|
||||||
|
static string FindNodeExe()
|
||||||
|
{
|
||||||
|
if (File.Exists(StdNodeExe)) return StdNodeExe;
|
||||||
|
string root = AppRoot();
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
string local = Path.Combine(root, "runtime", "node", "node.exe");
|
||||||
|
if (File.Exists(local)) return local;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetNodeDir()
|
||||||
|
{
|
||||||
|
string exe = FindNodeExe();
|
||||||
|
return exe != null ? Path.GetDirectoryName(exe) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FindNpmCli()
|
||||||
|
{
|
||||||
|
string nodeDir = GetNodeDir();
|
||||||
|
if (nodeDir != null)
|
||||||
|
{
|
||||||
|
string cli = Path.Combine(nodeDir, "node_modules", "npm", "bin", "npm-cli.js");
|
||||||
|
if (File.Exists(cli)) return cli;
|
||||||
|
}
|
||||||
|
if (File.Exists(StdNpmCli)) return StdNpmCli;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FindDshBinJs()
|
||||||
|
{
|
||||||
|
// 1) npm 全局(联网安装 / 离线复制到 APPDATA 的情况)
|
||||||
|
string npmDir = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm");
|
||||||
|
string p1 = Path.Combine(npmDir, "node_modules", "@deepseek-ai", "dsh", "lib", "bin.js");
|
||||||
|
if (File.Exists(p1)) return p1;
|
||||||
|
// 2) 离线包布局 <root>/runtime/dsh/node_modules
|
||||||
|
string root = AppRoot();
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
string p2 = Path.Combine(root, "runtime", "dsh", "node_modules", "@deepseek-ai", "dsh", "lib", "bin.js");
|
||||||
|
if (File.Exists(p2)) return p2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsPortOpen(int port)
|
static bool IsPortOpen(int port)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -201,14 +261,18 @@ static class Program
|
|||||||
{
|
{
|
||||||
string appDir = AppDir();
|
string appDir = AppDir();
|
||||||
string logFile = Path.Combine(appDir, "web.log");
|
string logFile = Path.Combine(appDir, "web.log");
|
||||||
string npmDir = Path.Combine(
|
string nodeExe = FindNodeExe();
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm");
|
string binJs = FindDshBinJs();
|
||||||
string binJs = Path.Combine(npmDir, "node_modules", "@deepseek-ai", "dsh", "lib", "bin.js");
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(NodeExe) || !File.Exists(binJs)) return;
|
if (nodeExe == null || binJs == null)
|
||||||
|
{
|
||||||
|
try { File.WriteAllText(Path.Combine(AppDir(), "start-error.log"),
|
||||||
|
"Node 或 dsh 未找到。nodeExe=" + (nodeExe ?? "null") + " binJs=" + (binJs ?? "null")); } catch { }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var psi = new ProcessStartInfo(NodeExe)
|
var psi = new ProcessStartInfo(nodeExe)
|
||||||
{
|
{
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
@@ -220,10 +284,10 @@ static class Program
|
|||||||
|
|
||||||
// 确保 node 与 npm 命令可用(dsh 插件可能用到)
|
// 确保 node 与 npm 命令可用(dsh 插件可能用到)
|
||||||
string path = psi.EnvironmentVariables["PATH"] ?? "";
|
string path = psi.EnvironmentVariables["PATH"] ?? "";
|
||||||
if (path.IndexOf("nodejs", StringComparison.OrdinalIgnoreCase) < 0)
|
string nodeDir = Path.GetDirectoryName(nodeExe);
|
||||||
path = @"C:\Program Files\nodejs;" + path;
|
if (nodeDir != null && path.IndexOf("nodejs", StringComparison.OrdinalIgnoreCase) < 0
|
||||||
if (path.IndexOf("npm", StringComparison.OrdinalIgnoreCase) < 0)
|
&& path.IndexOf(nodeDir, StringComparison.OrdinalIgnoreCase) < 0)
|
||||||
path = npmDir + ";" + path;
|
path = nodeDir + ";" + path;
|
||||||
psi.EnvironmentVariables["PATH"] = path;
|
psi.EnvironmentVariables["PATH"] = path;
|
||||||
|
|
||||||
// 禁用 dsh 启动遥测(可能小幅加速冷启动)
|
// 禁用 dsh 启动遥测(可能小幅加速冷启动)
|
||||||
@@ -310,6 +374,7 @@ static class Program
|
|||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
string vbs = Path.Combine(AppDir(), "start-dsh-service.vbs");
|
string vbs = Path.Combine(AppDir(), "start-dsh-service.vbs");
|
||||||
|
WriteServiceVbs(vbs);
|
||||||
key.SetValue(RunValueName, "wscript.exe \"" + vbs + "\"");
|
key.SetValue(RunValueName, "wscript.exe \"" + vbs + "\"");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -321,6 +386,25 @@ static class Program
|
|||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按当前环境动态生成隐藏启动器 vbs(路径随用户/安装位置变化)
|
||||||
|
static void WriteServiceVbs(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string nodeExe = FindNodeExe();
|
||||||
|
string binJs = FindDshBinJs();
|
||||||
|
if (nodeExe == null || binJs == null) return;
|
||||||
|
string logFile = Path.Combine(AppDir(), "web.log");
|
||||||
|
// cmd /c ""node" "bin.js" web > "log" 2>&1" (CreateProcess 剥一层引号后 cmd 仍收到带引号命令)
|
||||||
|
string inner = "cmd /c \"\"" + nodeExe + "\" \"" + binJs + "\" web > \"" + logFile + "\" 2>&1\"";
|
||||||
|
string vbs = "' Start dsh service (hidden, auto-generated)\r\n" +
|
||||||
|
"Set ws = CreateObject(\"WScript.Shell\")\r\n" +
|
||||||
|
"ws.Run \"" + inner.Replace("\"", "\"\"") + "\", 0, False\r\n";
|
||||||
|
File.WriteAllText(path, vbs);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
// ---- DSH 版本检查与升级引导(应用内完成,无需浏览器/终端)----
|
// ---- DSH 版本检查与升级引导(应用内完成,无需浏览器/终端)----
|
||||||
|
|
||||||
static void CheckUpdateAsync()
|
static void CheckUpdateAsync()
|
||||||
@@ -368,10 +452,13 @@ static class Program
|
|||||||
static string GetLocalVersion()
|
static string GetLocalVersion()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
string binJs = FindDshBinJs();
|
||||||
|
if (binJs != null)
|
||||||
{
|
{
|
||||||
string pkg = Path.Combine(
|
string pkg = Path.Combine(
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(binJs))),
|
||||||
"npm", "node_modules", "@deepseek-ai", "dsh", "package.json");
|
"package.json");
|
||||||
if (File.Exists(pkg))
|
if (File.Exists(pkg))
|
||||||
{
|
{
|
||||||
var doc = new System.Text.RegularExpressions.Regex("\"version\"\\s*:\\s*\"([^\"]+)\"");
|
var doc = new System.Text.RegularExpressions.Regex("\"version\"\\s*:\\s*\"([^\"]+)\"");
|
||||||
@@ -379,6 +466,7 @@ static class Program
|
|||||||
if (m.Success) return m.Groups[1].Value;
|
if (m.Success) return m.Groups[1].Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch { }
|
catch { }
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -387,14 +475,17 @@ static class Program
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
string nodeExe = FindNodeExe();
|
||||||
|
string cli = FindNpmCli();
|
||||||
|
if (nodeExe == null || cli == null) return "";
|
||||||
string stdout = "";
|
string stdout = "";
|
||||||
var psi = new ProcessStartInfo(NodeExe)
|
var psi = new ProcessStartInfo(nodeExe)
|
||||||
{
|
{
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
Arguments = "\"" + NpmCli + "\" view @deepseek-ai/dsh version",
|
Arguments = "\"" + cli + "\" view @deepseek-ai/dsh version",
|
||||||
};
|
};
|
||||||
using (var p = Process.Start(psi))
|
using (var p = Process.Start(psi))
|
||||||
{
|
{
|
||||||
@@ -413,14 +504,17 @@ static class Program
|
|||||||
string logFile = Path.Combine(AppDir(), "upgrade.log");
|
string logFile = Path.Combine(AppDir(), "upgrade.log");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var psi = new ProcessStartInfo(NodeExe)
|
string nodeExe = FindNodeExe();
|
||||||
|
string cli = FindNpmCli();
|
||||||
|
if (nodeExe == null || cli == null) return false;
|
||||||
|
var psi = new ProcessStartInfo(nodeExe)
|
||||||
{
|
{
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
Arguments = "\"" + NpmCli + "\" install -g @deepseek-ai/dsh@latest",
|
Arguments = "\"" + cli + "\" install -g @deepseek-ai/dsh@latest",
|
||||||
};
|
};
|
||||||
using (var p = Process.Start(psi))
|
using (var p = Process.Start(psi))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
' Start dsh (DeepSeek Harness) service in background, no window.
|
' Start dsh service (hidden, auto-generated)
|
||||||
' Used by "autostart" tray option (registry Run entry via wscript).
|
|
||||||
Set ws = CreateObject("WScript.Shell")
|
Set ws = CreateObject("WScript.Shell")
|
||||||
ws.Run "cmd /c """"C:\Program Files\nodejs\node.exe"" ""C:\Users\VanuSystems-Mu\AppData\Roaming\npm\node_modules\@deepseek-ai\dsh\lib\bin.js"" web > ""C:\Users\VanuSystems-Mu\AppData\Local\DeepSeekHarness\app\web.log"" 2>&1""", 0, False
|
ws.Run "cmd /c """"C:\Program Files\nodejs\node.exe"" ""C:\Users\VanuSystems-Mu\AppData\Roaming\npm\node_modules\@deepseek-ai\dsh\lib\bin.js"" web > ""C:\Users\VanuSystems-Mu\AppData\Local\DeepSeekHarness\app\web.log"" 2>&1""", 0, False
|
||||||
Reference in new issue
Block a user