Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Create a Vista Gadget Using Visual Studio IDE (updated)

4.84/5 (46 votes)
8 Feb 2011CPOL13 min read 270.9K   19.5K  
This article describes how to use Visual Studio for developing a Vista Gadget.
gadgettoolbarandmenu.png

gadgetmenu.png

Introduction

The absence of tools in Visual Studio that can help developers to create Vista gadgets is strange and disappointing, in my opinion. I hope it's a temporary state, but now, I want to show you some tools that can help you to develop Vista gadgets using only Visual Studio 2008 or 2010 IDE. These tools include Visual Studio template for creating Vista gadgets and Visual Studio add-in for creating a .gadget file from a project and run a gadget installation.

Background

By now, if we want to create a Vista gadget, we should do the following steps:

oldprocess.png

  1. Create all needed folders and important files in some folder.
  2. Create a zip archive within all folders and files that should be included in the gadget.
  3. Change the extension from .zip to .gadget for the archived files.
  4. Run this file by double clicking for starting the process of gadget installation.

All these actions could be executed from the Windows Explorer. If you will create a gadget for a company whose inner policy will require that all assemblies and executed files have to be signed, you will be engaged into using cabarc.exe and signtool.exe for signing your gadget. It’s a really boring task to create a signed gadget without any automation.

So, how can we automate all these steps using Visual Studio IDE?

newprocess.png

You can find out the answer here and it's the add-in that was created for helping in the development of Vista gadget. With this add-in, you can easily build signed and unsigned gadget using only one click on menu item or toolbar button or using shortcuts (Ctrl+R, Ctrl+R this combination can be changed). So, how to install it? For this issue, I've prepared some installation pack. Below, I describe how to install all this stuff.

Installation

In the installation pack, I have prepared:

  1. AddinDeployment.vsi - Visual Studio add-in installation file for Visual Studio 2008
  2. AddinDeployment2010.vsi - Visual Studio add-in installation file Visual Studio 2010
  3. CSharpHelloVistaGadgetTemplateDeployment.vsi and VBHelloVistaGadgetTemplateDeployment.vsi files – Sample Visual Studio gadget templates for C# and VB.NET. Really, they don’t depend on which language you will install a template, because a gadget requires only JavaScript and VBScript as programming languages. So, here there is only one difference – for which language you will use template, no more.
  4. cabarc.exe and signtool.exe – Additional program that will require add-in for running. You can set path for existing applications if they have already been installed on your computer. Later, I will explain how. So, if you have already installed these applications, you can delete each one from your computer.

So, when you have already installed add-in and some templates, you should define some important options for your future gadget development. For this issue, you should open add-in settings window and define some parameters.

Choose from menu Gadget -> Open gadget properties window or choose the corresponding appropriate button from the toolbar.

opengadgetproperties.png

Then you should see the next window.

GadgetPropertiesWindow2.PNG

In this window, you should define:

  1. Output Vista Gadget Path – a path where add-in will save your gadget after it has been created.
  2. Cabarc.exe path – cabarc.exe is an application which will create your gadget file. So, it’s extremely important to define here the right path to this application. The official page where you can find this utility is: http://support.microsoft.com/kb/310618. Moreover I already prepared this utility for you in this installation pack. So, you can choose a path where you will place an installation for this article.
  3. Allowed file extensions - this is a collection of file extensions that define types of files which you wish to place into your gadget.
    If you are going to sign your gadget, you should:
    1. Mark checkbox “It will build signed gadget”
    2. Define core signtool.exe utility path for this action. You can find more about this utility at http://msdn.microsoft.com/en-us/library/8s9b9yaz.aspx
    3. If you have ready to use .pfx file (personal information exchange file), define path to it.
    4. If you haven’t .pfx file, but you have .pvk and one from .spc or .cer files, you can make new .pfx file using pvk2pfk.exe utility. You can find more about this utility at http://msdn.microsoft.com/en-us/library/ff550672.aspx
    5. Define also password for your .pfx file.

After you have completed entering all the needed information, click button "Save" for saving these options.

Also, I want to notice that it is extremely important here that your project was placed on the same logical disk as cabarc.exe and signtool.exe. This is a restriction for Microsoft console applications that was mentioned above. So, you should be careful and place these utilities strictly on the same logical disk as for the project that you are working on.

Congratulations! Now, you are ready to use addin from your Visual Studio 2008 IDE.

Using Add-In And Templates

When you have completed the installation process, you are ready for creating your own gadget with Visual Studio IDE. In this case, you should open menu item: File -> Open -> Web site.
After this, you can find new open window where you can choose HelloWorldVistaGadget template.

gadgettemplate.png

When you click on this template, Visual Studio opens a new web site whose structure would resemble real gadget project structure as you can see in the picture.

gadgetproject.png

Here, you can find only one foreign element - it's a web.config file. But if you are going to build a gadget using RunVistaGadgetAddIn, it is not an obstacle, because add-in will not include this file to output .gadget file.

Here, I will not tell you about how to create a gadget. You can find more sources with good explanation of this process here on CodeProject or read great book about this issue.

I just noticed that after creating your beautiful gadget in Visual Studio, you can just click on the button "Run gadget" or use shortcut Ctrl+R, Ctrl+R and you can see your gadget in the earlier place. Moreover, add-in will run gadget installation process and you should only click on "Install" button in the gadget installation dialog (you can see it in the picture) for observing your gadget on sidebar.

gadgetinstallation.jpg

By now, after clicking on "Run gadget" button, you always should see this window that suggests you to install gadget on the Windows sidebar. But I discovered some problem with this scenario when gadget has used settings option in its code. You could have had a problem with installing gadget on sidebar, in this case, after the first installation. Really it's not a problem, you should just repeat the installation process twice. I'm personally trying to find out the reason for such behavior, but could only reveal that the Windows Sidebar has held some gadget files opened and hadn't cleared resources after closing gadget on the sidebar. So, if you find out how to resolve this issue, let me know, please!

If you have felt that this add-in has not satisfied your needs, you can switch off this add-in. You should choose menu item Tools -> Add-in manager. And in the appeared window, remove a tick from this add-in. In this case, this add-in will not disturb you anymore.

Development

In this topic, I'm trying to explain how this add-in works. How to work the main part of add-in. How can you create your own template. And at the end of this topic, I describe how you can prepare installation for Visual Studio add-in and templates.

The main algorithm is not very intricate. I can show it using only some piece of code from add-in sources:

C#
if (isHaveLoadedProject())
{
         SaveAllChangedFiles();
         CreateGadget();
         if (isBuildSignGadget())
         {
                  SignGadget();
         }
                        
         RunGadget();
} 

First of all, I want to remind you that all actions in an add-in are commands. Exec method is called when some command was invoked. Exec method is a common handler for all commands. So, the piece of code mentioned above will be executed from Exec method too, but only for particular command (in this case RunGadget command). For running gadget, we should be asking one question - is some project already loaded in IDE (it would be better if it will have some gadget project as well). Then, we save all changed files in this project, afterwards add-in will create gadget file. Then it will check if it should sign gadget. If it should, then it will sign gadget. And at the end, the add-in tries to run gadget installation.

In my opinion, the most interesting methods here are CreateGadget() and SignGadget() as well. Both of these functions are used by external programs for executing themselves. Here I apply, may be not a very optimal, but still simple way for executing external program. Because calling an external program is typically used not only for these two methods in this add-in, I create a simple base class where I have implemented typical behavior for all classes that were used for calling an external program. Here you can see the class diagram:

apprunnerhierarchy.jpg

As you can see, only in this add-in, six different classes had been used for calling an external program. No, I really don't take pride in this fact. But why I should reinvent something if it already existed in our system? So, for me, it was an easy way when I've used an already existed application than create one by myself. The structure of this hierarchy includes a base abstract class ApplicationRunner. When you inherit some class from this one, you should override two main methods GetAppArgruments() and GetOutputAndRunApplication(). First one GetAppArguments method should return string with arguments as it would be called in console application (for example, for executing cmd.exe cd /? method mentioned above method should return only cd /? without *.exe file). The second one GetOutputAndRunApplication method will call base class with appropriate arguments.

For example, let's consider the next example. For this example, we want to open the sidebar settings window. This is the window where we can choose appropriate Vista gadget and install it on the sidebar. You can see this window in the picture below:

gadgetcontrol.jpg

For this purpose, we can call cmd command like: "C:\Program Files\Windows Sidebar\sidebar.exe /showgadgets". More about sidebar command can be found in this post. From C# code we can use the ApplicationRunner base class mentioned above for this purpose. So, we need to create a new class that should inherit from ApplicationRunner class and override two methods. In this addin, I've created class SidebarSettingsRunner. You can see the code for this class below:

C#
class SidebarControlConsoleRunner: ApplicationRunner
{
        public SidebarControlConsoleRunner(DTE2 applicationObject)
            : base(applicationObject, false){ }

        public SidebarControlConsoleRunner(DTE2 applicationObject, bool isRunAsWinApp)
            : base(applicationObject, isRunAsWinApp){ }

        public override string GetAppArguments()
        {
            String GadgetArgs = "  /showgadgets";
            return GadgetArgs;
        }

        public override string GetOutputAndRunApplication()
        {           
            base.CalledApplicationPath = "c:\\" +
Environment.SpecialFolder.ProgramFiles + Path.DirectorySeparatorChar +
"Windows Sidebar\\sidebar.exe";
           
            return base.GetOutputAndRunApplication();
        }    
 } 

As you can see here, for GetAppArguments method, we define that argument would be "/cpl". For GetOutputAndRunApplication method, we define application path for sidebar.exe file and return output string after the application has been run. Furthermore, we can use this class like in this code snippet:

C#
SidebarControlConsoleRunner sccr = 
	new SidebarControlConsoleRunner(applicationObject, true);
String AppOutput = sccr.GetOutputAndRunApplication(); 

where applicationObject is a global for this add-in object which you can define on OnConnection event handler for current add-in instance.

This future can be called from toolbar button or menu item "Open Vista Sidebar Control Console". So, in addition, I want to explain how we can add such possibility for our add in.

For this issue, we should add some code for OnStartupComplete add in instance's event handler. First of all, we should understand that in any add-in, we should program any action with command pattern. And for any action, we should define a particular Command object instance. Class Command describes some action for add in. In this case, we want to define action for opening a Vista Sidebar Control Console. So, we've created a new instance for inner Visual Studio Command class and then define for it some properties in its building method.

Then, we've defined command collections which we want to use. In this case, we define commandBars and menuCommandBar collections. Here commandBar is a collection of CommandBar objects that represent the command bars in the container application. CommandBar objects represent objects that can help us to get specified controls collection for Visual Studio IDE. In this case, GadgetTemporaryCommandBarPopup control collection which will specify new menu group "Gadget" in standard Visual Studio IDE menu. With defined above command for our action (OpenVistaSidebarControlConsoleCommand), we can add new menu item to "Gadget" group menu. Below, you can see the entire code snippet for adding new toolbar, toolbar's button, menu group and menu item using C# code.

C#
 public void OnStartupComplete(ref Array custom)
{
        Command OpenVistaSidebarControlConsoleCommand = null;
        CommandBar menuCommandBar;
        CommandBar GadgetTemporaryToolbar;
        CommandBars commandBars;
        CommandBarButton OpenVistaSidebarControlConsoleCommandBarButton;
        CommandBarControl GadgetToolsCommandBarControl;
        CommandBarPopup GadgetTemporaryCommandBarPopup;        

        try
        {           
             OpenVistaSidebarControlConsoleCommand =
		applicationObject.Commands.Item(addInInstance.ProgID + "." +
		OPEN_VISTA_SIDEBAR_CONTROL_CONSOLE_COMMAND_NAME, 3);
        }
        catch
        {

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

        // Add the command if it does not exist
        if (OpenVistaSidebarControlConsoleCommand == null)
        {               
            OpenVistaSidebarControlConsoleCommand =
		applicationObject.Commands.AddNamedCommand(addInInstance,
		OPEN_VISTA_SIDEBAR_CONTROL_CONSOLE_COMMAND_NAME, "Open Vista Sidebar
		Control Console", "Open Vista Sidebar Control Console", true, 548, ref
		contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported +
		(int)vsCommandStatus.vsCommandStatusEnabled);
        }
        commandBars = (CommandBars)applicationObject.CommandBars;
        menuCommandBar = commandBars["MenuBar"];
          

        // Add a new toolbar with a button on it
         
        GadgetTemporaryToolbar =
        	commandBars.Add("VistaGadgetDevelopmentToolbar",
        	MsoBarPosition.msoBarTop, System.Type.Missing, true);

        // Change the button style, which must be done casting the control to a button
  
        OpenVistaSidebarControlConsoleCommandBarButton =
        (CommandBarButton)OpenVistaSidebarControlConsoleCommand.AddControl
		(GadgetTemporaryToolbar,
        GadgetTemporaryToolbar.Controls.Count + 1);
        OpenVistaSidebarControlConsoleCommandBarButton.Style = 
				MsoButtonStyle.msoButtonIcon;

        // Add a new command bar popup with a button on it
  
        GadgetTemporaryCommandBarPopup =
		(CommandBarPopup)menuCommandBar.Controls.Add
				(MsoControlType.msoControlPopup,
		System.Type.Missing, System.Type.Missing, position, true);
       	GadgetTemporaryCommandBarPopup.CommandBar.Name = 
			"VistaGadgetDevelopmentCommandBarPopup";
       	GadgetTemporaryCommandBarPopup.Caption = "Gadget";         
  
                          
      	OpenVistaSidebarControlConsoleCommand.AddControl
		(GadgetTemporaryCommandBarPopup.CommandBar,
		GadgetTemporaryCommandBarPopup.Controls.Count + 1);            
}

Some cool features of Visual Studio IDE can be used for saving time for developers. One of them is creating and using Visual Studio templates for projects and items. You can prepare your own template for some project and open the entire project in a few minutes without writing any code string. The real benefit for template is simplicity for creating your own instance. The most easy way is accepted for Team Edition owners. These guys should only prepare template project and choose menu item File -> Export Template... The rest can create template using methods that were described in the good article by Ron Petrusha "Creating Visual Studio Project Templates".

Another interesting subject in add-in development is deployment. You can create and share items for using in Visual Studio. There also exist items for add-in deployment among others. With this item, you can easily deliver add-in to other developers. For using it with Visual Studio, you can package the item in a .vsi file, which can be installed by using the Visual Studio Content Installer. The Visual Studio Content Installer automatically copies the add-in items to the correct directories on a developer's computer so that the items appear in the correct dialog boxes in Visual Studio.

For using the Visual Studio Content Installer to install your community components, you must create a .vscontent file for the component. After you've created the .vscontent file, you should compress the component files and the .vscontent file into a single .zip file and change the file name extension from .zip to .vsi. You can find more about creating package for add-in and creating .vscontent file in this article.

Also, I want to mention a beautiful book about creating Visual Studio add-in which has always been a source of inspiration for me when I think about updating this article. There is Keyvan Nayyery's "Professional Visual Studio Extensibility" book. I am very much obliged to him for such an interesting book that has been very useful to me.

Conclusion

In this article, I show you how to create a Visual Studio Vista Gadget project template and use it from the Visual Studio IDE. Also, I show you how to install and use the RunVistaGadget Visual Studio add-in for running a Vista gadget from Visual Studio IDE. Why is it comfortable to use the Visual Studio IDE for creating a Vista gadget?

  • You can open a Vista gadget project with all files that you need for creating the gadget file just by choosing the required project.
  • You can use your favorite source control program for managing versions and history of a gadget's files.
  • You can use such advantages of the Visual Studio IDE as highlighting syntax, autocomplete expression for JavaScript code, and so on.
  • You can automate the process for running a new version of a gadget without leaving Visual Studio IDE.

History

The article was updated on 20th November 2010. With this update, following changes were made:

  • AddIn installation for Visual Studio 2010
  • Fixed bug for project with space in the path

The source code also available on Codeplex.

Here is the first version of this article - RunVistaGadget.aspx. This version can be useful if you can't place your project and Microsoft's utilities on the same logical disk. But the old version doesn't support signing and has a poor interface for running. In any case, it can be helpful for somebody.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)