将 MediaInfo DLL 与 C# DLLImport 一起使用

Posted

技术标签:

【中文标题】将 MediaInfo DLL 与 C# DLLImport 一起使用【英文标题】:Using MediaInfo DLL with C# DLLImport 【发布时间】:2020-02-19 02:08:32 【问题描述】:

使用MediaInfo DLL(64 位),我正在尝试获取提供有关 mp4 文件信息的标准文本输出。

为了包装 dll,我创建了一个 MediaInfo 类,基于我对 quickstart 指南的(有限)理解。

public class MediaInfo

    [DllImport("MediaInfo.dll")]
    private static extern IntPtr MediaInfo_New();

    [DllImport("MediaInfo.dll")]
    private static extern void MediaInfo_Open(string FileName);

    [DllImport("MediaInfo.dll")]
    private static extern IntPtr MediaInfo_Inform(IntPtr Handle);

    [DllImport("MediaInfo.DLL")]
    private static extern void MediaInfo_Close(IntPtr Handle);

    IntPtr Handle;

    public MediaInfo()
    
        Handle = MediaInfo_New();
    

    public void Open(string FileName)
    
        MediaInfo_Open(FileName);
    

    public string Inform()
       
        return Marshal.PtrToStringUni(MediaInfo_Inform(Handle));
    

    public void Close()
    
        MediaInfo_Close(Handle);
    

我正在使用下面的控制台应用程序调用这个类:

static void Main(string[] args)
    
        var objMediaInfo = new MediaInfo();
        objMediaInfo.Open("test.mp4");
        string result = objMediaInfo.Inform();
        objMediaInfo.Close();

        Console.WriteLine(result);
        Console.ReadKey();
    

但是,我只得到一个空白字符串作为回报。我尝试了几种不同的媒体文件。

我知道已经有一个完全开发的包装器,但我想保持这个简单和轻量级。

【问题讨论】:

【参考方案1】:

试试这可能对你有用:

变化

[System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
private static extern UIntPtr MediaInfo_Open(IntPtr Handle, string FileName);

[System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
private static extern IntPtr MediaInfo_Inform(IntPtr Handle, UIntPtr Reserved);

public System.UIntPtr Open(string FileName)

    return MediaInfo_Open(Handle, FileName);


public string Inform()

    return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, (UIntPtr)0));

清理

不要忘记删除由_MediaInfo_New_创建的指针(句柄)。您需要添加:

[DllImport("MediaInfo.dll")]
private static extern void MediaInfo_Delete(IntPtr Handle);

因此:

~MediaInfo()  if (Handle == (IntPtr)0) return; MediaInfo_Delete(Handle); 

实施

然后在您的实现中,您必须传递媒体文件的完整路径,而不仅仅是其名称:

static void Main(string[] args)

    var objMediaInfo = new MediaInfo();
    objMediaInfo.Open(@"TheFullPathOf\test.mp4");
    string result = objMediaInfo.Inform();
    objMediaInfo.Close();

    Console.WriteLine(result);
    Console.ReadKey();

祝你好运。

编辑

抱歉,答案不完整。我忘了在上一篇文章中提到您还需要通过 MediaInfo_Option API 设置 Inform 选项,这是定义返回数据的重要步骤:

[System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
private static extern IntPtr MediaInfo_Option(IntPtr Handle, string option, string Value);

为此创建函数:

public string Option(string option, string Value = "")

    return Marshal.PtrToStringUni(MediaInfo_Option(Handle, option, Value));

最后,修改你的实现:

static void Main(string[] args)

    var objMediaInfo = new MediaInfo();
    objMediaInfo.Open(@"TheFullPathOf\test.mp4");
    objMediaInfo.Option("Complete"); //or mi.Option("Complete", "1") or mi.Option("Info_Parameters") try them..
    string result = objMediaInfo.Inform();
    objMediaInfo.Close();
    Console.WriteLine(result);
    Console.ReadKey();

希望这次能成功。

【讨论】:

不幸的是,它仍然导致一个空字符串。 没问题。你的项目设置怎么样?是针对 x64 机器还是 AnyCPU?试试 32 位版本,看看它是否有效?试试像 v18.05 这样的旧版本怎么样?不要放弃,我觉得这只是一个小问题。如果不介意,请让我了解情况。同时我会再次检查我的代码,看看我是否又错过了什么。 用“任何 cpu”和“x86”尝试了 32 位 v19 dll。尝试使用“任何 cpu”和“x86”的 32 位 v18 dll。任何组合都没有错误,但仍然得到空白字符串。 我仔细检查了我的代码,这里没有提到任何内容。我上传了一个屏幕截图,只是为了向您展示一切正常。很抱歉没有提供帮助。祝你好运, 让我们continue this discussion in chat.【参考方案2】:
namespace Test_MediaInfo
  public partial class MainWindow : Window
  

    public class MediaInfo
    
      [DllImport("MediaInfo.dll")]
      private static extern IntPtr MediaInfo_New();

      [System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
      internal static extern IntPtr MediaInfo_Open(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string FileName);

      [System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
      private static extern IntPtr MediaInfo_Option(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string option, [MarshalAs(UnmanagedType.LPWStr)] string Value);

      [System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
      private static extern IntPtr MediaInfo_Inform(IntPtr Handle, UIntPtr Reserved);

      [System.Runtime.InteropServices.DllImport("MediaInfo.DLL")]
      private static extern void MediaInfo_Close(IntPtr Handle);

      [System.Runtime.InteropServices.DllImport("MediaInfo.dll")]
      private static extern void MediaInfo_Delete(IntPtr Handle);

      [DllImport("MediaInfo.dll")]
      private static extern IntPtr MediaInfoA_Option(IntPtr Handle, IntPtr Option, IntPtr Value);

      IntPtr Handle;
      public MediaInfo()
      
        Handle = MediaInfo_New();
      
      public System.IntPtr Open(string FileName)
      
        return MediaInfo_Open(Handle, FileName);
      
      public string Option(string option, string Value = "")
      
        return Marshal.PtrToStringUni(MediaInfo_Option(Handle, option, Value));
      
      public string Inform()
      
        return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, (UIntPtr)0));
      
      public void Close()
      
        MediaInfo_Close(Handle);
      
      public void delete_pointeur()
      
        MediaInfo_Delete(Handle);
      

    
    //---------------------------------------------------------------------------------
    public MainWindow()
      
        InitializeComponent();
        btn_go_Click(null, null);
      
    //---------------------------------------------------------------------------------
     private void btn_go_Click(object sender, RoutedEventArgs e)
    
      string hhhh;
      string FileName = "";
    //  FileName = @"F:\mkv\American Nightmare 2 - Anarchy (2014).mkv";
      //   FileName = @"F:\mp4\Cinq cartes à abattre (1968).mp4";
      FileName = @"F:\avi\Danse avec les loups.avi";

      string[] msg = new string[15];

      var tmp = new MediaInfo();
      tmp.Open(FileName);
      tmp.Option("Inform", "General;%OverallBitRate/String%");    msg[0] = tmp.Inform();// 1 h 38 min
      tmp.Option("Inform", "General;%Format%");                   msg[1] = tmp.Inform();// MpEG-4
      tmp.Option("Inform", "General;%FileSize/String3%");         msg[2] = tmp.Inform();// 3.67 GiB
      tmp.Option("Inform", "General;%Duration/String2%");         msg[3] = tmp.Inform();// 1 h 38 min
      tmp.Option("Inform", "Video;%Width% x %Height%");           msg[4] = tmp.Inform();// 1920 x 1080    
      tmp.Option("Inform", "Video;%DisplayAspectRatio/String%");  msg[5] = tmp.Inform();// 16.9
      tmp.Option("Inform", "Video;%Format_Commercial%");          msg[6] = tmp.Inform();// AVC
      tmp.Option("Inform", "General;%FrameRate/String%");         msg[7] = tmp.Inform();// 60.000 FPS
      tmp.Option("Inform", "Video;%BitRate/String%");             msg[8] = tmp.Inform();// 5 165 kb/s
      tmp.Option("Inform", "Video;%CodecID/Hint%");               msg[9] = tmp.Inform();// DivX 3 low
      tmp.Option("Inform", "Audio;%SamplingRate/String%");        msg[10] = tmp.Inform();// 44.1 kHz
      tmp.Option("Inform", "Audio;%Language/String%, %Channel(s)% channels, %Codec/String%, %SamplingRate/String%, %BitRate/String%"); msg[11] = tmp.Inform(); // ,2 channels,, 44.1kHz, 160 kb/s
        tmp.Option("Inform", "Audio;%BitDepth/String%");          msg[12] = tmp.Inform();// 
      tmp.Option("Inform", "General;%Text_Language_List%");       msg[13] = tmp.Inform();// French / French / English
      tmp.Option("Inform", "Video;%CodecID%");                    msg[14] = tmp.Inform();// avc1
      hhhh = tmp.Option("Complete", "1");                         // end of session
      tmp.Close();
      tmp.delete_pointeur();

    
    //---------------------------------------------------------------------------------
  

【讨论】:

欢迎您,尽量解释您发布的代码,并省略 cmets 等不必要的部分。将它分成几部分并逐个解释可能更容易。不要犹豫,查看Code of conduct

以上是关于将 MediaInfo DLL 与 C# DLLImport 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

C#使用MediaInfo查看媒体信息

MediaInfo 在 C# 中动态检查 AudioStreams

从 C# 调用 FORTRAN DLL 的受保护内存冲突

我要安装格式工厂,电脑出现丢失mediainfo.dll,应该怎么办??win7的系统 重新下载了还是安装出错 怎么办

msvci70.dll是啥??

potplayer播放器,视频属性那里显示MediaInfo.dll 不存在或无法识别