C#后台智能传输服务(BITS) C#如何利用Windows BITS进行文件传输

来源:这里教程网 时间:2026-02-21 17:41:54 作者:

为什么直接调用 BITS COM 接口在 C# 中容易失败

因为

IBackgroundCopyManager
等 COM 接口未被 .NET 自动封装,直接引用类型库(如
bitsadmin.exe /? 
提示的旧工具)或尝试
tlbimp
生成互操作程序集,常导致
InvalidCastException
COMException 0x80040154
(类未注册)。BITS 的 COM 接口要求严格初始化(单线程套间,STA),且部分方法需管理员权限或特定 Windows 版本支持。

必须在 STA 线程中创建和调用 COM 对象,
Thread.SetApartmentState(ApartmentState.STA)
不能事后设置,得在
Thread.Start()
前完成
推荐绕过原始 COM,改用
bitsadmin.exe
命令行封装或 Windows 10+ 的
Windows.Networking.BackgroundTransfer
UWP API(需适配桌面桥)
若坚持 COM,应使用
System.Runtime.InteropServices.ComTypes.IConnectionPointContainer
手动连接事件,而非依赖 .NET 自动生成的事件包装

用 bitsadmin.exe 封装上传任务最简可行方案

bitsadmin.exe
是 Windows 内置命令行工具,无需额外引用,适合后台服务场景。它不提供实时进度回调,但可通过轮询状态 + 退出码判断成败,稳定性远高于直连 COM。

创建任务:
bitsadmin /create /download myjob
(下载)或
/upload
(上传)
添加文件:
bitsadmin /addfile myjob "C:\local\file.zip" "https://server.com/remote/file.zip"
设置凭据(如需):
bitsadmin /setcredentials myjob server BASIC username password
开始并等待:
bitsadmin /resume myjob && bitsadmin /info myjob
,解析输出中的
STATE:
ERROR:
注意:任务名(
myjob
)必须全局唯一,服务中建议用 GUID 避免冲突

Windows 10+ 后台传输(BackgroundTransfer)在桌面应用中的限制与绕过

Windows.Networking.BackgroundTransfer
是现代替代方案,但默认仅限 UWP 应用。桌面应用(WPF/WinForms)可通过 Desktop Bridge 或
AppContainer
模式启用,否则会抛出
UnauthorizedAccessException

非桥接应用可调用该 API,但仅限“前台”任务;后台服务进程因无 UI 上下文,
CreateUploadAsync
会静默失败
若已打包为 MSIX 并声明
rescap:Capability Name="backgroundTransfer"
,则可在服务中调用,但需确保服务以交互式用户上下文运行(非 LocalSystem)
关键参数:
BackgroundTransferGroup
控制并发数,
UploadOperation.SuccessOrFailThresholdForFailureInBytes
可设断点续传阈值

服务中使用 BITS 必须处理的三个底层细节

无论选哪种方式,Windows 服务环境对 BITS 有硬性约束:网络凭据、会话隔离、权限提升。

BITS 任务默认绑定到创建它的用户会话;服务若以
LocalSystem
运行,无法访问用户凭据缓存,需显式调用
bitsadmin /setcredentials
或在 COM 中用
IBackgroundCopyJob.AddFileWithRanges
配合
IBackgroundCopyJob.SetNotifyFlags
从 Windows Vista 起,BITS 不再允许跨会话访问任务,服务中查询其他用户任务会返回
HRESULT 0x80070005
(拒绝访问)
上传大文件时,BITS 默认启用 HTTP 1.1 分块编码;若目标服务器不支持(如某些嵌入式 HTTP 服务),需提前用
bitsadmin /sethttpmethod myjob PUT
切换为完整体上传

BITS 不是“开箱即用”的后台传输黑盒——它的行为高度依赖 Windows 版本、服务登录身份、目标服务器 HTTP 实现,以及你是否愿意接受命令行封装带来的可观测性折损。

相关推荐