MSIX打包应用中BITS后台下载任务触发BG_JOB_STATE_TRANSIENT_ERROR问题排查
问题描述
开发基于BITS(后台智能传输服务)的文件下载应用,未打包时运行正常,使用MSIX打包后出现异常:所有由打包应用启动的后台复制任务会立即进入BG_JOB_STATE_TRANSIENT_ERROR状态,仅当应用关闭或变为非活动/最小化状态时,任务状态才会更新。
通过bitsadmin /list /allusers /verbose命令获取到的关键错误信息:
ERROR CODE: 0x8020006e - The background access settings of the job's owner app prevent the job from transferring at this time.
完整命令输出:
GUID: {A8C6001C-182D-424B-86DC-6C8E131E185B} DISPLAY: 'Download an update' TYPE: DOWNLOAD STATE: TRANSIENT_ERROR OWNER: .... PRIORITY: NORMAL FILES: 0 / 1 BYTES: 0 / UNKNOWN CREATION TIME: 9/2/2022 11:33:08 AM MODIFICATION TIME: 9/2/2022 11:33:58 AM COMPLETION TIME: UNKNOWN ACL FLAGS: NOTIFY INTERFACE: UNREGISTERED NOTIFICATION FLAGS: 3 RETRY DELAY: 600 NO PROGRESS TIMEOUT: 1209600 ERROR COUNT: 0 PROXY USAGE: PRECONFIG PROXY LIST: NULL PROXY BYPASS LIST: NULL ERROR FILE: ... ERROR CODE: 0x8020006e - The background access settings of the job's owner app prevent the job from transferring at this time. ERROR CONTEXT: 0x00000002 - The error occurred in the Background Intelligent Transfer Service (BITS) queue manager. DESCRIPTION: JOB FILES: 0 / UNKNOWN WORKING ... NOTIFICATION COMMAND LINE: none owner MIC integrity level: MEDIUM owner elevated ? false Peercaching flags Enable download from peers :false Enable serving to peers :false CUSTOM HEADERS: NULL
已尝试调整任务优先级、寻找MSIX清单权限选项、改用BackgroundDownloader(仅适用于UWP),均未解决问题。当前使用的BITS任务代码基于BITS-Manager,打包后可稳定复现问题:
internal class DownloadJob : BITS.IBackgroundCopyCallback { private readonly TaskCompletionSource taskCompletionSource; private BITS.IBackgroundCopyJob job; public DownloadJob() { this.taskCompletionSource = new TaskCompletionSource(); this.job = null; } public Task Start(string name, string url, string path, Action<byte[]> onJobIdCreated) { try { var manager = new BITS.BackgroundCopyManager1_5(); GUID jobGuid; manager.CreateJob( name, BITS.BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out jobGuid, out job); onJobIdCreated(jobGuid.GetBytes()); job.AddFile(url, path); job.SetDownloadCost(Costs.TRANSFER_STANDARD); job.DisablePeerCaching(); this.RegisterListenerFor(job); job.Resume(); } catch { job?.Cancel(); taskCompletionSource.TrySetException(new DownloadFailedException()); } return taskCompletionSource.Task; } public void JobTransferred(BITS.IBackgroundCopyJob job) { job?.Complete(); taskCompletionSource.TrySetResult(); } public void JobError(BITS.IBackgroundCopyJob job, BITS.IBackgroundCopyError error) { job?.Cancel(); taskCompletionSource.TrySetException(new DownloadFailedException()); } public void JobModification(BITS.IBackgroundCopyJob pJob, uint dwReserved) { } }
当前MSIX打包清单:
<?xml version="1.0" encoding="utf-8"?> <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap rescap"> <Identity Name="..." Publisher="..." Version="1.0.0.0" /> <Properties> <DisplayName>BITSManagerPackaged</DisplayName> <PublisherDisplayName>...</PublisherDisplayName> <Logo>Images\StoreLogo.png</Logo> </Properties> <Dependencies> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" /> </Dependencies> <Resources> <Resource Language="x-generate"/> </Resources> <Applications> <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> <uap:VisualElements DisplayName="BITSManagerPackaged" Description="BITSManagerPackaged" BackgroundColor="transparent" Square150x150Logo="Images\Square150x150Logo.png" Square44x44Logo="Images\Square44x44Logo.png"> <uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" /> <uap:SplashScreen Image="Images\SplashScreen.png" /> </uap:VisualElements> </Application> </Applications> <Capabilities> <Capability Name="internetClient" /> <rescap:Capability Name="runFullTrust" /> </Capabilities> </Package>
问题原因
这是MSIX打包应用的已知行为:MSIX容器会限制前台活跃应用发起的BITS任务,默认仅允许应用进入后台(非活动/最小化)或关闭时执行BITS任务,目的是平衡前台资源占用与后台任务调度。
解决方法
方法1:配置MSIX后台权限+调整BITS任务执行策略
- 修改MSIX清单:在
<Application>节点内添加后台任务声明,并补充对应权限
<Extensions> <uap:Extension Category="windows.backgroundTasks" EntryPoint="$targetentrypoint$"> <uap:BackgroundTasks> <uap:Task Type="general" /> </uap:BackgroundTasks> </uap:Extension> </Extensions>
同时更新<Capabilities>节点:
<Capability Name="internetClient" /> <Capability Name="internetClientServer" /> <rescap:Capability Name="runFullTrust" /> <rescap:Capability Name="backgroundMediaPlayback" />
- 调整BITS任务代码:设置任务为低优先级,并允许前台活跃时执行
在Start方法的job.Resume()前添加以下代码:
// 设置任务优先级为低,适配后台调度 job.SetPriority(BITS.BG_JOB_PRIORITY.BG_JOB_PRIORITY_LOW); // 强制允许任务在应用前台活跃时运行 var job2 = (BITS.IBackgroundCopyJob2)job; job2.SetForegroundPriority(false);
方法2:使用BITS传输策略强制允许前台执行
通过IBackgroundCopyJob3接口设置传输策略,直接允许任务在用户活跃(应用前台)时运行:
var job3 = (BITS.IBackgroundCopyJob3)job; job3.SetTransferPolicy(BITS.BG_TRANSFER_POLICY.BG_TRANSFER_POLICY_ALLOW_WHEN_USER_IS_ACTIVE);
方法3:升级SDK版本优化权限
将项目的Target Windows SDK版本升级至19041及以上,同时更新MSIX清单中的Windows.Desktop目标版本:
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.0" />
更高版本的SDK对MSIX容器的后台权限限制更宽松,能更好地适配BITS任务调度。
验证方式
修改配置后重新打包应用,启动后发起BITS下载任务,执行bitsadmin /list /allusers /verbose查看任务状态,若状态变为TRANSFERRING则说明配置生效。
内容的提问来源于stack exchange,提问作者Balázs Szántó

