发布XBAP后出现System.Reflection.TargetInvocationException问题求助
解决XBAP中读取Content XML文件的路径问题
首先,你的问题核心在于XBAP的运行环境和桌面WPF完全不同,原来用Assembly.GetExecutingAssembly().Location获取路径的方式在XBAP沙箱里不适用,而且Content文件在XBAP中是嵌入到应用包中的,不是普通的文件系统文件。
一、为什么原来的路径会失败?
- XBAP运行在浏览器沙箱中,
Assembly.GetExecutingAssembly().Location返回的是ClickOnce缓存中的路径,和你发布的Application Files目录结构完全不一致。 - 即使路径凑巧对上,沙箱的权限限制也会阻止你直接通过
File.Exists和StreamReader访问文件系统路径。
二、正确的读取方式(针对Content类型的XML)
因为你已经把XML设置为Build Action=Content和Copy Always,在XBAP中应该通过应用程序资源流来读取,而不是直接访问文件系统:
修改你的代码逻辑如下:
public partial class Page1 : Page { List<TestXML> myList = new List<TestXML>(); public Page1() { InitializeComponent(); // 用相对Uri定位Content资源 Uri xmlUri = new Uri("testxml.xml", UriKind.Relative); ReadXML(xmlUri, myList, ListBox1); } public static void ReadXML(Uri xmlUri, List<TestXML> myList, ListBox ListBox) { try { // 从应用资源流中读取文件 var resourceStream = Application.GetResourceStream(xmlUri); if (resourceStream != null) { XmlSerializer deserializer = new XmlSerializer(typeof(List<TestXML>)); // 使用using自动释放资源 using (TextReader reader = new StreamReader(resourceStream.Stream)) { var deserializedList = (List<TestXML>)deserializer.Deserialize(reader); // 修复原代码的bug:更新传入的列表(原代码只是修改了方法内的局部变量) myList.Clear(); myList.AddRange(deserializedList); } } // 将数据添加到ListBox foreach (var item in myList) { ListBox.Items.Add(item.Name); } } catch (Exception ex) { // 关键:TargetInvocationException是包装异常,InnerException才是真实错误 MessageBox.Show($"读取XML失败:{ex.InnerException?.Message ?? ex.Message}"); } } }
三、还要注意的几个细节
- 修复List赋值的bug:原来的代码中
myList = (List<TestXML>) obj;只是修改了方法内部的局部变量,类中的myList根本没被更新,上面的代码用Clear()+AddRange()来正确更新传入的列表。 - 查看真实异常:
TargetInvocationException只是一个“包装器”,你必须查看它的InnerException才能知道具体是路径找不到、权限问题还是XML序列化错误。 - XBAP权限限制:默认XBAP是部分信任模式,只能访问应用包内的资源,所以用
GetResourceStream是最稳妥的方式;如果你的XBAP是完全信任的,路径逻辑可以调整,但不推荐。
四、最后验证发布配置
确保你的XML文件确实被正确打包:
- 右键XML文件→属性,确认
Build Action=Content,Copy to Output Directory=Copy always。 - 在发布向导的“应用程序文件”中,确认该XML文件的“发布状态”是“Include”,“下载组”是“Required”。
内容的提问来源于stack exchange,提问作者niwreg
相关产品推荐
相关产品推荐

