相关疑难解决方法(0)

将NuGet包中的本机文件添加到项目输出目录

我正在尝试为.Net程序集创建NuGet程序包,它会对原生的win32 dll进行pinvoke.我需要将程序集和本机dll打包,并将程序集添加到项目引用中(此部分没有问题),并且应将本机dll复制到项目输出目录或其他相关目录中.

我的问题是:

  1. 如何在没有visual studio尝试将其添加到引用列表中的情况下打包本机dll?
  2. 我是否必须编写install.ps1来复制本机dll?如果是这样,我如何访问包内容进行复制呢?

nuget nuget-package nuget-spec

112
推荐指数
6
解决办法
5万
查看次数

为什么Visual Studio找不到我的DLL?

在Visual Studio 2010中,VC++ Directories > Executable Directories我已指定了路径glew32d.dll.但是,当我运行可执行文件时,它仍然会抱怨.

另一方面,如果我将DLL复制到本地文件夹然后运行可执行文件,它不会抱怨.

有人可以告诉我如何解决这个问题吗?另外,为什么Visual Studio无法识别该路径?

更新 场景:我目前使用的模板项目用作许多项目的入门代码.此模板取决于glew32d.dll.我通常将所有相关的dll存储在一个公共bin文件夹中.我希望引用这个文件夹,Visual Studio可以从那里读取dll,而不是每次都要复制dll.处理这个问题的好方法是什么?

c++ dll visual-studio-2010 visual-studio visual-c++

46
推荐指数
4
解决办法
16万
查看次数

C#Native Interop - 为什么大多数库使用LoadLibrary和委托代替SetDllDirectory和简单的DllImport

有关如何在运行时设置搜索目录的SO有一个很好的答案DllImport.使用两行代码可以正常工作.

但是,许多开源项目改为使用LoadLibrary函数.有传言称通过委托调用本机方法的速度较慢.我把它们称为"谣言",因为我只在两个地方看过这个,这无论如何都是微优化.

最有趣的地方是这篇博文:http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html

在那里,作者测量了不同技术的表现:

  • C#(资料性)4318毫秒
  • PInvoke - 抑制安全性5415 ms
  • Calli指令5505毫秒
  • C++/CLI 6311 ms
  • 功能委托 - 抑制安全性7788 ms
  • PInvoke 8249 ms
  • 功能代表11594ms

NNanomsg使用功能的代表,但提到的博客文章与评论"的这比传统的P中的性能的影响/ Invoke的,显然不是好"在这条线.

来自MSFT的ASP vNext的Kestrel服务器使用与Libuv库相同的技术:这是代码

我认为代理使用比简单的DllImport更麻烦,并且考虑到性能差异,我想知道为什么面向性能的库使用委托代替设置dll搜索文件夹?

是否有任何技术原因,如安全性,灵活性或其他 - 或者这仅仅是品味问题?我不明白其理由 - 作者是否可能没有足够的搜索StackOverflow!?

.net c# pinvoke interop

12
推荐指数
1
解决办法
2283
查看次数

如何在C#中使用C++ DLL导出的接口指针

我有一个用C++编写的DLL,它导出一个函数CreateRisk.该函数返回一个接口指针,如下所示:

extern "C"
{
    __declspec(dllexport) IRisk* __stdcall CreateRisk()
    {
        return new  Risk();


    }
}
Run Code Online (Sandbox Code Playgroud)

IRisk派生自IUnknown并具有自定义方法Calculate:

class IRisk: public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double s) = 0;  
};
Run Code Online (Sandbox Code Playgroud)

Risk类实现了IRisk接口(这里省略了实现).

我想要的是在c#中调用CreateRisk函数并获取对IRisk的引用.

我在c#中定义了一个包装器接口

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]        
    public interface IRisk
    {
        [PreserveSig]                                            
        int Calculate(int i,double s);
    }
Run Code Online (Sandbox Code Playgroud)

我在C#中添加了一个dll条目

    [DllImport("Risk.dll")]
    extern static IntPtr CreateRisk();
Run Code Online (Sandbox Code Playgroud)

我可以在C#中调用CreateRisk并获取IntPtr的值类型.有没有办法将IntPtr编组到c#IRisk接口,以便我可以在C#中调用Calculate方法?

我曾尝试过Marshal.GetIUnknownForObjectInContext,Marshal.GetObjectForIUnknown,但无济于事.

我知道创建COM组件可以做到这一点.但是,COM组件需要在系统中注册.我想避免这些麻烦,让C#直接使用C++ dll导出的接口.

PS:

以下是我的Risk类实现:

class IRisk : public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double y ) = 0;  
};

class Risk:public IRisk
{
    int count;
public: …
Run Code Online (Sandbox Code Playgroud)

c# c++ pinvoke

6
推荐指数
1
解决办法
4147
查看次数

非托管 DLL 的相对路径

可能的重复:
在 .NET 中指定 DllImport 的搜索路径

我有一个非托管的 DLL。为了清除,它是我想在我的 c# 代码中使用的 C++ dll。问题是它是一个 Windows 应用程序,用户可以将它安装在他们选择的任何目录中。所以我不能用静态路径引用它,也找不到给出相对路径的方法。这是我试过的代码:

 [DllImport("mydll.dll", CharSet = CharSet.Auto, SetLastError = true)]
  static extern bool SetDllDirectory(string lpPathName);

  public void SetDllDirectory(string lpPathName)
        {
            try
            {
                bool r = SetDllDirectory(lpPathName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void SetDirectoryPath()
        {
            try
            {
                DirectoryInfo directory = new DirectoryInfo(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath));
                if (directory.Exists)
                    SetDllDirectory(directory.ToString() + "\\mydll.dll");

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Run Code Online (Sandbox Code Playgroud)

下面是我收到的错误。

无法在 DLL“mydll.dll”中找到名为“SetDllDirectory”的入口点。

这个问题可能是复制品

C# 中的 C++ 非托管 …

c# windows dll unmanaged

4
推荐指数
2
解决办法
1万
查看次数

如何从C#中的特定路径读取DLL

我需要将SglW32.dll导入我的解决方案.

但我得到:

AccessViolation exeption:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.

我不能只使用DllImport.在那种情况下,找不到dll.

这是完整的例子.

using System;
using System.Runtime.InteropServices;
namespace TestDllimport
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new MyClass();
            var result = a.getValue();
        }
    }
    class FunctionLoader
    {
        [DllImport("Kernel32.dll")]
        private static extern IntPtr LoadLibrary(string path);

        [DllImport("Kernel32.dll")]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        public static Delegate LoadFunction<T>(string dllPath, string functionName)
        {
            var hModule = LoadLibrary(dllPath);
            var functionAddress = GetProcAddress(hModule, functionName);
            return Marshal.GetDelegateForFunctionPointer(functionAddress, typeof(T));
        }
    }

    public class MyClass
    {
        //Define your path …
Run Code Online (Sandbox Code Playgroud)

.net c# dll

3
推荐指数
1
解决办法
460
查看次数

当所需DLL的名称可能发生变化时,如何在运行时选择DllImport的路径?

我今天问了这个问题,但它被错误地关闭了,我无法选择重新打开它。因此,我不得不再问一遍。

我有一个类,其中有一长串定义,如下所示:

[DllImport(NativeLibraryName, EntryPoint = "FunctionName", CallingConvention = CallingConvention.Cdecl)]
public static extern void FunctionName();
Run Code Online (Sandbox Code Playgroud)

参数“NativeLibraryName”由编译器开关设置。但是,我想在运行时设置此参数。我的问题是,我需要考虑两种不同的 DLL:一种用于 32 位系统,一种用于 64 位系统,并且它们的名称不同。我想要实现的是确定应用程序是否以 64 位或 32 位运行并使用正确的 DLL。我需要加载正确的 DLL,否则我会遇到 BadImageFormatExceptions。

切换为代表

我可以使用 Reflection 生成一个文件,其功能与使用像这样的委托给出的文件相同。在这里,我可以在运行时提供正确的 DLL 的路径。

重命名 DLL

我还可以重命名这两个 DLL,使它们具有相同的名称,但将它们放在不同的目录中。然后我可以选择要从中加载 DLL 的文件夹。

这两个选项都可以正常工作,但我正在处理的项目是现有项目的一个分支,我希望尽可能少地进行更改,以便我可以轻松地将原始项目的更新合并到我的项目中。

我很高兴你的任何想法。

该线程被错误地建议作为我的问题的解决方案,并且原始线程在那之后被关闭。该线程讨论了类似的问题,但它没有提供适用于我的问题的解决方案。事实上,实际上提出了我自己想出的解决方案之一,但我正在寻找更好的方法来做到这一点。

c# dllimport loadlibrary

1
推荐指数
1
解决办法
2107
查看次数