C# Can';无法使用DllImport找到VSIX DLL

C# Can';无法使用DllImport找到VSIX DLL,c#,visual-studio-2012,vsix,C#,Visual Studio 2012,Vsix,我有一个VSIX扩展,它依赖于从非托管DLL部署的代码。我已经将DLL包含在VSIX中,并用zip程序打开VSIX以确认它已正确部署。但是,当我使用DllImport属性时,.NET Framework声称找不到它。如何从我的VSIX中打包的DLL导入函数?Windows无法打开嵌入压缩.zip中的DLL文件,因此您必须将其解压缩并放入一个您有权写入的文件夹中 NET Framework将在%LocalAppData%中查找DLL的路径,因此在那里解压缩DLL是合理的。我不知道这里出了什么问题,

我有一个VSIX扩展,它依赖于从非托管DLL部署的代码。我已经将DLL包含在VSIX中,并用zip程序打开VSIX以确认它已正确部署。但是,当我使用DllImport属性时,.NET Framework声称找不到它。如何从我的VSIX中打包的DLL导入函数?

Windows无法打开嵌入压缩
.zip
中的DLL文件,因此您必须将其解压缩并放入一个您有权写入的文件夹中


NET Framework将在
%LocalAppData%
中查找DLL的路径,因此在那里解压缩DLL是合理的。

我不知道这里出了什么问题,但我重新安装了Windows和Visual Studio,没有对项目做任何更改,现在一切都很好。我在为其他应用程序查找DLL时遇到了一些其他问题,我想它们是相关的,我一定是搞砸了一些设置。

我过去常常在看似随机的情况下遇到虚假的包加载失败。这些问题主要影响由多个DLL文件组成的扩展名。通过将该属性应用于扩展中提供的主
,我最终解决了这些问题

您需要在项目中包含属性的源

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

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));
        }
    }
}
/***************************************************************************
版权所有(c)微软公司。版权所有。
此代码根据Visual Studio SDK许可条款获得许可。
此代码按原样提供,不保证
任何种类,无论明示或暗示,包括
对特定产品适用性的默示保证
目的、适销性或非侵权。
***************************************************************************/
使用制度;
使用系统文本;
命名空间Microsoft.VisualStudio.Shell
{
/// 
///此属性注册应在程序集加载时为候选程序集探测的路径。
/// 
///例如:
///[…\VisualStudio\10.0\BindingPath\{5C48C732-5C7F-40f0-87A7-05C4F15BC8C3}]
///“$PackageFolder$”=“”
///     
///这将把“PackageFolder”(即pkgdef文件的位置)注册为要探测的目录
///用于加载程序集。
/// 
[AttributeUsage(AttributeTargets.Class,AllowMultiple=true,Inherited=true)]
公共密封类ProvideBindingPathAttribute:RegistrationAttribute
{
/// 
///要在$PackageFolder$之后设置的可选子路径。应使用此选项
///如果要探测的程序集位于与
///pkgdef文件。
/// 
公共字符串子路径{get;set;}
私有静态字符串GetPathToKey(RegistrationContext上下文)
{
返回string.Concat(@“BindingPaths\”,context.ComponentType.GUID.ToString(“B”).ToUpperInvariant());
}
公共覆盖无效寄存器(RegistrationContext上下文)
{
if(上下文==null)
{
抛出新的ArgumentNullException(“上下文”);
}
使用(Key-childKey=context.CreateKey(GetPathToKey(context)))
{
StringBuilder keyName=新的StringBuilder(context.ComponentPath);
如果(!string.IsNullOrEmpty(子路径))
{
keyName.Append(“\\”);
追加(子路径);
}
SetValue(keyName.ToString(),string.Empty);
}
}
公共覆盖无效注销(RegistrationContext上下文)
{
if(上下文==null)
{
抛出新的ArgumentNullException(“上下文”);
}
RemoveKey(GetPathToKey(context));
}
}
}

可能缺少路径?这个有用吗?是否已确认非托管dll已正确提取到扩展的安装目录?我组装了一个简单的VSIX,它部署了一个调用非托管dll的shell包。我使用内容的构建操作将非托管dll添加到项目中,并将其包含在VSIX中。它在调试和常规部署的扩展中都能正确运行。@沃伦:我不知道它在哪里。我的DLL的生成操作也是“内容”,我将其设置为包含在VSIX中。@WarrenG:我检查了11.0exp extensions文件夹,非托管DLL就在那里,就在VSIX的其他未打包内容(包括DLL)旁边。因此,非托管DLL位于程序集的工作目录中。您的非托管DLL是否依赖于vsix中未包含的任何其他DLL?我更改了测试项目,使vsix包依赖于非托管dll#1,而非托管dll#2又反过来依赖于非托管dll#1。如果在vsix中包含dll#1,但不包含dll#2,则在执行测试代码时会出现DllNotFoundException。Visual Studio会将文件从vsix提取到安装目录中。是否可以打开事件日志并检查包尝试从哪个路径加载dll?这个工具可能会有所帮助:事件日志不会记录来自Visual Studio的任何事件。这似乎只有在DLLMain发出错误信号时,或者对于使用LoadLibrary或_declspec(dllimport)的非托管代码时才会出现。它当然没有列出任何来自VisualStudio或我的扩展的DLL错误。是的,但我这里不是说加载包。非托管DLL和包使用完全不同的机制。