Visual Studio extension auto-update

I am trying to have my extension automatically update when new versions are brought over to the Visual Studio gallery. There are several guides on how this can be achieved, but they are a couple of years old and may not apply.

First, I try to query IVsExtensionRepository

like this:

var _extensionRepository = (IVsExtensionRepository)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsExtensionRepository));

var query = _extensionRepository.CreateQuery<VSGalleryEntry>(false, true)
                .OrderByDescending(n => n.Ranking)
                .Skip(0)
                .Take(25) as IVsExtensionRepositoryQuery<VSGalleryEntry>;

query.ExecuteCompleted += Query_ExecuteCompleted;
query.ExecuteAsync();

      

Q Query_ExecuteCompleted

I am getting an exception from the server: "The remote server returned an error: (400) Bad request."

A stack trace is provided:

Server Stack Trace: at System.Runtime.AsyncResult.End [TAsyncResult] (result of IAsyncResult) at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End (result of SendAsyncResult) at System.Service.ServiceModel.Channel [] out, result IAsyncResult) in System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService (method IMethodCallMessageCall, ProxyOperationRuntime) in System.ServiceModel.Channels.ServiceChannelProxy.Invoke (message with message)

The service is hosted at: https://visualstudiogallery.msdn.microsoft.com/services/dev12/extension.svc

Does anyone know how I can create a Visual Studio extension that automatically updates from the Visual Studio gallery? Either via IVsExtensionRepository

or manually?

+3


source to share


2 answers


Edit: Now in Visual Studio 2015, extensions are loaded automatically.

So, I gave up on the request entirely IVsExtensionRepository

. I'm not sure why, but there must be some internal problem with the queries it creates. I requested the same service using the project suggested by ErikEJ and it worked fine.

However, I didn't want to create a service from WSDL as SQLCeToolbox did. I used IVsExtensionRepository

but avoided the method instead CreateQuery()

.

Attached is my approach to updating VSPackage. You will need to replace any GUIDs or specific package names with your package information.

NOTE There is one Gotcha in the following code:

Please note that CodeConnectRepositoryEntry

only implements DownloadUrl

. When updating the VSPackage, this is all we need to worry about as it allows us to download a new package. This url can be found on the VSGallery page for your VSPackage.



However: you should truncate the URL like this:

http://visualstudiogallery.msdn.microsoft.com/c0c2ad47-957c-4e07-89fc-20996595b6dd/file/140793/4/CodeConnectAlpha.vsix

in

http://visualstudiogallery.msdn.microsoft.com/c0c2ad47-957c-4e07-89fc-20996595b6dd/file/140793/

Above, / 4 / represents the fourth download. By removing it completely, the latest version will be loaded in the Visual Studio gallery.

internal class CodeConnectUpdater
{
    IVsExtensionManager _extensionManager;

    IVsExtensionRepository _extensionRepository;

    //We need only supply the download URL.
    //This can be retrieved from the "Download" button on your extension page.
    private class CodeConnectRepositoryEntry : IRepositoryEntry
    {
        public string DownloadUpdateUrl
        {
            get; set;
        }

        public string DownloadUrl
        {
            get
            {
                //NOTE: YOU MUST TRIM THE DOWNLOAD URL
                //TO NOT CONTAIN A VERSION. THIS FORCES 
                //THE GALLERY TO DOWNLOAD THE LATEST VERSION
                return "http://visualstudiogallery.msdn.microsoft.com/c0c2ad47-957c-4e07-89fc-20996595b6dd/file/140793/";
            }
            set
            {
                throw new NotImplementedException("Don't overwrite this.");
            }
        }

        public string VsixReferences
        {
            get; set;
        }
    }

    //I have been calling this from the VSPackage Initilize, passing in the component model
    public bool CheckForUpdates(IComponentModel componentModel)
    {
        _extensionRepository = (IVsExtensionRepository)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsExtensionRepository));
        _extensionManager = (IVsExtensionManager)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsExtensionManager));
        //Find the extension you're after.
        var extension = _extensionManager.GetInstalledExtensions().Where(n => n.Header.Name == "Code Connect Alpha").SingleOrDefault();

        return CheckAndInstallNewVersion(extension);
    }

    private bool CheckAndInstallNewVersion(IInstalledExtension myExtension)
    {
        var needsRestart = false;
        var entry = new CodeConnectRepositoryEntry();
        var newVersion = FetchIfUpdated(myExtension, entry);
        if (newVersion != null)
        {
            Install(myExtension, newVersion);
            needsRestart = true;
        }

        return needsRestart;
    }

    //Checks the version of the extension on the VS Gallery and downloads it if necessary.
    private IInstallableExtension FetchIfUpdated(IInstalledExtension extension, CodeConnectRepositoryEntry entry)
    {
        var version = extension.Header.Version;
        var strNewVersion = _extensionRepository.GetCurrentExtensionVersions("ExtensionManagerQuery", new List<string>() { "6767f237-b6e4-4d95-9982-c9e898f72502" }, 1033).Single();
        var newVersion = Version.Parse(strNewVersion);

        if (newVersion > version)
        {
            var newestVersion = _extensionRepository.Download(entry);
            return newestVersion;
        }

        return null;
    }

    private RestartReason Install(IInstalledExtension currentExtension, IInstallableExtension updatedExtension)
    {
        //Uninstall old extension
        _extensionManager.Disable(currentExtension);
        _extensionManager.Uninstall(currentExtension);

        //Install new version
        var restartReason = _extensionManager.Install(updatedExtension, false);

        //Enable the newly installed version of the extension
        var newlyInstalledVersion = _extensionManager.GetInstalledExtension(updatedExtension.Header.Identifier);
        if (newlyInstalledVersion != null)
        {
            _extensionManager.Enable(newlyInstalledVersion);
        }

        return restartReason;
    }
}

      

+2


source


I have the code to access the service and create an RSS feed from it here: sqlcetoolbox.codeplex.com/SourceControl/latest - in the NuGetDownloadfedd.zip file (has nothing to do with Nuget!) - also includes version number:

 foundItem.Project.Metadata.TryGetValue("VsixVersion", out version);

      



Actually I already have an RSS feed service, please let me know if you want to use it.

+1


source







All Articles