Can't find VSIX dlls with DllImport
Asked Answered
I

3

6

I have a VSIX extension which depends on code deployed from an unmanaged DLL. I've included the DLL with the VSIX, and I cracked open the VSIX with a zip program to confirm that it is deployed correctly. However, when I use the DllImport attribute, the .NET Framework claims that it can't find it. How can I import functions from a DLL packaged inside my VSIX?

Invest answered 3/8, 2013 at 18:8 Comment(5)
Maybe missing paths? Does this one help? https://mcmap.net/q/328251/-specify-the-search-path-for-dllimport-in-netCommingle
Have you confirmed that the unmanaged dll is being extracted correctly to the extension's install directory? I put together a simple VSIX that deploys a shell package that calls an unmanaged dll. I added the unmanaged dll to the project with a build action of Content and included it in the VSIX. It runs correctly both in debug and as a regular deployed extension.Herrle
@WarrenG: I have no idea where that is. My build action for my DLL is also "Content" and I set it to include in VSIX.Invest
@WarrenG: I checked the 11.0exp extensions folder, and the unmanaged DLL is right there, right next to the other unpacked contents of the VSIX- including the dll. So the unmanaged DLL is in the assembly's working directory.Invest
Does your unmanaged dll depend on any other dlls that aren't included in the vsix? I changed my test project so that the vsix package depends on unmanaged dll #1, which in turn depends on unmanaged dll #2. If I include dll #1, but don't include dll #2 in the vsix, I get a DllNotFoundException when I execute the test code.Herrle
I
3

I dunno what is going wrong here, but I reinstalled Windows and Visual Studio, made no changes to the project, and now everything is fine. I had some other issues with finding DLLs for other applications, and I guess they were related, I must have just screwed up some setting.

Invest answered 10/8, 2013 at 0:28 Comment(0)
T
2

Windows is unable to open DLL files embedded into compressed .zip, so you will have to unpack it and put in a folder where you have the access to write to.

The .NET Framework will look for the paths of your DLLs in %LocalAppData%, so it is reasonable to unpack your DLL there.

Termitarium answered 7/8, 2013 at 17:2 Comment(8)
Visual Studio extracts the files from the VSIX into an install directory.Invest
Can you open Events Log and check from what path your package tries to load DLL? en.wikipedia.org/wiki/Event_ViewerTermitarium
And this tool probably can help: technet.microsoft.com/en-us/sysinternals/bb896645Termitarium
The Event Log does not log any events coming from Visual Studio.Invest
That would seem to be only if DLLMain signals an error, or perhaps for unmanaged code using LoadLibrary or __declspec(dllimport). It certainly does not list any DLL errors coming from Visual Studio or my extension.Invest
It is a perfect tool to debug managed assemblies. Please, try it.Termitarium
I'mma be honest here and say that I looked at both the event log and process monitor, and neither of them appeared to provide any relevant information whatsoever. I have no idea how to use them to debug this issue.Invest
You can try simpler approach now (while you are learning how to use them): put your DLL into windows/system32 folder and try running the application.Termitarium
A
1

I used to get spurious package load failures in seemingly random situations. The problems primarily affected extensions comprised of more than one DLL file. I finally got them resolved by applying the [ProvideBindingPath] attribute to the main Package provided in the extension.

You'll need to include the source for the attribute in your project.

/***************************************************************************

Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

***************************************************************************/

using System;
using System.Text;

namespace Microsoft.VisualStudio.Shell
{
    /// <summary>
    /// This attribute registers a path that should be probed for candidate assemblies at assembly load time.
    /// 
    /// For example:
    ///   [...\VisualStudio\10.0\BindingPaths\{5C48C732-5C7F-40f0-87A7-05C4F15BC8C3}]
    ///     "$PackageFolder$"=""
    ///     
    /// This would register the "PackageFolder" (i.e. the location of the pkgdef file) as a directory to be probed
    /// for assemblies to load.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class ProvideBindingPathAttribute : RegistrationAttribute
    {
        /// <summary>
        /// An optional SubPath to set after $PackageFolder$. This should be used
        /// if the assemblies to be probed reside in a different directory than
        /// the pkgdef file.
        /// </summary>
        public string SubPath { get; set; }

        private static string GetPathToKey(RegistrationContext context)
        {
            return string.Concat(@"BindingPaths\", context.ComponentType.GUID.ToString("B").ToUpperInvariant());
        }

        public override void Register(RegistrationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            using (Key childKey = context.CreateKey(GetPathToKey(context)))
            {
                StringBuilder keyName = new StringBuilder(context.ComponentPath); 
                if (!string.IsNullOrEmpty(SubPath))
                {
                    keyName.Append("\\");
                    keyName.Append(SubPath);
                }

                childKey.SetValue(keyName.ToString(), string.Empty);
            }
        }

        public override void Unregister(RegistrationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.RemoveKey(GetPathToKey(context));
        }
    }
}
Amphictyony answered 10/8, 2013 at 5:30 Comment(1)
Yeah, but I'm not talking about loading packages here. Unmanaged DLLs and packages use quite different mechanisms.Invest

© 2022 - 2024 — McMap. All rights reserved.