一、插件功能描述

插件监控一个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文件同步插件开发的更多相关文章

  1. BAT实现服务器文件同步

    服务器文件同步有很多工具,例如 GoodSync.rsync.BitTorrent Sync等……其实WINDOWS下自带了一个文件同步利器:ROBOCOPY.它是一个命令行的目录复制命令,自从Win ...

  2. 使用syncthing进行双机文件同步

    使用syncthing进行双机文件同步 syncthing是一款开源的文件同步软件,可以 syncthing安装 tar -zxvf syncthing-linux-amd64-v0.12.15.ta ...

  3. sharepoint多个NLB的web前段如何进行文件同步?

    大家都知道,sharepoint2010服务器场可能有2个或2个以上的web服务器做NLB,有个时候牵涉到上传文件到文件夹(说到这里,有人会说全部以二进制文件保存到文档库啊,但是有些情况不允许的,比如 ...

  4. BitTorrent Sync - 神奇的文件同步软件,无需服务器让多台电脑互相同步!

    176,487 微博 腾讯 空间 微信 141 49 如今人们对文件备份和同步的需求已经越来越强烈了.像 Dropbox 一样的云存储网盘有很多,但它们都有一个局限性,就是所有的文件都得经过它们的服务 ...

  5. 烂泥:linux文件同步之rsync学习(一)

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 这几天刚好有空就打算开始学习linux下的文件同步软件rsync,在学习rsync时,我们可以分以下几个步骤进行: 1. rsync是什么 2. rsy ...

  6. CentOS系统rsync文件同步 安装配置

    rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync 它的特性如下: 可以镜像保存整个目录树和文件系统. 可以很容易做到保持原来文件的权限.时间.软硬 ...

  7. inotify配合rsync实现文件同步

    一.slave端rsync设置在此部署rsync服务和rsync daemon 1.安装rsync   2.配置rsyncd.conf文件#vi /etc/rsyncd.conf配置文件uid = r ...

  8. Rsync 3.1.0 发布,文件同步工具

    文件同步工具Rsync 3.1.0发布.2013-09-29 上一个版本还是2011-09-23的3.0.9 过了2年多.Rsync基本是Linux上文件同步的标准了,也可以和inotify配合做实时 ...

  9. cwRsync window下的跨服务器的文件同步

    cwRsync 是window下的文件同步软件,可以跨服务器运行,第一次运行的时候是全部备份同步,之后的同步采用的是增量同步 这个软件分为服务端和客户端. 服务器是需要同步的文件源, 客户端相当于是备 ...

随机推荐

  1. jvm参数设置 -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M

    -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M 这里有几个问题: 1. 各个参数的含义什么? 2. 为什么有的机器我将- ...

  2. OpenJudge 6042 雇佣兵

    37:雇佣兵 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 雇佣兵的体力最大值为M,初始体力值为0.战斗力为N.拥有X个能量元素. 当雇佣兵的体力值恰好为M时,才可以参加一个 ...

  3. codevs——2822 爱在心中

    2822 爱在心中  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description “每个人都拥有一个梦,即使彼此不相 ...

  4. (转)Redis

    Rdis和JQuery一样是纯粹为应用而产生的,这里记录的是在CentOS 5.7上学习入门文章: 1.Redis简介 Redis是 一个key-value存储系统.和Memcached类似,但是解决 ...

  5. C# 错误!!容量超出了最大容量。参数名: capacity 这个是什么问题呢?

    C# 错误!!容量超出了最大容量.参数名: capacity 这个是什么问题呢?   对于这个问题我纠结了好久老是报错误,报这个错误的原因是应为我加了皮肤的控件,在没有加皮肤控件的时候没有这个错误, ...

  6. mysql资料整理

    ###SQL的语言分类 1.DQL(Data Query Language):数据查询语言 select 2.DML(Data Manipulate Language):数据操作语言 insert . ...

  7. Github配置SSH

    以前也配置过ssh,但是没有注意用法,在配置一次熟悉流程 检查本机是否有ssh key设置 $ cd ~/.ssh 或cd .ssh 如果没有则提示: No such file or director ...

  8. [Rust] Load a WebAssembly Function Written in Rust and Invoke it from JavaScript

    In this lesson we are going to setup a project from scratch by introducing the JavaScript snippet to ...

  9. [RxJS] Implement RxJS `concatMap` by Waiting for Inner Subscriptions to Complete

    Unlike mergeMap and switchMap, concatMap focuses on when "inner" subscriptions "compl ...

  10. Office WORD EXCEL批量查找和替换技巧实例

    1 删除多余的空行 如果是在WORD中,则查找^p^p替换为^p.   如果是在EXCEL里,则为全部选中,然后点击编辑,定位,定位条件,空值. 将全部选中空白的行,如图所示 再次点击编辑,删除,删除 ...