这里简单介绍如何在VS2010开发环境下制作安装项目,其中包括如何设置开机启动、删除注册表及安装后自动运行,加上卸载功能。
1、? 创建安装项目
??? 打开VS2010,点击菜单上的“文件”>>“新建”>>“项目”,弹出如下对话框。
?
??? 如上图所示,在“其他项目类型”中选择“安装项目”,根据自己的需求命名,这里命名为“MySetup”,选择保存路径。这样就创建了一个安装项目。
2、?在安装项目中添加其他应用程序项目 点击菜单上的“文件”>>“添加”>>“现有项目”,弹出如下对话框。
??? 这里选择之前已经做好的一个WPF应用程序项目
3、?将WPF的可执行文件(.exe)、类库(.dll文件)及所需图片加入安装项目中 右击“MySetup”>>“视图”>>“文件系统”,主窗口显示文件系统界面,如下图
??? 右击“应用程序文件夹”>>“添加”>>“项目输出”,弹出如下对话框。
??? 在“项目”选项中选择“DataServiceHost”,按住“Ctrl”键,选中“主输出”和“内容文件”,单击“确定”。 再右击“应用程序文件夹”>>“添加”>>“文件夹”,命名为“Images”,在“Images”中放入应用程序需要的图片,右击“Images”>>“添加”>>“文件”,在弹出的对话框中添加所需的图片。
4、?创建快捷方式 在“应用程序文件夹”中右击“主输出来自DataServiceHost(活动)”,如下图。
?? 点击“创建主输出来自DataServiceHost(活动)的快捷方式”,将快捷方式重命名为“我的WPF应用程序”,这里可以根据需要命名。 在“文件系统”中的“用户的“程序”菜单”添加文件夹“我的WPF应用程序”,这里可以根据需求命名,将之前“我的WPF应用程序快捷方式”剪切到该文件夹中。 同理可以在“文件系统”中的“用户桌面”中创建快捷方式。(在用户桌面中不要添加文件夹)
5、?实现安装程序卸载 这里直接引用了Windows系统中自带的一个卸载程序,该卸载程序在“C:/Windows/System32”文件夹中,名称为“msiexec.exe”,右击“应用程序文件夹”>>“添加”>>“文件”,将“msiexec.exe”加入“应用程序文件夹”中
??? 同步骤4,创建卸载程序的快捷方式,这里建议不要在“用户桌面”中创建卸载程序,难看!!! 重点,“卸载快捷方式”的属性“Argument”值设为“/x{710AD120-3D4C-430D-A9FA-A1D504465CC8}”,其中“{710AD120-3D4C-430D-A9FA-A1D504465CC8}”可在“MySetup”属性框口中找到。左击“MySetup”(不是右击),再点击属性窗口,如下图。 “ProductName”属性值就是上述的“{710AD120-3D4C-430D-A9FA-A1D504465CC8}”。
6、?改变各快捷方式的图标 这里只拿“我的WPF应用程序快捷方式”为例,其他同理。 在“应用程序文件夹”中的“Images”中添加需要的“.ico图标”,这里添加一个“mywpf.ico”图标。如下图。 右击“我的WPF应用程序快捷方式”>>“属性窗口”,属性窗口如下图。 设置“Icon”属性,选择“Images”中的“mywpf.ico”图标。
7、?实现开机启动 右击“MySetup”>>“视图”>>“注册表”,主窗口显示如下图。
?? 在“HKEY_LOCAL-MACHINE”文件夹下新建键“Software”>>“Microsoft”>>“Windows”>>“CurrentVersion”>>“Run”,在“Run”文件夹新建字符串值,命名为“DataServiceHost.exe”,可根据需求命名,右击“DataServiceHost”>>“属性窗口”,其中“Value”属性设为“[TARGETDIR] DataServiceHost.exe”。如此,便实现了开机启动。
8、?实现安装后自动运行及删除注册表 实现这两个功能就需要一些技巧,点击菜单上的“文件”>>“添加”>>“新项目”,如下图。 在“HKEY_LOCAL-MACHINE”文件夹下新建键“Software”>>“Microsoft”>>“Windows”>>“CurrentVersion”>>“Run”,在“Run”文件夹新建字符串值,命名为“DataServiceHost.exe”,可根据需求命名,右击“DataServiceHost”>>“属性窗口”,其中“Value”属性设为“[TARGETDIR] DataServiceHost.exe”。如此,便实现了开机启动。
8、?实现安装后自动运行及删除注册表 实现这两个功能就需要一些技巧,点击菜单上的“文件”>>“添加”>>“新项目”,如下图。
选择“安装程序类”,命名为“Installer”。 在“Installer.cs”代码中重写如下方法:
///
/// 函数入口——主函数
///
public static void Main()
{
}
public Installer1()
{
InitializeComponent();
}
///
/// 重写安装完成后函数
/// 实现安装完成后自动启动已安装的程序
///
///
protected override void OnAfterInstall(IDictionary savedState)
{
base.OnAfterInstall(savedState);
}
///
/// 重写安装过程方法
///
///
///
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
}
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);
}
///
/// 重写卸载方法
///
///
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
}
///
/// 重写卸载完成后函数
/// 实现安装完成后自动删除注册表
///
///
protected override void OnAfterUninstall(IDictionary savedState)
{
base.OnAfterUninstall(savedState);
}
///
/// 重写回滚方法
///
///
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
这里对protected override void OnAfterInstall(IDictionary savedState){}和protected override void OnAfterUninstall(IDictionary savedState){}进行如下自定义操作(当然也可以对其它方法进行自定义以实现其它功能)。
protected override void OnAfterInstall(IDictionary savedState)
{
base.OnAfterInstall(savedState);
Assembly asm = Assembly.GetExecutingAssembly();
string path = asm.Location.Remove(asm.Location.LastIndexOf("\\")) + "\\";
try
{
System.Diagnostics.Process.Start(path + "\\DataServiceHost.exe");
}
catch (Exception my)
{
throw new Exception(my.Message);
}
}
protected override void OnAfterUninstall(IDictionary savedState)
{
base.OnAfterUninstall(savedState);
RegistryKey hklm = Registry.LocalMachine;
RegistryKey run = hklm.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
try
{
run.DeleteValue("DataServiceHost.exe");
run.Close();
hklm.Close();
}
catch (Exception my)
{
throw new Exception(my.Message);
}
}
自定义操作完成后,一定要将应用程序生成,这样就可以得到“.dll”文件。
生成成功后,就可以将该“.dll”程序集添加到安装项目中。右击“MySetup”>>“视图”>>“自定义操作”,主窗口如下图。
右击“安装”>>“添加自定义操作”,弹出如下对话框。
在“应用程序文件夹”中添加程序集,在之前“InstallService应用程序”中debug文件夹中找到“.dll”文件,添加进去。这样便实现了安装后自动运行和卸载后删除注册表的功能。9、?现在可以点击生成
右击“MySetup”>>“生成”,成啦!!!在安装项目中Debug文件夹中找到“Setup.msi”,双击就可以安装了….
10 Context.Parameters["targetdir"]为获取安装路径,需要在部署项目中设置?其次,在部署项目的自定义操作中,把安装,提交,回滚,卸载都添加上面项目的主输出设置主输出的属性CustomActionData值为/targetdir="[TARGETDIR]\",这样Context.Parameters["targetdir"]才能获取到安装路径。
?
当原始控件无法满足你的开发要求的时候,自定义控件无疑使最好的选择。
关于自定义控件的使用:
一般情况下,在VS2010等版本的IDE中会将你的自定义控件自动加载到你的工具箱,但是也有些时候,VS不会自动加载,但是再程序中控件是可用的。这就会对使用自定义控件造成一定的麻烦,原因是自定义控件没有自动加载,需要手动载入。
手动载入方法: 在工具箱新建一个选项卡,右键-选择项(I)(英文:choose items)选择浏览,找到自定义控件的dll 文件,加载,即可!
在设计自定义控件时,系统默认生成的图标比较单一难看,如何为控件设计自己的图标呢,这里给出了一种基于ToolBoxBitmap?属性设置自定义控件工具箱图标的方法。
1)首先将图标文件名改为自定义控件名,如自定义控件类为
??public?partial?class?UserDefindControl:?UserControl ????????{ ????????}
那么就要将图标图片文件更名为UserDefindControl,如UserDefindControl.bmp
2)然后将图标图片复制到程序根目录下,在解决方案管理器中在项目名称右键选择“添加”—>“添加现有项”,将图标图片加入到项目中,对图片资源的属性进行修改,将“生成操作”一栏该为“嵌入的资源”。
3)添加代码。在类头部添加如下代码
??[ToolboxBitmap(typeof(UserDefindControl),"UserDefindControl.bmp")]//新添加的代码
??public?partial?class?UserDefindControl:?UserControl ????????{ ????????}
需要注意的是,使用ToolboxBitmap时需要添加using?System.Drawing引用。
如果图标图片不是放在程序根目录下,就要调整以上代码。比如图片放在程序根目录的下一级目录文件夹Icons下时,代码就要修改为:
[ToolboxBitmap(typeof(UserDefindControl),"Icons.UserDefindControl.bmp")]
至此,控件的自定义工具箱图标设置就完成了,编译程序,然后把控件拖到工具箱中试试吧!
基本介绍篇
??? 在实现这个扩展之前,让我们先弄清楚这个扩展实现什么功能。这个扩展实际上是在你的VS窗口的右上角创建了一个信息框代码。该信息框显示您的源代码的统计信息。这些信息包括:
??? 1、文件的代码行数??? 2、文件的字符数??? 3、命名空间的个数??? 4、字段个数??? 5、接口个数??? 6、类的个数??? 7、函数个数??? 8、属性个数??? 9、注释的数量???10、统计文件的大小(Bytes, KB, MB等)。
??? 当您键入您的代码,你会看到信息窗口中的数据会即时更新。
??? 这个信息窗口,是利用可扩展面板。你可以把它看成两个部分,每一个部分都可以根据您的需要展开和折叠。这样,当你不需要它时,你将它可以折叠起来,需要的时候,将它展开。下面演示如何展开/折叠这个控件。
?
??? 这个控件有三个特殊的状态。第一个状态是一个很小的扩展按钮。如上图的第一部分。只需点击它,就会打开控件右侧的面板,这个面板显示文件的基本数据,如上图的第二部分。这个控件还有一个可扩展面板,如果点击扩展,就会看到下面的面板,其中显示其他的统计数据,如上图的第三部分。
实现篇:
??? 需要软件:
??? 1、 Microsoft Visual Studio 2010??? 2、 Visual Studio 2010 SDK
??? 你安装 Visual Studio SDK之后,你的Visual Studio 2010中会多出下面这些模板:
??? 这篇文章中,我们使用模板Editor ViewPort Adornment实现这个扩展,此模板将为你的代码编辑器的带来一个装饰品。?
??? 其实这个扩展包一个WPF用户控件,我把它放进VS的视窗中就成了信息框。它还含有两个类,一个类用来解析代码,获取代码的相关信息;另一个类用来处理自定义编辑器的事件和当页以及加载的时候将WPF控件添加到页面中。
第一步:创建一个Viewport Adornment项目
??? 我们从Extensibility中选择Viewport Adornment模板创建一个项目。这将生成一个SourceManifest文件和两个类文件。一个是Adornment类本身,另外一个是AdornmentFactory类。
第二步:添加一个WPF用户控件
??? 右键单击项目,选择添加一个新的WPF用户控件。为了简单起见,我使用了一个用户控件。这个用户控件实际上包含一个Expander控件,设置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一个Expander ,设置里面的这个Expander的ExpandDirection = Down。看下面的代码(我删除不必要的元素,使其更简单):
?1?
??
<
Expander?
ExpandDirection
="Left"
?Style
="
{DynamicResource?ExpanderStyle1}
"
?
?2?
???????????x:Name
="expMain"
?
>
?3?
??
<
StackPanel
>
?4?
????????????????
<
TextBlock?
x:Name
="txtNoLines"
?
?5?
???????????????????????????Text
="No?of?Lines?:?{0}"
?
?6?
???????????????????????????Margin
="25?25?25?0"
?
?7?
???????????????????????????FontSize
="12"
?
?8?
???????????????????????????FontFamily
="Verdana"
?
?9?
???????????????????????????FontWeight
="Bold"
?
10?
???????????????????????????Foreground
="Yellow"
>
TextBlock
>
11?
????????????????
<
TextBlock?
x:Name
="txtNoCharacters"
?
12?
???????????????????????????Text
="No?of?Characters?:?{0}"
?
13?
???????????????????????????Margin
="25?5?25?15"
?
14?
???????????????????????????FontSize
="12"
?
15?
???????????????????????????FontFamily
="Verdana"
?
16?
???????????????????????????FontWeight
="Bold"
?
17?
???????????????????????????Foreground
="Yellow"
>
TextBlock
>
18?
????????????????
<
Expander?
x:Name
="expCodeInfo"
?ExpandDirection
="Down"
?
19?
?????????????????????????????????????Header
="Code?Information"
>
20?
????????????????????
<
StackPanel
>
21?
????????????????????????
<
TextBlock?
x:Name
="txtClassInfo"
?
22?
???????????????????????????????????Margin
="25?25?25?0"
?
23?
???????????????????????????????????FontSize
="12"
?
24?
???????????????????????????????????FontFamily
="Verdana"
?
25?
???????????????????????????????????FontWeight
="Bold"
?
26?
???????????????????????????????????Foreground
="LightYellow"
/>
27?
????????????????????????
<
Line
28?
??????????????????????????????
Margin
="0,4"
29?
??????????????????????????????SnapsToDevicePixels
="True"
30?
??????????????????????????????Stroke
="Gold"
31?
??????????????????????????????Stretch
="Fill"
32?
??????????????????????????????X1
="0"
?X2
="1"
?
33?
??????????????????????????????
/>
34?
????????????????????????
<
TextBlock?
x:Name
="txtFileSize"
35?
???????????????????????????????????Margin
="25?5?25?15"
?
36?
???????????????????????????????????FontSize
="12"
?
37?
???????????????????????????????????FontFamily
="Verdana"
?
38?
???????????????????????????????????FontWeight
="Bold"
?
39?
???????????????????????????????????Foreground
="AliceBlue"
/>
40?
????????????????????
StackPanel
>
41?
????????????????
Expander
>
42?
????????????
StackPanel
>
43?
?????????
Expander
>
??? 你可以看到,代码很简单,两个Expanders,一个用来显示基本的统计信息和另外一个显示扩展的统计信息。我还使用StackPanel来固定TextBlocks布局。
??? 现在,如果你看一下后台代码,发现它也一样简单。其实我已经创建了一个CodeInfoTracker类,用它来为我们分析源代码文件。我只是为我们的用户控件添加了一个构造函数,使用户控件更具扩展性而已。
?1?
private
?CodeInfoTracker?_cinfo;
?2?
private
?CodeInfoTracker.Calculators?_calculator;
?3?
public
?ucInfoBox(CodeInfoTracker?cinfo)
?4?
????????????:?
this
()
?5?
{
?6?
????????
this
._cinfo?
=
?cinfo;
?7?
}
?8?
?
public
?
void
?UpdateInfo(CodeInfoTracker?info)
?9?
?{
10?
????????????_calculator?
=
?info.PerFormCalculate();
11?
????????????
this
.txtNoLines.Text?
=
?
string
.Format(
"
No?of?Lines?:?{0}
"
,?
12?
????????????????????????????????????_www.sychzs.cn_of_lines);
13?
????????????
this
.txtNoCharacters.Text?
=
?
string
.Format(
"
No?of?Characters?:?{0}
"
,?
14?
???????????????????????????????????????????????????????_www.sychzs.cn_of_characters);
15?
????????????
this
.txtFileSize.Text?
=
?
string
.Format(
"
Total?File?Size?:?{0}
"
,?
16?
???????????????????????????????????????????????????????_calculator.totalfilesize);
17?
18?
????????????StringBuilder?builder?
=
?
new
?StringBuilder();
19?
????????????
if
?(
this
._calculator.interfaces?
!=
?
0
)
20?
????????????????builder.AppendFormat(
"
Interfaces?:?{0}\n\r
"
,?
21?
??????????????????????????????????????????
this
._calculator.interfaces);
22?
????????????
if
?(
this
._calculator.namespaces?
!=
?
0
)
23?
????????????????builder.AppendFormat(
"
NameSpaces?:?{0}\n\r
"
,?
24?
????????????????????????????????????????????
this
._calculator.namespaces);
25?
????????????
if
?(
this
._calculator.classes?
!=
?
0
)
26?
????????????????builder.AppendFormat(
"
Classes?:?{0}\n\r
"
,?
27?
????????????????????????????????????????????
this
._calculator.classes);
28?
????????????
if
?(
this
._calculator.methods?
!=
?
0
)
29?
????????????????builder.AppendFormat(
"
Methods?:?{0}\n\r
"
,?
this
._calculator.methods);
30?
????????????
if
?(
this
._calculator.properties?
!=
?
0
)
31?
????????????????builder.AppendFormat(
"
Properties?:?{0}\n\r
"
,?
32?
???????????????????????????????????????????????
this
._calculator.properties);
33?
????????????
if
?(
this
._calculator.fields?
!=
?
0
)
34?
????????????????builder.AppendFormat(
"
Fields?:?{0}\n\r
"
,?
this
._calculator.fields);
35?
????????????
if
?(
this
._calculator.comments?
!=
?
0
)
36?
????????????????builder.AppendFormat(
"
Comments?:?{0}\n\r
"
,?
this
._calculator.comments);
37?
38?
????????????
if
?(builder.Length?
>
?
0
)
39?
????????????{
40?
????????????????
this
.txtClassInfo.Visibility?
=
?System.Windows.Visibility.Visible;
41?
????????????????
this
.txtClassInfo.Text?
=
?builder.ToString();
42?
????????????}
43?
????????????
else
44?
????????????{
45?
????????????????
this
.txtClassInfo.Text?
=
?
""
;
46?
????????????????
this
.txtClassInfo.Visibility?
=
?System.Windows.Visibility.Hidden;
47?
???????}
48?
??}
??? 使用了一个结构体Calculators ,这个结构体放置在我们的自定义类中,它有几个int属性用来保存分析源文件获取的所有信息。?info.PerFormCalculate(); 给出分析的结果。这里使用的所有获取的信息来更新了UIElements。
第三步:创建获取源文件信息的类
??? 虽然代码存在一些复杂性,但是这个类其实很简单。我很感谢CS Parser [^],它帮助我自动地解析源代码。???
??? 这个类需要一个IWpfTextView对象,它代表着Visual Studio文本编辑器。实际上WpfTextView实现了IWpfTextView。在执行期间这个类接受这个对象。我可以从WPFTextView.TextSnapshot.GetText()获得到了源代码。??? 在我调用的这个分析的时候,我只需要检测的代码是什么语言写的。开始我想自己来实现,但是感谢上帝,我在WPFTextView中发现已经存在这个对象了。
?1?
public
?
enum
?Language
?2?
{
?3?
????????CSharp,?VisualBasic,?Indeterminate
?4?
}
?5?
internal
?Language?DetectLanguage
?6?
{
?7?
????????????
get
?8?
????????????{
?9?
????????????????
string
?langtype?
=
?
10?
????????
this
._view.FormattedLineSource.TextAndAdornmentSequencer.
11?
????????SourceBuffer.ContentType.DisplayName;
12?
????????????????
if
(langtype.Equals(
"
CSHARP
"
,?
13?
????????????StringComparison.InvariantCultureIgnoreCase))
14?
????????????????????
return
?Language.CSharp;
15?
????????????????
else
?
if
(langtype.Equals(
"
BASIC
"
,?
16?
??????????????????????????????StringComparison.InvariantCultureIgnoreCase))
17?
????????????????????
return
?Language.VisualBasic;
18?
????????????????
else
19?
????????????????????
return
?Language.Indeterminate;
20?
????????????}
21?
}
???? DetectLanguage妥善地利用WPFTextView对象的FormattedLineSource.TextAndAdornmentSequencer.SourceBuffer.ContentType.DisplayName,这个属性告诉我是使用了哪种语言。之后我创建了一个新的方法PerFormCalculate,用它来解析源代码,它返回一个Calculation结构对象。
第四步:创建 Adornment Factory 类
??? 回到这个扩展,我创建一个Adornment(InfoBoxAdornmentFactory)的Factory类。这个类继承IWpfTextViewCreationListener,用来监听WPF的编辑和创建事件。
?1?
[Export(
typeof
(IWpfTextViewCreationListener))]
?2?
[ContentType(
"
text
"
)]
?3?
[TextViewRole(PredefinedTextViewRoles.Document)]?
?4?
internal
?
sealed
?
class
?InfoBoxAdornmentFactory?:?IWpfTextViewCreationListener
?5?
{
?6?
????????[Export(
typeof
(AdornmentLayerDefinition))]
?7?
????????[Name(
"
AlwaysVisibleInfoBox
"
)]
?8?
????????[Order(After?
=
?www.sychzs.cnion)]
?9?
????????[TextViewRole(PredefinedTextViewRoles.Interactive)]
10?
????????
public
?AdornmentLayerDefinition?editorAdornmentLayer?
=
?
null
;
11?
????????
public
?
void
?TextViewCreated(IWpfTextView?textView)
12?
????????{
13?
????????????
new
?AlwaysVisibleInfoBox(textView);
14?
????????}
15?
?}?
??? 这里,你可以看到我在这个类上使用了很多Attributes,像ContentType,它定义了我们只处理文本格式的编辑器;还有TextViewRole,它定义了将被这个类处理的textview的类型。
??? 在这个类中,我创建了一个AdornmentLayerDefination对象。可能你想知道我们没有使用它,无什么还需要定义它呢,它只是用来配置属性的。Order属性指定,当,InfoBox在层被选之后监听,Name是编辑扩展的名字。
第五步:创建Adornment 类
????Adornment类实际创建了一个WPF用户控件对象,并设置它的视图画布。在内部构造函数中,我处理IWpfTextView.LayoutChanged事件,当代码修改或者布局改变的时候,就触发这个事件。因此,通过这一事件,当我们编辑的文档时,我们可以很容易地得到回调。当浏览器编辑器的大小改变时,我还通过处理WPFTextView.ViewportHeightChanged,WPFTextView.ViewportWidthChanged得到回调,使我们可以重新定位相应的UserControl。
?1?
public
?AlwaysVisibleInfoBox(IWpfTextView?view)
?2?
{
?3?
??????????_view.LayoutChanged?
+=
?
this
.OnLayoutChanged;
?4?
??????????
this
.GetLayer();
?5?
}
?6?
private
?
void
?GetLayer()
?7?
?{
?8?
????????????_adornmentLayer?
=
?
this
._view.GetAdornmentLayer(
"
AlwaysVisibleInfoBox
"
);
?9?
????????????_view.ViewportHeightChanged?
+=
?
delegate
?{?
this
.onSizeChange();?};
10?
????????????_view.ViewportWidthChanged?
+=
?
delegate
?{?
this
.onSizeChange();?};
11?
}
12?
?
private
?
void
?OnLayoutChanged(
object
?sender,?TextViewLayoutChangedEventArgs?e)
13?
{
14?
????????????
this
._info?
=
?
new
?CodeInfoTracker(_view);
15?
????????????
this
.infobox.UpdateInfo(
this
._info);
16?
?}
17?
?
public
?
void
?onSizeChange()
18?
?{
19?
?????
20?
????????????_adornmentLayer.RemoveAllAdornments();
21?
????????????Canvas.SetLeft(infobox,?_view.ViewportRight?
-
?
255
);
22?
????????????Canvas.SetTop(infobox,?_view.ViewportTop?
+
?
10
);
23?
????????????
24?
??????????_adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative,?
25?
??????????
null
,?
null
,?
26?
??????????infobox,?
null
);
27?
}
?? 因此,构造函数只是调用GetLayer来获取的Layer对象,发生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。当一个布局改变时,我就能更新这个用户的控件。
??? 至此,我们成功地建立我们的扩展。你可以使用F5运行它,它会打开一个Visual Studio的Experimental实例。
安装和卸载这个扩展:??? 安装和卸载这个扩展是非常容易的。当您编译项目后,它会产生一个VSIX文件。您可以只需双击这个文件,它会自动安装到Visual Studio。???
??? 要卸载的文件,您打开Visual Studio,转到 Tools - > Extension Manager,然后选择卸载该扩展。
发布您的扩展:
??? 发布你的扩展到Visual Studio库的方式也非常的酷。只要你需要上传VSIX文件到http://www.sychzs.cn/。我已经上载我的这个扩展。
总结:这篇文章,从头到尾一步一步教你实现一个很简单很酷的VS2010的扩展
原文:Code InfoBox Visual Studio Extension (VSX) 2010
参考:
Building and publishing an extension for Visual Studio 2010 [^]
Official Extension Site [^]
代码:Zip
(全文完)
以下为广告部分
您部署的HTTPS网站安全吗?
如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 www.sychzs.cn 检测以下吧。让您的HTTPS网站变得更安全!
SSL检测评估
快速了解HTTPS网站安全情况。
安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。
SSL证书工具
安装部署SSL证书变得更方便。
SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。
SSL漏洞检测
让服务器远离SSL证书漏洞侵扰
TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。