VS2013文件同步插件开发
一、插件功能描述
插件监控一个xml文件,当该文档有添加新元素在保存的时候将新增的元素同步到指定的目录下。
二、模板的选择
由于该功能是跟代码编辑有关的,要监控文档的保存事件,所以要在文档打开的时候就注册保存事件的响应方法。VS提供了一个接口,监听文档的打开事件,这个接口就是:IWpfTextViewCreationListener,接口代码如下,该接口只有一个方法,在文档打开的时候会调用TextViewCreated方法执行。
// 摘要:
// Listens to text view created events.
public interface IWpfTextViewCreationListener
{
// 摘要:
// Called when a text view having matching roles is created over a text data
// model having a matching content type.
//
// 参数:
// textView:
// The newly created text view.
void TextViewCreated(IWpfTextView textView);
}
所以随便选择一个模板都是可以的,只要在项目里面将模板创建的插件入口类改为继承IWpfTextViewCreationListener接口,并实现其接口即可。由于该功能需要用到选项配置功能,所以我建议读者使用Visual Stuido Package模板,因为使用该模板添加选项页会比较容易。这是msdn上在使用Visual Studio Package模板的情况下如何添加选项页的教程:http://msdn.microsoft.com/en-us/library/bb166195.aspx。我选择的是Editor Text Adornment模板,因为该模板创建的入口类就是继承IWpfTextViewCreationListener接口,但是使用该模板的话,添加选项页会比较麻烦一点。
三、添加选项页
按照msdn上的教程,我们知道需要添加两个类:继承Package的类和继承DialogPage的类,过程我就不再赘述。如果紧紧按照msdn上的教程,你会发现在工具-选项下根本没有我们添加的选项页(非Visual Studio Package模板的情况),这是为什么呢?原来在我们的csproj文件和source.extension.vsixmanifest里缺少了一些元素,按照下面的步骤就可以实现添加选项页的功能:
1、打开source.extension.vsixmanifest,选择Assets选项,点击New按钮,弹出图-1窗口

图-1
Type选择Microsoft.VisualStudio.Assembly,Source选择A project in current solution,Project选择当前的插件项目,点击OK添加完成,再次点击New按钮,这次的Type选择Microsoft.VisualStudio.VsPackage,Source和Project跟第一次的一样即可。
2、将csproj文件里的GeneratePkgDefFile元素改为true。
3、GeneratePkgDefFile元素后添加<CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory>
4、在GeneratePkgDefFile元素前添加<IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>,注意IncludeAssemblyInVSIXContainer这个元素一定要添加在GeneratePkgDefFile和CopyBuildOutputToOutputDirectory元素之前。
经过上面的四个步骤,我们添加的选项页就会显示在工具-选项里了,如果缺少了第一个步骤的话会出现”加载此属性页时出错“的错误。
四、监听保存事件
通过查看TextViewCreated函数的参数类型textView,可以知道IWpfTextView 接口并没有包含文档保存的事件。那么,我们该如何才能订阅保存事件呢?通过查找相关的资料,发现可以通过以下方式获取文档的保存事件:
//EnvDTE.DTE _dte
this._dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE;
//EnvDTE.Events _events
this._events = this._dte.Events;
//EnvDTE.DocumentEvents _docEvents
this._docEvents = this._events.DocumentEvents;
一定要记住一定要将上面的三个对象定义为全局变量,否则就没办法响应保存事件,这是因为C#的垃圾回收机制造成的,读者可以自己试一下定义为局部变量的情况。
以下是该插件的部分代码
namespace AppSettingsSync
{
public class TextViewListener
{
/// <summary>
/// 文档信息
/// </summary>
private ITextView _view; private DTE _dte;
private Events _events;
private DocumentEvents _docEvents;
/// <summary>
/// 文档是否修改过
/// </summary>
private bool _isChanged;
/// <summary>
/// 保存的时候是否自动同步到其他AppSettings.xml
/// </summary>
private bool _isAutoReplace = true;
/// <summary>
/// 触发同步操作的AppSetting.xml
/// </summary>
private string _sourceFile;
/// <summary>
/// 要被同步的AppSettings.xml所在的文件目录
/// </summary>
private string _targetFolder; /// <summary>
/// 打开文档时触发
/// </summary>
/// <param name="textView"></param>
public TextViewListener(IWpfTextView textView)
{
this._view = textView;
this._dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE;
Properties props = this._dte.get_Properties("IStrong", "AppSettingsSync");
if (props == null)
return;
this._sourceFile = (string)props.Item("SourceXmlFilePath").Value;
//File.AppendAllText(@"D:\log.txt", "源文件" + this._sourceFile + "当前文件" + this._dte.ActiveDocument.FullName);
if (!this._dte.ActiveDocument.FullName.Equals(this._sourceFile, StringComparison.OrdinalIgnoreCase))
return;
//获取DTE对象
this._events = this._dte.Events;
this._docEvents = this._events.DocumentEvents;
//订阅文档保存和修改事件
this._docEvents.DocumentSaved += _docEvents_DocumentSaved;
this._view.TextBuffer.Changed += TextBuffer_Changed;
} /// <summary>
/// 文档修改事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void TextBuffer_Changed(object sender, Microsoft.VisualStudio.Text.TextContentChangedEventArgs e)
{
if (e.Changes.Count() > )
this._isChanged = true;
} /// <summary>
/// 文档保存事件
/// </summary>
/// <param name="Document"></param>
async void _docEvents_DocumentSaved(Document Document)
{
try
{
//File.AppendAllText(@"D:\log.txt", "触发保存事件");
//获取Tool->Opetions->IStrong->AppSettingsSync配置项内容
Properties props = this._dte.get_Properties("IStrong", "AppSettingsSync");
if (props == null)
return;
this._sourceFile = (string)props.Item("SourceXmlFilePath").Value;
//保存时要同时满足是源AppSettings.xml文件和该文件有被修改过
if (Document.FullName.Equals(this._sourceFile, StringComparison.OrdinalIgnoreCase) && this._isChanged)
{
this._isAutoReplace = (bool)props.Item("IsAutoSync").Value;
this._targetFolder = (string)props.Item("TargetFolder").Value;
//手动选择要同步的文件
if (!this._isAutoReplace)
{
SelectFiles sf = new SelectFiles(this._sourceFile, this._targetFolder);
sf.ShowDialog();
this._isChanged = false;
}
else
{
//自动同步文件
string fileName = System.IO.Path.GetFileName(this._sourceFile);
string[] files = Directory.GetFiles(this._targetFolder, fileName, SearchOption.AllDirectories);
this._isChanged = false;
await SyncHelper.SyncAppSettings(this._sourceFile, files);
//同步完成后修改Visual Studio状态栏信息
IVsStatusbar bar = ServiceProvider.GlobalProvider.GetService(typeof(SVsStatusbar)) as IVsStatusbar;
bar.SetText("AppSettings配置文件同步完成。");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
获取VS的主题颜色
/// <summary>
/// 将模态窗口的颜色设置为Visual Studio的背景色
/// </summary>
/// <param name="themeColor"></param>
/// <returns></returns>
private Color converVsThemeColor(vsThemeColors themeColor)
{
DTE2 dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.12.0");
uint color = dte2.GetThemeColor(themeColor);
int a = (int)color / 0x1000000;
int b = (int)(color - a * 0x1000000) / 0x10000;
int g = (int)(color - a * 0x1000000 - b * 0x10000) / 0x100;
int r = (int)(color - a * 0x1000000 - b * 0x10000 - g * 0x100);
return Color.FromArgb(0xFF, r, g, b);
}
VS2013文件同步插件开发的更多相关文章
- BAT实现服务器文件同步
服务器文件同步有很多工具,例如 GoodSync.rsync.BitTorrent Sync等……其实WINDOWS下自带了一个文件同步利器:ROBOCOPY.它是一个命令行的目录复制命令,自从Win ...
- 使用syncthing进行双机文件同步
使用syncthing进行双机文件同步 syncthing是一款开源的文件同步软件,可以 syncthing安装 tar -zxvf syncthing-linux-amd64-v0.12.15.ta ...
- sharepoint多个NLB的web前段如何进行文件同步?
大家都知道,sharepoint2010服务器场可能有2个或2个以上的web服务器做NLB,有个时候牵涉到上传文件到文件夹(说到这里,有人会说全部以二进制文件保存到文档库啊,但是有些情况不允许的,比如 ...
- BitTorrent Sync - 神奇的文件同步软件,无需服务器让多台电脑互相同步!
176,487 微博 腾讯 空间 微信 141 49 如今人们对文件备份和同步的需求已经越来越强烈了.像 Dropbox 一样的云存储网盘有很多,但它们都有一个局限性,就是所有的文件都得经过它们的服务 ...
- 烂泥:linux文件同步之rsync学习(一)
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 这几天刚好有空就打算开始学习linux下的文件同步软件rsync,在学习rsync时,我们可以分以下几个步骤进行: 1. rsync是什么 2. rsy ...
- CentOS系统rsync文件同步 安装配置
rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync 它的特性如下: 可以镜像保存整个目录树和文件系统. 可以很容易做到保持原来文件的权限.时间.软硬 ...
- inotify配合rsync实现文件同步
一.slave端rsync设置在此部署rsync服务和rsync daemon 1.安装rsync 2.配置rsyncd.conf文件#vi /etc/rsyncd.conf配置文件uid = r ...
- Rsync 3.1.0 发布,文件同步工具
文件同步工具Rsync 3.1.0发布.2013-09-29 上一个版本还是2011-09-23的3.0.9 过了2年多.Rsync基本是Linux上文件同步的标准了,也可以和inotify配合做实时 ...
- cwRsync window下的跨服务器的文件同步
cwRsync 是window下的文件同步软件,可以跨服务器运行,第一次运行的时候是全部备份同步,之后的同步采用的是增量同步 这个软件分为服务端和客户端. 服务器是需要同步的文件源, 客户端相当于是备 ...
随机推荐
- 什么是Istio
本文主要是对Istio Prelim 1.0(https://preliminary.istio.io/docs/)的翻译 Istio:一种开放式平台,用于连接,管理和保护微服务. Istio提供了一 ...
- mysql5.7.20主从和主主搭建
环境描述mysql主从和主主同步 注意事项:1)同步服务器网络联通,ping通,对方授权信息连接到对方数据库(防火墙开发3306)2)关闭SELinux3)同步前,双方数据库需要同步数据保持一致. 主 ...
- hdu 2112
#include<stdio.h> #include<string.h> #define N 200 #define inf 999999999999 __int64 map[ ...
- 如何在Eclipse中生成Native类对应的JNI的.h文件
1 致谢 感谢super_level网友 他的博客写的很清楚 给了我很多帮助 链接如下:http://blog.csdn.net/super_level/article/details/2124353 ...
- [codevs] 1699 开关灯
题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人 ...
- CF830B:Cards Sorting
对叠放着的n张牌,第i张牌写有数字Ai,进行操作:将牌堆顶的牌取出,若是当前牌堆最小值就扔掉,否则放到牌堆底,求牌堆空时操作次数. 怎么看怎么像约瑟夫..不过约瑟夫DP我不太熟,于是就yy了一下 “当 ...
- hdu 4049 Tourism Planning [ 状压dp ]
传送门 Tourism Planning Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- windows 下安装Apache httpd 只需三步
1.下载 Apache 官网地址:http://httpd.apache.org/docs/current/platform/windows.html#down 找到这个, 看到这几个选项: Apac ...
- Servlet的Service方法和doget 和 dopost方法的区别,常见的错误解析
package com.sxt.in; import java.io.IOException; import javax.servlet.ServletException; import javax. ...
- MySQL查询在一个表而不在另一个表中的数据
1.使用not in,容易理解,效率低 select distinct A.ID from A where A.ID not in (select ID from B) 2.使用left join.. ...