NewLife/Stardust

应用退出时,销毁AppClient对象之后,不再允许请求业务接口
大石头 authored at 2025-07-13 22:08:16
fab9cc2
Tree
1 Parent(s) 6e3778d
Summary: 16 changed files with 57 additions and 60 deletions.
Modified +1 -1
Modified +1 -1
Modified +6 -6
Modified +5 -5
Modified +8 -12
Modified +1 -1
Modified +6 -6
Modified +4 -4
Modified +10 -10
Modified +1 -1
Modified +1 -1
Modified +1 -1
Modified +2 -2
Modified +7 -6
Modified +2 -2
Modified +1 -1
Modified +1 -1
diff --git a/Samples/TestA/TestA.csproj b/Samples/TestA/TestA.csproj
index d8fea4a..c786fbf 100644
--- a/Samples/TestA/TestA.csproj
+++ b/Samples/TestA/TestA.csproj
@@ -18,7 +18,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.5.2025.701" />
+    <PackageReference Include="NewLife.Core" Version="11.5.2025.713-beta1307" />
   </ItemGroup>
 
 </Project>
Modified +1 -1
diff --git a/Samples/TestB/TestB.csproj b/Samples/TestB/TestB.csproj
index 5ef8543..c30feee 100644
--- a/Samples/TestB/TestB.csproj
+++ b/Samples/TestB/TestB.csproj
@@ -18,7 +18,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.5.2025.701" />
+    <PackageReference Include="NewLife.Core" Version="11.5.2025.713-beta1307" />
   </ItemGroup>
 
 </Project>
Modified +6 -6
diff --git a/Stardust.Server/Controllers/AppController.cs b/Stardust.Server/Controllers/AppController.cs
index 3aea0db..4cd09b1 100644
--- a/Stardust.Server/Controllers/AppController.cs
+++ b/Stardust.Server/Controllers/AppController.cs
@@ -89,7 +89,7 @@ public class AppController : BaseController
 
         var clientId = model.ClientId;
         app ??= _registryService.Register(model.AppId, model.Secret, set.AppAutoRegister, ip, clientId);
-        _app = app ?? throw new ApiException(12, "应用鉴权失败");
+        _app = app ?? throw new ApiException(ApiCode.Unauthorized, "应用鉴权失败");
 
         _registryService.Login(app, model, ip, _setting);
 
@@ -241,7 +241,7 @@ public class AppController : BaseController
 
     private async Task HandleNotify(WebSocket socket, App app, String clientId, String ip, CancellationToken cancellationToken)
     {
-        if (app == null) throw new ApiException(401, "未登录!");
+        if (app == null) throw new ApiException(ApiCode.Unauthorized, "未登录!");
 
         using var session = new AppCommandSession(socket)
         {
@@ -286,10 +286,10 @@ public class AppController : BaseController
         var target = App.FindByName(code) ?? throw new ArgumentOutOfRangeException(nameof(model.Code), "无效应用");
 
         var app = _app;
-        if (app == null || app.AllowControlNodes.IsNullOrEmpty()) throw new ApiException(401, "无权操作!");
+        if (app == null || app.AllowControlNodes.IsNullOrEmpty()) throw new ApiException(ApiCode.Unauthorized, "无权操作!");
 
         if (app.AllowControlNodes != "*" && !target.Name.EqualIgnoreCase(app.AllowControlNodes.Split(",")))
-            throw new ApiException(403, $"[{app}]无权操作应用[{target}]!\n安全设计需要,默认禁止所有应用向其它应用发送控制指令。\n可在注册中心应用系统中修改[{app}]的可控节点,添加[{target.Name}],或者设置为*所有应用。");
+            throw new ApiException(ApiCode.Forbidden, $"[{app}]无权操作应用[{target}]!\n安全设计需要,默认禁止所有应用向其它应用发送控制指令。\n可在注册中心应用系统中修改[{app}]的可控节点,添加[{target.Name}],或者设置为*所有应用。");
 
         var cmd = await _registryService.SendCommand(target, clientId, model, app + "");
 
@@ -302,7 +302,7 @@ public class AppController : BaseController
     [HttpPost(nameof(CommandReply))]
     public Int32 CommandReply(CommandReplyModel model)
     {
-        if (_app == null) throw new ApiException(401, "节点未登录");
+        if (_app == null) throw new ApiException(ApiCode.Unauthorized, "节点未登录");
 
         var cmd = _registryService.CommandReply(_app, model);
 
@@ -319,7 +319,7 @@ public class AppController : BaseController
             info = new Service { Name = serviceName, Enable = true };
             info.Insert();
         }
-        if (!info.Enable) throw new ApiException(403, $"服务[{serviceName}]已停用!");
+        if (!info.Enable) throw new ApiException(ApiCode.Forbidden, $"服务[{serviceName}]已停用!");
 
         return info;
     }
Modified +5 -5
diff --git a/Stardust.Server/Controllers/CubeController.cs b/Stardust.Server/Controllers/CubeController.cs
index d41afa8..eb20f6d 100644
--- a/Stardust.Server/Controllers/CubeController.cs
+++ b/Stardust.Server/Controllers/CubeController.cs
@@ -16,14 +16,14 @@ public class CubeController : ControllerBase
     #region 附件
     private async Task<(Attachment att, String filePath)> GetFile(String id)
     {
-        if (id.IsNullOrEmpty()) throw new ApiException(404, "非法附件编号");
+        if (id.IsNullOrEmpty()) throw new ApiException(ApiCode.NotFound, "非法附件编号");
 
         // 去掉仅用于装饰的后缀名
         var p = id.IndexOf('.');
         if (p > 0) id = id[..p];
 
         var att = Attachment.FindById(id.ToLong());
-        if (att == null) throw new ApiException(404, "找不到附件信息");
+        if (att == null) throw new ApiException(ApiCode.NotFound, "找不到附件信息");
 
         var set = StarServerSetting.Current;
 
@@ -32,14 +32,14 @@ public class CubeController : ControllerBase
         if (filePath.IsNullOrEmpty() || !System.IO.File.Exists(filePath))
         {
             var url = att.Source;
-            if (url.IsNullOrEmpty()) throw new ApiException(404, "找不到附件文件");
+            if (url.IsNullOrEmpty()) throw new ApiException(ApiCode.NotFound, "找不到附件文件");
 
             var rs = await att.Fetch(url, set.UploadPath);
-            if (!rs) throw new ApiException(404, "附件远程抓取失败");
+            if (!rs) throw new ApiException(ApiCode.NotFound, "附件远程抓取失败");
 
             filePath = att.GetFilePath(set.UploadPath);
         }
-        if (filePath.IsNullOrEmpty() || !System.IO.File.Exists(filePath)) throw new ApiException(404, "附件文件不存在");
+        if (filePath.IsNullOrEmpty() || !System.IO.File.Exists(filePath)) throw new ApiException(ApiCode.NotFound, "附件文件不存在");
 
         return (att, filePath);
     }
Modified +8 -12
diff --git a/Stardust.Server/Controllers/NodeController.cs b/Stardust.Server/Controllers/NodeController.cs
index 2c29577..30c608e 100644
--- a/Stardust.Server/Controllers/NodeController.cs
+++ b/Stardust.Server/Controllers/NodeController.cs
@@ -26,23 +26,19 @@ public class NodeController : BaseController
 {
     private Node _node;
     private String _clientId;
-    private readonly ICacheProvider _cacheProvider;
     private readonly ITracer _tracer;
     private readonly IOptions<JsonOptions> _jsonOptions;
     private readonly NodeService _nodeService;
     private readonly TokenService _tokenService;
-    private readonly DeployService _deployService;
     private readonly NodeSessionManager _sessionManager;
     private readonly StarServerSetting _setting;
 
-    public NodeController(NodeService nodeService, TokenService tokenService, DeployService deployService, NodeSessionManager sessionManager, StarServerSetting setting, ICacheProvider cacheProvider, IServiceProvider serviceProvider, ITracer tracer, IOptions<JsonOptions> jsonOptions) : base(serviceProvider)
+    public NodeController(NodeService nodeService, TokenService tokenService, NodeSessionManager sessionManager, StarServerSetting setting, IServiceProvider serviceProvider, ITracer tracer, IOptions<JsonOptions> jsonOptions) : base(serviceProvider)
     {
-        _cacheProvider = cacheProvider;
         _tracer = tracer;
-        this._jsonOptions = jsonOptions;
+        _jsonOptions = jsonOptions;
         _nodeService = nodeService;
         _tokenService = tokenService;
-        _deployService = deployService;
         _sessionManager = sessionManager;
         _setting = setting;
     }
@@ -90,7 +86,7 @@ public class NodeController : BaseController
         var oldSecret = node?.Secret;
         _node = node;
 
-        if (node != null && !node.Enable) throw new ApiException(99, "禁止登录");
+        if (node != null && !node.Enable) throw new ApiException(ApiCode.Unauthorized, "禁止登录");
 
         // 支持自动识别2020年的XCoder版本,兼容性处理
         if (inf.ProductCode.IsNullOrEmpty())
@@ -113,7 +109,7 @@ public class NodeController : BaseController
 
         node ??= _nodeService.Register(inf, ip, _setting);
 
-        if (node == null) throw new ApiException(12, "节点鉴权失败");
+        if (node == null) throw new ApiException(ApiCode.Unauthorized, "节点鉴权失败");
 
         var tokenModel = _nodeService.Login(node, inf, ip, _setting);
 
@@ -207,7 +203,7 @@ public class NodeController : BaseController
     [HttpGet(nameof(Upgrade))]
     public UpgradeInfo Upgrade(String channel)
     {
-        var node = _node ?? throw new ApiException(401, "节点未登录");
+        var node = _node ?? throw new ApiException(ApiCode.Unauthorized, "节点未登录");
 
         // 基础路径
         var uri = Request.GetRawUrl().ToString();
@@ -291,7 +287,7 @@ public class NodeController : BaseController
     [HttpPost(nameof(Report))]
     public async Task<Object> Report(Int32 id)
     {
-        var node = _node ?? throw new ApiException(401, "节点未登录");
+        var node = _node ?? throw new ApiException(ApiCode.Unauthorized, "节点未登录");
 
         var cmd = NodeCommand.FindById(id);
         if (cmd != null && cmd.NodeID == node.ID)
@@ -335,7 +331,7 @@ public class NodeController : BaseController
     /// <param name="model">服务</param>
     /// <returns></returns>
     [HttpPost(nameof(CommandReply))]
-    public Int32 CommandReply(CommandReplyModel model) => _node == null ? throw new ApiException(401, "节点未登录") : _nodeService.CommandReply(_node, model, Token);
+    public Int32 CommandReply(CommandReplyModel model) => _node == null ? throw new ApiException(ApiCode.Unauthorized, "节点未登录") : _nodeService.CommandReply(_node, model, Token);
     #endregion
 
     #region 下行通知
@@ -370,7 +366,7 @@ public class NodeController : BaseController
     private async Task HandleNotify(WebSocket socket, String token, String ip, CancellationToken cancellationToken)
     {
         var (_, node, error) = _nodeService.DecodeToken(token, _setting.TokenSecret);
-        _node = node ?? throw new ApiException(401, $"未登录![ip={ip}]");
+        _node = node ?? throw new ApiException(ApiCode.Unauthorized, $"未登录![ip={ip}]");
         if (error != null) throw error;
 
         using var session = new NodeCommandSession(socket)
Modified +1 -1
diff --git a/Stardust.Server/Controllers/OAuthController.cs b/Stardust.Server/Controllers/OAuthController.cs
index dc4ade1..0a3f507 100644
--- a/Stardust.Server/Controllers/OAuthController.cs
+++ b/Stardust.Server/Controllers/OAuthController.cs
@@ -63,7 +63,7 @@ public class OAuthController : ControllerBase
                 var app = App.FindByName(jwt?.Subject);
                 if (app == null || !app.Enable)
                 {
-                    ex ??= new ApiException(403, $"无效应用[{jwt.Subject}]");
+                    ex ??= new ApiException(ApiCode.Unauthorized, $"无效应用[{jwt.Subject}]");
                 }
 
                 if (clientId.IsNullOrEmpty()) clientId = jwt.Id;
Modified +6 -6
diff --git a/Stardust.Server/Services/NodeService.cs b/Stardust.Server/Services/NodeService.cs
index 18cb154..13f26ef 100644
--- a/Stardust.Server/Services/NodeService.cs
+++ b/Stardust.Server/Services/NodeService.cs
@@ -246,11 +246,11 @@ public class NodeService
 
     private Node AutoRegister(Node node, LoginInfo inf, String ip, StarServerSetting set)
     {
-        if (!set.AutoRegister) throw new ApiException(12, "禁止自动注册");
+        if (!set.AutoRegister) throw new ApiException(ApiCode.Forbidden, "禁止自动注册");
 
         // 检查白名单
         //var ip = UserHost;
-        if (!IsMatchWhiteIP(set.WhiteIP, ip)) throw new ApiException(13, "非法来源,禁止注册");
+        if (!IsMatchWhiteIP(set.WhiteIP, ip)) throw new ApiException(ApiCode.Forbidden, "非法来源,禁止注册");
 
         using var span = _tracer?.NewSpan(nameof(AutoRegister), new { inf.ProductCode, inf.Node });
 
@@ -768,10 +768,10 @@ public class NodeService
         if (node == null) throw new ArgumentOutOfRangeException(nameof(model.Code), "无效节点");
 
         var (_, app) = _tokenService.DecodeToken(token, setting.TokenSecret);
-        if (app == null || app.AllowControlNodes.IsNullOrEmpty()) throw new ApiException(401, "无权操作!");
+        if (app == null || app.AllowControlNodes.IsNullOrEmpty()) throw new ApiException(ApiCode.Unauthorized, "无权操作!");
 
         if (app.AllowControlNodes != "*" && !node.Code.EqualIgnoreCase(app.AllowControlNodes.Split(",")))
-            throw new ApiException(403, $"[{app}]无权操作节点[{node}]!\n安全设计需要,默认禁止所有应用向任意节点发送控制指令。\n可在注册中心应用系统中修改[{app}]的可控节点,添加[{node.Code}],或者设置为*所有节点。");
+            throw new ApiException(ApiCode.Forbidden, $"[{app}]无权操作节点[{node}]!\n安全设计需要,默认禁止所有应用向任意节点发送控制指令。\n可在注册中心应用系统中修改[{app}]的可控节点,添加[{node.Code}],或者设置为*所有节点。");
 
         return await SendCommand(node, model, app + "");
     }
@@ -863,9 +863,9 @@ public class NodeService
         if (!rs || node == null)
         {
             if (node != null)
-                ex = new ApiException(403, $"[{node.Name}/{node.Code}]非法访问 {message}");
+                ex = new ApiException(ApiCode.Forbidden, $"[{node.Name}/{node.Code}]非法访问 {message}");
             else
-                ex = new ApiException(403, $"[{jwt.Subject}]非法访问 {message}");
+                ex = new ApiException(ApiCode.Forbidden, $"[{jwt.Subject}]非法访问 {message}");
         }
 
         return (jwt, node, ex);
Modified +4 -4
diff --git a/Stardust.Server/Services/RegistryService.cs b/Stardust.Server/Services/RegistryService.cs
index 7ddd257..35f3c65 100644
--- a/Stardust.Server/Services/RegistryService.cs
+++ b/Stardust.Server/Services/RegistryService.cs
@@ -45,12 +45,12 @@ public class RegistryService
 
         // 检查黑白名单
         if (!app.MatchIp(ip))
-            throw new ApiException(403, $"应用[{app.Name}]禁止{ip}访问!");
+            throw new ApiException(ApiCode.Forbidden, $"应用[{app.Name}]禁止{ip}访问!");
         if (app.Project != null && !app.Project.MatchIp(ip))
-            throw new ApiException(403, $"项目[{app.Project}]禁止{ip}访问!");
+            throw new ApiException(ApiCode.Forbidden, $"项目[{app.Project}]禁止{ip}访问!");
 
         // 检查应用有效性
-        if (!app.Enable) throw new ApiException(403, $"应用[{app.Name}]已禁用!");
+        if (!app.Enable) throw new ApiException(ApiCode.Forbidden, $"应用[{app.Name}]已禁用!");
 
         // 未设置密钥,直接通过
         if (app.Secret.IsNullOrEmpty()) return true;
@@ -567,7 +567,7 @@ public class RegistryService
         if (cmd == null) return null;
 
         // 防止越权
-        if (cmd.AppId != app.Id) throw new ApiException(403, $"[{app}]越权访问[{cmd.AppName}]的服务");
+        if (cmd.AppId != app.Id) throw new ApiException(ApiCode.Forbidden, $"[{app}]越权访问[{cmd.AppName}]的服务");
 
         cmd.Status = model.Status;
         cmd.Result = model.Data;
Modified +10 -10
diff --git a/Stardust.Server/Services/TokenService.cs b/Stardust.Server/Services/TokenService.cs
index 9f01042..90f4454 100644
--- a/Stardust.Server/Services/TokenService.cs
+++ b/Stardust.Server/Services/TokenService.cs
@@ -32,13 +32,13 @@ public class TokenService
 
         // 检查黑白名单
         if (!app.MatchIp(ip))
-            throw new ApiException(403, $"应用[{username}]禁止{ip}访问!");
+            throw new ApiException(ApiCode.Forbidden, $"应用[{username}]禁止{ip}访问!");
         if (app.Project != null && !app.Project.MatchIp(ip))
-            throw new ApiException(403, $"项目[{app.Project}]禁止{ip}访问!");
+            throw new ApiException(ApiCode.Forbidden, $"项目[{app.Project}]禁止{ip}访问!");
 
         // 检查应用有效性
-        if (!app.Enable) throw new ApiException(403, $"应用[{username}]已禁用!");
-        if (!app.Secret.IsNullOrEmpty() && password != app.Secret) throw new ApiException(401, $"非法访问应用[{username}]!");
+        if (!app.Enable) throw new ApiException(ApiCode.Forbidden, $"应用[{username}]已禁用!");
+        if (!app.Secret.IsNullOrEmpty() && password != app.Secret) throw new ApiException(ApiCode.Forbidden, $"非法访问应用[{username}]!");
 
         return app;
     }
@@ -113,7 +113,7 @@ public class TokenService
         };
 
         Exception ex = null;
-        if (!jwt.TryDecode(token, out var message)) ex = new ApiException(403, $"[{jwt.Subject}]非法访问 {message}");
+        if (!jwt.TryDecode(token, out var message)) ex = new ApiException(ApiCode.Forbidden, $"[{jwt.Subject}]非法访问 {message}");
 
         return (jwt, ex);
     }
@@ -133,7 +133,7 @@ public class TokenService
             Algorithm = ss[0],
             Secret = ss[1],
         };
-        if (!jwt.TryDecode(token, out var message)) throw new ApiException(403, $"非法访问[{jwt.Subject}],{message}");
+        if (!jwt.TryDecode(token, out var message)) throw new ApiException(ApiCode.Forbidden, $"非法访问[{jwt.Subject}],{message}");
 
         // 验证应用
         var app = App.FindByName(jwt.Subject);
@@ -141,11 +141,11 @@ public class TokenService
         {
             // 可能是StarAgent混用了token
             var node = Data.Nodes.Node.FindByCode(jwt.Subject);
-            if (node == null) throw new ApiException(403, $"无效应用[{jwt.Subject}]");
+            if (node == null) throw new ApiException(ApiCode.Forbidden, $"无效应用[{jwt.Subject}]");
 
             app = new App { Name = node.Code, DisplayName = node.Name, Enable = true };
         }
-        if (!app.Enable) throw new ApiException(403, $"已停用应用[{jwt.Subject}]");
+        if (!app.Enable) throw new ApiException(ApiCode.Forbidden, $"已停用应用[{jwt.Subject}]");
 
         return (jwt, app);
     }
@@ -167,11 +167,11 @@ public class TokenService
         };
 
         Exception ex = null;
-        if (!jwt.TryDecode(token, out var message)) ex = new ApiException(403, $"非法访问 {message}");
+        if (!jwt.TryDecode(token, out var message)) ex = new ApiException(ApiCode.Forbidden, $"非法访问 {message}");
 
         // 验证应用
         var app = App.FindByName(jwt.Subject);
-        if ((app == null || !app.Enable) && ex == null) ex = new ApiException(401, $"无效应用[{jwt.Subject}]");
+        if ((app == null || !app.Enable) && ex == null) ex = new ApiException(ApiCode.NotFound, $"无效应用[{jwt.Subject}]");
 
         return (app, ex);
     }
Modified +1 -1
diff --git a/Stardust.Server/Setting.cs b/Stardust.Server/Setting.cs
index 8ebc5ce..2f778bd 100644
--- a/Stardust.Server/Setting.cs
+++ b/Stardust.Server/Setting.cs
@@ -1,7 +1,7 @@
 using System.ComponentModel;
 using NewLife;
 using NewLife.Configuration;
-using NewLife.Remoting.Extensions.Models;
+using NewLife.Remoting.Models;
 using NewLife.Security;
 using XCode.Configuration;
 
Modified +1 -1
diff --git a/Stardust.Server/Stardust.Server.csproj b/Stardust.Server/Stardust.Server.csproj
index 0133030..4db5b6b 100644
--- a/Stardust.Server/Stardust.Server.csproj
+++ b/Stardust.Server/Stardust.Server.csproj
@@ -47,7 +47,7 @@
   <ItemGroup>
     <PackageReference Include="NewLife.IP" Version="2.3.2025.601" />
     <PackageReference Include="NewLife.Redis" Version="6.3.2025.701" />
-    <PackageReference Include="NewLife.Remoting.Extensions" Version="3.3.2025.701" />
+    <PackageReference Include="NewLife.Remoting.Extensions" Version="3.4.2025.713-beta1351" />
   </ItemGroup>
 
   <ItemGroup>
Modified +1 -1
diff --git a/Stardust.Web/Controllers/ConfigController.cs b/Stardust.Web/Controllers/ConfigController.cs
index f486b63..0cd3c5e 100644
--- a/Stardust.Web/Controllers/ConfigController.cs
+++ b/Stardust.Web/Controllers/ConfigController.cs
@@ -29,7 +29,7 @@ public class ConfigController : ControllerBase
     public ConfigInfo GetAll(String appId, String secret, String scope, Int32 version)
     {
         if (appId.IsNullOrEmpty()) throw new ArgumentNullException(nameof(appId));
-        if (ManageProvider.User == null) throw new ApiException(401, "未登录!");
+        if (ManageProvider.User == null) throw new ApiException(ApiCode.Unauthorized, "未登录!");
 
         // 验证
         var app = Valid(appId, secret, out var online);
Modified +2 -2
diff --git a/Stardust.Web/Stardust.Web.csproj b/Stardust.Web/Stardust.Web.csproj
index 2f9341b..d3ed483 100644
--- a/Stardust.Web/Stardust.Web.csproj
+++ b/Stardust.Web/Stardust.Web.csproj
@@ -50,10 +50,10 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Cube.Core" Version="6.5.2025.701" />
+    <PackageReference Include="NewLife.Cube.Core" Version="6.5.2025.711-beta0137" />
     <PackageReference Include="NewLife.IP" Version="2.3.2025.601" />
     <PackageReference Include="NewLife.Redis" Version="6.3.2025.701" />
-    <PackageReference Include="NewLife.Remoting.Extensions" Version="3.3.2025.701" />
+    <PackageReference Include="NewLife.Remoting.Extensions" Version="3.4.2025.713-beta1351" />
   </ItemGroup>
 
   <ItemGroup>
Modified +7 -6
diff --git a/Stardust/Monitors/StarTracer.cs b/Stardust/Monitors/StarTracer.cs
index 7dea6d2..e41072d 100644
--- a/Stardust/Monitors/StarTracer.cs
+++ b/Stardust/Monitors/StarTracer.cs
@@ -105,9 +105,10 @@ public class StarTracer : DefaultTracer
         if (_inited) return;
 
         // 自动从本地星尘代理获取地址
-        if (Client == null) throw new ArgumentNullException(nameof(Client));
+        var client = Client;
+        if (client == null) throw new ArgumentNullException(nameof(Client));
 
-        var server = Client is ClientBase cbase ? cbase.Server : (Client + "");
+        var server = client is ClientBase cbase ? cbase.Server : (client + "");
         WriteLog("星尘监控中心 Server={0} AppId={1} ClientId={2}", server, AppId, ClientId);
 
         _inited = true;
@@ -127,10 +128,10 @@ public class StarTracer : DefaultTracer
         Init();
 
         var client = Client;
-        if (client == null) return;
+        if (client == null || client is IDisposable2 ds && ds.Disposed) return;
 
         // 构建应用信息。如果应用心跳已存在,则监控上报时不需要携带应用性能信息
-        if (EnableMeter && Client is not ClientBase)
+        if (EnableMeter && client is not ClientBase)
         {
             if (_appInfo == null)
                 _appInfo = new AppInfo(_process) { Version = _version };
@@ -202,7 +203,7 @@ public class StarTracer : DefaultTracer
         }
         catch (Exception ex)
         {
-            var source = (Client as ApiHttpClient)?.Source;
+            var source = (client as ApiHttpClient)?.Source;
             var ex2 = ex is AggregateException aex ? aex.InnerException : ex;
             if (ex2 is TaskCanceledException tce)
                 Log?.Debug("监控中心[{0}]出错 {1} TaskId={2}", source, ex2.GetType().Name, tce.Task?.Id);
@@ -246,7 +247,7 @@ public class StarTracer : DefaultTracer
     void ProcessFails()
     {
         var client = Client;
-        if (client == null) return;
+        if (client == null || client is IDisposable2 ds && ds.Disposed) return;
 
         while (_fails.TryDequeue(out var model))
         {
Modified +2 -2
diff --git a/Stardust/Stardust.csproj b/Stardust/Stardust.csproj
index 76fe9a5..b34d0b0 100644
--- a/Stardust/Stardust.csproj
+++ b/Stardust/Stardust.csproj
@@ -119,10 +119,10 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Remoting" Version="3.3.2025.701" />
+    <PackageReference Include="NewLife.Remoting" Version="3.4.2025.713-beta1351" />
   </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.5.2025.701" />
+    <PackageReference Include="NewLife.Core" Version="11.5.2025.713-beta1307" />
   </ItemGroup>
 
 </Project>
Modified +1 -1
diff --git a/Test/Test.csproj b/Test/Test.csproj
index 6a2483c..52043ee 100644
--- a/Test/Test.csproj
+++ b/Test/Test.csproj
@@ -33,7 +33,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.5.2025.701" />
+    <PackageReference Include="NewLife.Core" Version="11.5.2025.713-beta1307" />
   </ItemGroup>
 
   <ItemGroup>