如何获取自定义控件被添加到的目标项目路径?
解决自定义控件获取宿主项目Resources.resx路径的问题
核心问题在于Environment.CurrentDirectory在设计时(Visual Studio中使用控件时)指向的是VS的安装目录,而非宿主项目的路径,所以会出现找不到文件的错误。要获取宿主项目的路径,需要借助Visual Studio的自动化对象模型(EnvDTE)来实现。
步骤说明
- 添加EnvDTE引用:在自定义控件项目中添加对
EnvDTE程序集的引用(可在COM组件中找到"Microsoft Development Environment 8.0",或直接引用NuGet包EnvDTE)。 - 通过Site获取DTE对象:利用
ITypeDescriptorContext的Site属性获取Visual Studio的DTE实例,进而定位到宿主项目。 - 定位Resources.resx文件:遍历项目中的Properties文件夹,找到Resources.resx并获取其完整物理路径。
修改后的代码片段
替换你代码中标记的resx_file_path行,以下是完整的修改部分:
//[ The path of .resx file. ] string resx_file_path = string.Empty; // 获取DTE对象 var dte = (EnvDTE.DTE)context.Site.GetService(typeof(EnvDTE.DTE)); if (dte != null) { // 获取当前选中的项目(即宿主项目) var project = dte.Solution.FindProjectItem(ctrl.GetType().Assembly.Location)?.ContainingProject; if (project != null) { // 遍历项目中的Properties文件夹,找到Resources.resx foreach (EnvDTE.ProjectItem item in project.ProjectItems) { if (item.Name.Equals("Properties", StringComparison.OrdinalIgnoreCase)) { foreach (EnvDTE.ProjectItem resxItem in item.ProjectItems) { if (resxItem.Name.Equals("Resources.resx", StringComparison.OrdinalIgnoreCase)) { resx_file_path = resxItem.FileNames[0]; break; } } break; } } } } // 确保路径有效再执行后续操作 if (!string.IsNullOrEmpty(resx_file_path) && File.Exists(resx_file_path)) { //[ Generates resource's name by filename. ] string resource_name = Path.GetFileName(open_file_dialog.FileName); //[ Converts file's XmlDocument to string. ] XmlDocument xml_document = new XmlDocument { XmlResolver = null }; xml_document.Load(open_file_dialog.FileName); string svg_image_document = xml_document.InnerXml; //[ Adds resource to .resx file. ] Helpers.ResourcesOperator.Add_or_Update_Resource(resource_name, svg_image_document, resx_file_path); //[ Returns only the name of resource. ] return resource_name; }
补充说明
- 设计时环境判断:可以通过
LicenseManager.UsageMode == LicenseUsageMode.Designtime来判断当前是否处于设计模式,避免运行时执行这段逻辑。 - 异常处理:建议添加try-catch块处理DTE对象获取失败的情况,防止设计时VS崩溃。
内容的提问来源于stack exchange,提问作者Simos Sigma
相关产品推荐
相关产品推荐

