Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

Deploying VSIX



  • I've been trying the community edition, and have been having issues deploying to vsix feeds. I've seen an example with curl, http://inedo.com/support/questions/6059, but that didn't provide much detail given the error I'm receiving:

    HTTP Status 500

    Details from Proget

    An error occurred processing a POST request to http://192.168.1.136:81/vsix/VSIXSample/: Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory.
    Details: System.IO.InvalidDataException: Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory.
    at System.IO.Compression.ZipArchive.ReadCentralDirectory()
    at System.IO.Compression.ZipArchive.GetEntry(String entryName)
    at Inedo.ProGet.Feeds.Vsix.VisualStudioPackageManifest.ReadFromPackage(Stream packageStream)
    at Inedo.ProGet.Feeds.Vsix.VsixFeed.<InstallPackageInternalAsync>d__20.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Inedo.ProGet.WebApplication.FeedEndpoints.Vsix.VsixFeedHandler.<ProcessRequestAsync>d__5.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Inedo.ProGet.WebApplication.FeedEndpoints.FeedEndpointHandler.FeedRequestHandler.<ProcessRequestAsync>d__8.MoveNext()

    I've been using to attempt deploy w/ C# in Linqpad:

    HttpClient client = new HttpClient();
    
    client.BaseAddress = new Uri("http://localhost:81/vsix/");
    client.DefaultRequestHeaders.Accept.Clear();
    var byteArray = Encoding.ASCII.GetBytes("admin:Admin");
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
    
    using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture)))
    {
    	var sourceFile = File.ReadAllBytes(@"ExtensionsTest.vsix");
    	var streamContent = new StreamContent(new MemoryStream(sourceFile));
     	streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/vsix");
                    
    	content.Add(streamContent, "ExtensionsTest.vsix", "ExtensionsTest.vsix");
    	using (var message = await client.PostAsync("VSIXSample/", content))
    	{
          var input = await message.Content.ReadAsStringAsync();
    	}
    }
    

    I've also compare the contents of the generated body against the what proget is sending when manually uploading from the page, I know this doesn't doesn't post to the same endpoint but I thought I've at least compare, and semantically they looked similar.

    If someone can point me to, what I assume is, my obvious bug I've overlooking, I'd appreciate it.

    Product: ProGet
    Version: 4.7.13



  • Hello Joshua,

    "Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory." is an error from the zip file format.

    How are you creating the .vsix file?



  • I was using a VSIX, generated in VS 2017.



  • We're not aware of any changes to the VISX format in Visual Studio 2017; it's really just a ZIP file with a metadata file in it.

    One possibility is that the file is getting corrupted somewhere between Visual Studio and ProGet (a common cause for file corruption would be some program reading it as if it was text).



  • I don't think it has to do with reading the file as text, since you see I'm explicitly reading using File.ReadAllBytes, which at least from the documentation read and return the file as types. I can look into StreamContent and what it does, but in the mean time as this is a dummy VSIX I have no issue posting the request to post, including the body, in case it will help.

    No idea how well this will work on the forum but lets give it a shot.

    POST http://mj0532y6:81/vsix/QL_VSGallery/ HTTP/1.1
    Authorization: Basic YWRtaW46QWRtaW4=
    Content-Type: multipart/form-data; boundary="Upload----07/18/2017 15:27:06"
    Host: mj0532y6:81
    Content-Length: 3307
    Expect: 100-continue
    Connection: Keep-Alive

    --Upload----07/18/2017 15:27:06
    Content-Type: application/vsix
    Content-Disposition: form-data; name=ExtensionsTest.vsix; filename=ExtensionsTest.vsix; filename*=utf-8''ExtensionsTest.vsix

    PK
     J [ l l   extension.vsixmanifest  (  <?xml version="1.0" encoding="utf-8"?>
    <PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
    <Metadata>
    <Identity Id="VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6" Version="1.0" Language="en-US" Publisher="Josh Baran" />
    <DisplayName>VSIXProjectTemplateTest</DisplayName>
    <Description>Empty VSIX Project.</Description>
    </Metadata>
    <Installation>
    <InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0]" />
    </Installation>
    <Dependencies>
    <Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" Version="[4.5,)" />
    </Dependencies>
    <Prerequisites>
    <Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
    </Prerequisites>
    </PackageManifest>PK
     JϜ   [Content_Types].xml  (  <?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="vsixmanifest" ContentType="text/xml" /><Default Extension="json" ContentType="application/json" /></Types>PK
     J ,%  
     manifest.json  (  {"id":"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6","version":"1.0","type":"Vsix","vsixId":"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6","extensionDir":"[installdir]\Common7\IDE\Extensions\awhrjxtf.exe","files":[{"fileName":"/extension.vsixmanifest","sha256":"80C46D9AB647AAEED79167D41A3DC3EBF23319278C9481D36D6FAB884CB93B0B"}],"installSize":2262,"dependencies":{"Microsoft.VisualStudio.Component.CoreEditor":"[15.0,16.0)"}}PK
     J Aш   catalog.json  (  {"manifestVersion":"1.1","info":{"id":"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6,version=1.0"},"packages":[{"id":"Component.VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6","version":"1.0","type":"Component","extension":true,"dependencies":{"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6":"1.0","Microsoft.VisualStudio.Component.CoreEditor":"[15.0,16.0)"},"localizedResources":[{"language":"en-US","title":"VSIXProjectTemplateTest","description":"Empty VSIX Project."}]},{"id":"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6","version":"1.0","type":"Vsix","payloads":[{"fileName":"VSIXProjectTemplateTest.vsix","size":6854}],"vsixId":"VSIXProjectTemplateTest.Josh Baran.54526157-c027-414d-a3b1-f81522b786e6","extensionDir":"[installdir]\Common7\IDE\Extensions\awhrjxtf.exe","installSize":2262}]}PK-
     J [ l l  extension.vsixmanifestPK-
     JϜ   [Content_Types].xmlPK-
     J ,%  
     manifest.jsonPK-
     J Aш  ' catalog.jsonPK  

    --Upload----07/18/2017 15:27:06--





  • Hello Joshua,

    Upon closer inspection, this seems to be because of the multipart request. This code should work:

    HttpClient client = new HttpClient();
    
    client.BaseAddress = new Uri("http://localhost:81/vsix/");
    client.DefaultRequestHeaders.Accept.Clear();
    var byteArray = Encoding.ASCII.GetBytes("admin:Admin");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
    
    var sourceFile = File.ReadAllBytes(@"ExtensionsTest.vsix");
    using (var streamContent = new ByteArrayContent(sourceFile))
    {
     	streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/vsix");
    
    	using (var message = await client.PostAsync("VSIXSample/", streamContent))
    	{
    		var input = await message.Content.ReadAsStringAsync();
    	}
    }
    

    VSIX feeds do not need the filename of the VSIX file because the data used to construct the URL is stored inside the file. Specifically, the Product ID and Version fields from the vsixmanifest.



  • Ben,

    That works. Thank you!

    TLDR; don't use "MultipartFormDataContent" when making this request.



Inedo Website HomeSupport HomeCode of ConductForums GuideDocumentation