VS 2003 IDE插件开发指南

office插件编程 关于office插件编程的资料,如果初次接触编写office插件,正好可以指导和参考一下。适用于VC/ATL。 立即下载

Visual Studio.NET插件能做很多事情,例如:
1、   编写如CodeRush一样的开发环境代码辅助工具
2、   编写如CodeSmith这样的代码模板工具
3、   编写代码生成器,根据自定义的一些条件自动生成代码。如现在比较流行的一些代码生成工具,如果和开发环境集成,使用起来应该会更加方便。
4、   编写如DataSetPryer这样的调试工具,可以在调试时查看DataSet的内容。
5、   甚至还可以在VS.NET里集成Google搜索引擎,或将MSN集成到VS.NET。
这里不再一一列举,总而言之,凡是可以和Visual Studio.NET开发环境相关的,都能以插件的形式进行。
开发VS.NET插件,目前有两种形式:一是利用VS向导生成的VS外接程序;二是利用微软的VSIP开发包(Visual Studio Industry Partner:微软合作伙伴计划)。本文讨论的是第一种方法。

 二、             程序框架概述
在Visual Studio.NET中选择”新建项目à其他项目à扩展性项目àVisual Studio.NET外接程序”,按照向导生成代码,最后会生成两个工程文件,一个是外接程序项目,一个是外接程序安装项目。可以在外接程序项目里看到生成的项目文件中有个connect.cs文件,该文件有以下几个部分:


1、   类的继承接口及其常量定义

[GuidAttribute("952A6CFF-8516-4DA0-B0BA-519CB9614525"), ProgId("STDTools.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2, IDTCommandTarget
{…}

Connect类主要从两个接口继承,一个是Extensibility.IDTExtensibility2接口,该接口主要定义了下面几个方法:
OnAddInsUpdate 方法:在环境中加载或卸载外接程序时发生。
OnBeginShutdown 方法:正在关闭环境时发生。
OnConnection 方法:将外接程序加载到环境中时发生。
OnDisconnection 方法:当从环境中卸载外接程序时发生。
OnStartupComplete 方法:环境启动完毕时发生。

IDTCommandTarget接口则定义了以下两个方法
Exec 方法:在VS开发环境中选择了某个外接菜单命令时被VS环境所调用。
QueryStatus方法:当VS环境要显示外接菜单时调用该方法查询菜单的状态。
该方法返回指定的已命名命令的当前状态,无论此命令是启用、禁用还是隐藏

2、   OnConnection()函数:
本事件处理函数是在插件被加载时发生,一般用于做一些初始化工作,如创建菜单等。该函数的传入参数如下:
object application:定义了IDE自动化对象
Extensibility.ext_ConnectMode connectMode:连接模式,指明了插件当前的连接模式
ext_cm_AfterStartup 外接程序是在应用程序启动后加载的,或是通过将相应 AddIn 对象的 Connect 属性设置为 True 加载的。
ext_cm_Startup 外接程序是在启动时加载的。
ext_cm_UISetup 外接程序自安装后首次被启动。

3、   OnDisconnection()函数:系统卸载插件时被调用
本事件处理函数是在插件被卸载时发生,其传入参数如下
Extensibility.ext_DisconnectMode disconnectMode:
ext_dm_HostShutdown:外接程序是在开发环境关闭时卸载的。
ext_dm_UserClosed:外接程序是在用户清除“外接程序管理器”对话框中该外接程序的复选框时卸载的
ext_dm_UISetupComplete:外接程序是在环境安装完成后和在 OnConnection 方法返回后卸载的。

4、   QueryStatus()函数:
系统查询菜单状态

5、   Exec()函数:
在VS开发环境中选择了某个外接菜单命令时被VS环境所调用,在这里可以编写自己的响应代码,例如运行自己的程序或弹出某个窗口。

三、             处理菜单
在OnConnect方法中可以进行一系列初始化工作,其中之一就是生成菜单


1、   添加菜单条菜单和工具条菜单


applicationObject = (_DTE)application;
addInInstance = (AddIn)addInInst;
if
(connectMode == Extensibility.ext_ConnectMode.ext_cm_UISetup
|| connectMode == Extensibility.ext_ConnectMode.ext_cm_Startup)
{//    如果是安装状态或是插件刚被启动的状态,则创建菜单

object []contextGUIDS = new object[] { };

 

//获取IDE环境的Command集合和CommandBar集合 Commands commands = applicationObject.Commands;
_CommandBars commandBars = applicationObject.CommandBars;

try
{
//菜单条对象和工具条对象都是CommandBar类型

CommandBar menuObj,toolbarObj;
//生成新的子菜单对象,将会被插入到菜单条和工具条对象上

Command commandObj = commands.AddNamedCommand(addInInstance,
 "PublishUserManage",
 "添加用户管理代码
",
"添加用户管理的代码
",
true
,
127,
ref
contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled
);
#region

这里有几点要说明:

     1、菜单图片:
以上的参数中的true,bool MSOButton参数为true,意味着该菜单命令的图片是来源于Office资源库,则后面的int Bitmap(位图ID号)则指明了是哪个图片。如何知道哪个ID号对应哪个图片?可以从微软的页面上下载一个用VBA写的工具,该工具列举出了所有的图片资源(附录工具中已经包含FaceID.xls)。
以上的参数中的true(bool MSOButton),意味着该菜单命令的图片是来源于Office资源库,则后面的127(int Bitmap--位图ID号)则指明了是哪个图片。如何知道哪个ID号对应哪个图片?可以从微软的页面上下载一个用VBA写的工具,该工具列举出了所有的图片资源(附录工具中已经包含FaceID.xls)。
如果不想用Microsoft Office自带的图片资源,则需要先在自己的解决方案中添加一个MFC DLL的工程,然后在其中加入图片资源;然后将MSOButton设为False,将Bitmap位图ID设为该资源文件中图片资源的ID号,然后还要在安装程序里添加一个文件夹,同时添加注册表项。具体过程就不再多说了,可以看参考资料
2、菜单项的名称
函数的第二项参数string Name(本例中是”PublishUserManage”),系统在生成菜单对象时会自动在Name前面添加本插件的ProgID代表的字符串作为菜单对象的全名。后面在根据名称检索该菜单对象时,需要用全名,本例中应该是”STDTools.Connect.PublishUserManage”
;
*/
#endregion

//添加主菜单

CommandBarButton buttonObj;
//创建主菜单项和工具条

menuObj = (CommandBar) applicationObject.Commands.AddCommandBar("代码生成
(&C)" ,
  vsCommandBarType.vsCommandBarTypeMenu,
  applicationObject.CommandBars["MenuBar"],10);
toolbarObj = (CommandBar) applicationObject.Commands.AddCommandBar(
                "CodeTools(&C)",
vsCommandBarType.vsCommandBarTypeToolbar,
null
,
-1);
toolbarObj.Position = Microsoft.Office.Core.MsoBarPosition.msoBarTop;
//增加子菜单

//将子菜单加入主菜单和工具条
buttonObj = (CommandBarButton) commandObj.AddControl(menuObj, menuObj.Controls.Count + 1);
buttonObj = (CommandBarButton) commandObj.AddControl(toolbarObj, toolbarObj.Controls.Count + 1);
buttonObj.Style = MsoButtonStyle.msoButtonIcon;
//将子菜单加入Project的右键菜单

CommandBar projBar = this.applicationObject.CommandBars["Project"];
commandObj.AddControl(projBar,1);
}
catch
(System.Exception ex)
{
string
error = ex.Message;
}

2、   添加右键弹出快捷菜单

除了上面在VS开发环境中添加常规菜单外,还允许用户为开发环境添加一些右键弹出菜单项。下面代码是为代码编辑窗口添加右键弹出菜单。
            //检索代码编辑窗口右键弹出菜单的工具条
CommandBar projBar = this.applicationObject.CommandBars["Code Window"];
//将自己的菜单项加入工具条
            commandObj.AddControl(projBar,1);
如果想在鼠标右键点击“解决方案资源管理器”中的某项目结点时弹出的菜单条中添加自己的菜单项,则只需把上面的"Code Window"改成"Project"即可。如何知道是"Code Window"或"Project"这个没有什么资料说明,但是也很简单,只要编写一个插件程序,列举出所有的菜单条对象就行了。幸好笔者已经做了这件事情,把所有的菜单条对象的名称都列在附录的CommandBar_Names.txt文件里了,你所要做的就是根据名称去猜哪个是你所需要的菜单条了。


3、   卸载菜单


为什么需要卸载菜单?
因为如果在你的插件中没有处理卸载菜单,则用户通过“工具à外接程序管理器”暂时关闭了你的插件,或者是通过添加/删除程序卸载了你的插件时,菜单项依然存在,但是却已经不能执行命令,这是不合理的。
卸载菜单是在OnDisconnection方法中实现的,具体可参见下载资源里的STDTool里的Connect.cs文件中的OnDisconnection方法。在该方法中的代码比较简单,先判断是不是VS环境正在关闭或用户通过外接程序暂停了插件,然后查找到子菜单项并删除,再查找到主菜单项和工具条项,从系统菜单集合里移除掉这些命令条对象。


4、   确定菜单状态


菜单显示时有一项比较重要的工作,就是根据应用环境的不同,菜单对象的显示状态也在不断变化。也即可用,禁用,不显示。每当VS集成环境要显示一个插件的菜单时,它会调用QueryStatus()方法查询该菜单应该显示的状态。具体代码可参见下载资源里的STDTool里的Connect.cs文件中的QueryStatus方法,该方法先预设菜单项状态为受支持状态(vsCommandStatusSupported,如果不受支持,则菜单不会显示),然后判断条件满足的情况下添加菜单为可用状态(vsCommandStatusEnabled),如果不满足条件,则菜单为禁用状态。


5、   执行菜单命令


当用户选择插件的菜单项时,集成环境会调用Exec()方法,具体代码可参见下载资源里的STDTool里的Connect.cs文件中的Exec方法,该方法查询被执行的菜单的名称是本插件所期望的名称,则执行一段代码,如显示窗口等。执行成功,则设置handled为true,告诉集成环境已经成功执行命令。


四、             使用窗口


1、   使用WinForm窗口

在VS.NET中显示WinForm窗口非常容易,和平常编写WinForm程序没什么两样,步骤如下:
l          在项目里添加一个WinForm窗体
l          修改WinForm窗体的构造函数
将VS环境的根对象DTE对象传入,以便在WinForm中可以操纵开发环境
          public class MyForm : System.Windows.Forms.Form
          {       
private EnvDTE.DTE applicationObject;

         public MyForm(EnvDTE.DTE applicationObject)
         {
              InitializeComponent();
              this.applicationObject = applicationObject;
              …

          }


l          在Connect文件的Exec函数里生成并显示WinForm窗体。
              MyForm form = new MyForm(this.applicationObject.DTE);
              form.ShowDialog();
注意:这里的this.applicationObject是_DTE接口指针,它的一个成员DTE成员才是DTE对象,不能直接用类型转换如(DTE) this.applicationObject

2、   使用工具窗口


VS.NET的工具窗口指的是类似“解决方案资源管理器”,“类视图”,“工具箱”这样停靠在上下左右侧边的窗口。而如代码编辑窗口这样的窗口,需要用VSIP进行开发,外接程序插件是没有办法开发这类窗口的。
根据MSDN里的资料,如果要开发侧边工具窗口,是件非常繁琐的事情。因为VS.NET是基于COM开发的,所以开发出来的侧边工具窗口也需要实现一系列接口,也就是说,不能直接使用.NET程序集。幸而已经有人做了这件事情
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vstchFAQAboutVSNETAutomation.asp),
开发了一个将.NET用户控件包装成COM组件的容器VSUserControlHostLib,使得我们只需要开发出.NET用户控件,就可以将其嵌入到VS集成环境里了
开发步骤:
1、   生成Addin项目
2、   在项目中添加VSUserControlHost.dll引用
3、   在Connect.cs文件的OnConnection方法中添加显示窗口的代码
下面是代码示例:(添加在OnConnect方法中)
//GUID串可以用VS开发环境里菜单命令“工具à创建GUID”弹出的对话框创建
         string guidstr = "{65FADCBF-63D2-448b-8A4B-393D7E751345}";
         object objTemp = null;
         VSUserControlHostLib.IVSUserControlHostCtl objControl = null;
         //这里先生成容器窗口,返回的控件对象在objTemp里
         windowExplorer = applicationObject.Windows.CreateToolWindow(
addInInstance,
"VSUserControlHost.VSUserControlHostCtl",
"菜单浏览器",
guidstr,
ref objTemp);
         //使用容器窗口时,必须在调用该容器控件前设置其为可见,否者将会不能正常显示
         windowExplorer.Visible = true;
         windowExplorer.IsFloating = false;
         //将返回的工具窗口转换为容器对象
         objControl = (VSUserControlHostLib.IVSUserControlHostCtl)objTemp;
         System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
         //用容器对象包含用户控件,
         menuExplorer = (MenuExplore)objControl.HostUserControl(asm.Location,
"MenuBrowser.MenuExplore");
         //设置窗口的图标
//windowExplorer.SetTabPicture(…)
              //将DTE对象赋给窗口
menuExplorer.Application = applicationObject;

说明:
l          生成工具窗口:
以上代码先用CreateToolWindow函数生成工具窗口,工具窗口里承载的VSUserControlHost.VSUserControlHostCtl类型控件由objTemp对象返回
l          设置可见性:
将工具窗口设置为可见,非浮动
l          获取IVSUserControlHostCtl接口:
将返回的工具窗口中承载的控件对象objTemp转换为IVSUserControlHostCtl接口类型,并赋给objControl对象
l          加载用户控件:
用objControl的HostUserControl方法加载指定程序集的指定用户控件对象,上面代码中因为MenuBrowser.MenuExplore类是在插件项目的程序集里,所以用System.Reflection.Assembly.GetExecutingAssembly()方法获取当前程序集位置。如果用户控件是在其他程序集里,需要根据实际情况指定程序集位置

4、   最后还应该在OnDisconnection方法里关闭窗口
if(windowExplorer!= null)
{
     windowExplorer.Visible = false;
}

五、             操纵VS开发环境


VS.NET自动化模型涉及的面太广,本文只针对一些专题加以说明。
1、   利用代码模型浏览代码
l          获取代码模型对象
//获取当前正活动的文档
     Document activeDocument = applicationObject.ActiveDocument;
//获取代码模型对象,
//请自行判断activeDocument,ProjectItem,FileCodeModel以及CodeElements是否不为空
CodeElements codeElements = activeDocument.ProjectItem.FileCodeModel.CodeElements;
//检索代码元素
     foreach(CodeElement ce in codeElements)
     {
         result.AddRange(getCodeElements(ce));
     }

说明:
上面的代码先从DTE对象(也即VS自动模型的根对象)获得当前正活动的文档对象
然后再根据文档对象获取和它关联的项目元素,这里的ProjectItem其实就是在解决方案资源管理器下面的项目文件夹对应的子项。可以是各种类型,如文件,文件夹等
再从项目元素获得关联的文件代码模型
根据文件代码模型获取其代码元素的集合CodeElementCollection,代码元素的父类为CodeElement,下面派生出许多的子类,代表具体的代码元素,分别有:
CodeNamespace、CodeClass、CodeInterface、CodeFunction
CodeProperty、CodeVariable、CodeDelegate、CodeStruct、CodeEnum
代表着命名空间、类、接口、函数、属性、变量、委托、结构、枚举等类型的代码元素,某个CodeElement具体是何类型,可以根据CodeElement. vsCMElement枚举类型来判断,然后再显式转换成具体的子类即可
但是更进一步的代码元素,如函数体内的语句,好像还没有看到有方法检索。不过也可以利用一些其它的方法,比如CodeRush的程序集里面提供了一个StructuralParser程序集,用于C#的代码分析。如果谁有兴趣可以研究研究

l          根据具体类型检索代码元素
具体可参见下载资源包里的MenuBrowser的getCodeElements方法,这里不多作解释
2、   操纵解决方案及其项目文档
l          获取当前被选中的项目
下面代码演示了鼠标点击一个项目,或项目中的子项时,如何得到该项目对象
public Project GetSelectedProject()
{
     Project project = null;
     //从被选中对象中获取工程对象
     EnvDTE.SelectedItem item = Application.SelectedItems.Item(1);
     if(item.Project != null)
     {//被选中的就是项目本生
         project = item.Project;
     }
     else
     {//被选中的是项目下的子项
         project = item.ProjectItem.ProjectItems.ContainingProject;
     }
     return project;
}
l          获取当前项目的所在目录
private string GetSelectedProjectPath()
{
         string path = "";
     //获取被选中的工程
         Project project = GetSelectedProject();
         if(project != null)
         {
         //全名包括*.csproj这样的文件命
                   path = project.FullName;
         }
     //去掉工程的文件名
         path = Path.GetDirectoryName(path);
         return path;
}
l          将文件加入工程中
//获取被选中的工程
Project project = this.GetSelectedProject();
//将文件夹下的文件加入工程
project.ProjectItems.AddFromDirectory(sdir);
//将单个文件加入工程
project.ProjectItems.AddFromFile(nfile);

l          向项目中加入程序集引用
using VSLangProj;
private void AddReference(string assembly)
{
         Project project = GetSelectedProject();
         VSProject vsproject = null;
         if (project.Kind == PrjKind.prjKindCSharpProject)
         {
         //工程类型为C#工程,将project的Object成员转换为VSProject对象
                   vsproject = project.Object as VSProject;
         }
         if(vsproject != null)
         {
          //获取C#工程的引用集
                   VSLangProj.References refers = vsproject.References;
                   if(refers != null)
                   {
              //将程序集引用添加到工程中
                            refers.Add(assembly);
                   }
         }
}
3、   在代码编辑窗口操纵代码
这里不再详述,只是列出网上的资源,大家可以自行参考

六、             参考资料
http://www.knowdotnet.com/add-insmacros.html
msdn帮助目录:Visual Studio .NET-->使用 Visual Studio .NET 进行开发-->参考-->自动化与扩展性参考-->公共环境对象模型

七、             下载包说明:
CodeNavigator    :演示了如何通过代码模型浏览代码
GuidGen             :演示了WinForm窗口在VS.NET集成环境中的应用
MenuBrowser     :演示了工具窗口的应用以及例举菜单对象的名称
RegionsAddIn     :用于添加#Region标签,演示了如何操纵代码编辑窗口
STDTools           :演示了如何向工程里添加文件,以及程序集引用,以及在工程项目的右键菜单上添加自己的菜单项

vs2003插件 包含不少vs2003插件的源代码,有MenuBrowser,STDTools 立即下载

相关推荐

VS Helper(VS插件2003版)

非常难找的工具VS中除VA外另外一个很受欢迎的工具VS 2003版。

wps2005插件开发之旅

WPS2005插件开发二:如何屏蔽WPS菜单栏的功能添加自己的功能? Word在安装的时候都自带了VBA环境可以将一些自定义的功能代码写在模板中方便的进行控制,但是由于宏代码执行存在一定的安全性问题,不同的客户端设置也不一样这样给宏代码执行可能带来一些影响,所以比较好的方法就是使用插件控制。WPS在安装的时候默认没有带VBA环境,所以写在模板或文件中的宏代码在没有VBA环境的机器上是不

MVC2008MVC的专栏 7295

VS 2003 Helper(VS插件

非常难找的工具VS中除VA外另外一个很受欢迎的工具VS 2003版。

C++开发Office插件:实现Word插件

简介本文以Word插件为例,介绍如何使用C++实现一个完整的Office插件。简单来说Office插件就是一个实现了IDTExtensibility2和IRibbonExtensibility两个接口的COM组件。IDTExtensibility2提供了Office插件接口,IRibbonExtensibility提供了Ribbon界面接口。下面详细介绍实现步骤。本例的开发环境为:Win8 + VS

Cynhard的专栏 2万+

Visual Studio 2008 可扩展性开发(三):Add-In运行机制解析(下)

前言 在上篇Add-In运行机制解析(上)中,我分析了Add-In向导生成的代码,从中我们知道只要创建一个类库,它包含实现了IDTExtensibility2接口的类,然后为其建立.addin配置文件,就可以实现一个Add-In了。本文将更进一步,介绍Add-In的事件和生命周期,为今后的开发打下基础。 Add-In的事件 Add-In是事件驱动的,可以猜到的事件有加载、卸载、状态改变等...

weixin_34111819的博客 241

创建属于自己的OneNote插件

OneNote是一款很受欢迎的笔记软件,其分章节的结构特点非常适合记录课堂笔记,读书笔记和知识体系,但与Office其他明星产品相比,OneNote的资历更短,功能也不及Word、Excel强大,还好我们可以通过AddIn来扩展OneNote的功能。 发现国内OneNote插件开发的资料基本没有,好不容易找到两篇也是针对2010版的开发,在此附上链接: http://www.malt...

dijianggou0335的博客 876

VS.Net 2003 IDE 插件开发指南

VS 2003 IDE插件开发指南 作者 sema 2005-04-15 10:03 Visual Studio.NET插件能做很多事情,例如:1、 编写如CodeRush一样的开发环境代码辅助工具2、 编写如CodeSmith这样的代码模板工具3、 编写代码生成器,根据自定义的一些条件自动生成代码。如现在比较流行...

weixin_30241919的博客 197

VS.Net 2003 IDE 插件开发指南(转贴)

作者 sema    2005-04-15 10:03 Visual Studio.NET插件能做很多事情,例如:1、   编写如CodeRush一样的开发环境代码辅助工具2

qdzx2008的专栏 3395

VS.NET 2003集成环境插件开发指南(三)----操纵VS开发环境(完结篇)

一、             操纵VS开发环境 VS.NET自动化模型涉及的面太广,本文只针对一些专题加以说明。 1、   利用代码模型浏览代码 l          获取代码模型对象 //获取当前正活动的文档      Document activeDocument = applicationObject.ActiveDocument;      if(act

技术资料收集站 654

【转贴】VS.NET 2003集成环境插件开发指南

VS.NET 2003集成环境插件开发指南 转载请注明出处:http://www.cnblogs.com/dragon 一、             简介――Visual Studio.NET插件能做什么? Visual Studio.NET插件能做很多事情,例如: 1、   编写如CodeRush一样的开发环境代码辅助工具 2、   编写如CodeSmith这样的代码模板

烟雨阁 672

NUnit 在VS.NET 2003上的插件.

NUnit 在VS.NET 2003上的插件. VSNUnit2k3是Sourceforge上的一个开源软件,通过这个插件,能使我们VS.NET的IDE中直接使用单元测试工具,,不用去来回的切换了哦~:P使用说明:先装上原版,再把压缩包中的VSNUnit2k3.dll覆盖到原版的位置..重启VS.NET IDE就OK了...Good luck..说明:     1.原始版本打开这个

shanyou的专栏 1742

VS.NET 2003集成环境插件开发指南

VS.NET 2003集成环境插件开发指南 转载请注明出处:http://www.cnblogs.com/dragon 一、             简介――Visual Studio.NET插件能做什么? Visual Studio.NET插件能做很多事情,

wsxqaz的专栏 733

收集大家常用的VS.Net IDE Addins工具

FROM :http://test.xiaozhu.com/CS/blogs/play/archive/2005/01/24/8417.aspx 我常用的 几个 VS.Net IDE Addins 工具 草稿,待改,待补图 我常用的几个 IDE 插件列表如下(详细功能介绍见各自公司网站): Visual Assist (Whole Tomato) Code...

weixin_30508309的博客 261

vs2003+VAssistX插件快捷键失效

vs2003+VAssistX插件快捷键失效: 解决办法:                  找VA里面有个设置-->clear就好了...

ghevinn欢迎您光临 3719

使用插件功能扩展VB ::来自applevb

使用插件功能扩展VB ::来自applevb 一、插件介绍   从结构上来看,一个VB插件实际上是一个COM组件,原则上组件可以使用支持COM的开发工具,例如Delphi、VC来编写。组件通过实现COM中的IDTExtensibility对象来建立与VB的连接。组件注册以后,当VB运行中在Add-In菜单中装载组件后,VB就会调用组件中IDTE...

麦壳饼 292

《北塔教你做插件 从RibbonX开始》第三讲:再建Ribbon——ATL的实现方法

前言: 本文将介绍如何使用ATL标准模板库实现Office 插件开发工作,重点内容在Addin插件连接以及Ribbon菜单载入。 PS:本章示例的实现环境为VS2010。 目录: 实现MSOffice_Addin插件基础用ATL创建WordAddin插件WordAddin插件定义Ribbon菜单 第一节、实现MSOffice_Addin插件

北塔 5142
上一篇: sql server 2008 常见安装错误解决方法
下一篇: Microsoft 微软101个LINQ查询示例
迷途笛音
博客等级 码龄18年 27粉丝 15原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值