增强的写过滤器api c#

本文关键字:api 过滤器 增强的 | 更新日期: 2023-09-27 18:20:28

我使用的是Visual Studio 2010并使用c#进行编码。

 public partial class App : Application
    {
    [DllImport("ewfapi.dll")]   
    public static extern IntPtr EwfMgrOpenProtected(string lpVolume);
    [DllImport("ewfapi.dll")]   
     public static extern bool EwfMgrCommit(IntPtr hDevice);

 public static bool EWFcommit()
    {
     temp = true;
        string strVolumeName = "C:";

        hProVol = EwfMgrOpenProtected(strVolumeName);       
       temp = EwfMgrCommit(hProVol);
       return temp;
}
}

我遇到的问题是,这些命令在启用EWF的机器上不起作用。我尝试从ewfmanager获取卷名,而不是将其硬编码为"C:"。然而,我仍在学习,并且在使用命令"EwfMgrGetProtectedVolumeList"时遇到了问题。这个api命令将返回运行其他ewfapi命令所需的VolumeName。但是,此命令返回我需要定义的"PEWF_VOLUME_NAME_ENTRY"变量。这就是我陷入困境的地方。在C++中,头文件定义了这个变量,但在C#中头文件是不存在的。为了使用头文件中定义的结构,我是否必须将C++代码转换为C#代码?目前,我正在使用一种通过命令提示符执行命令的变通方法,它可以完美地工作。但是,我很好奇,想在c#中学习"正确"/最好的方法。请告诉我在C#中使用api命令的任何经验。非常感谢。

这是我试图转换为C#的代码。我不确定如何将C++中的Declarator转换为C#。

 typedef struct _EWF_VOLUME_NAME_ENTRY
 {
struct _EWF_VOLUME_NAME_ENTRY* Next;
 WCHAR Name[1];
 } EWF_VOLUME_NAME_ENTRY, * PEWF_VOLUME_NAME_ENTRY;

这是没有声明符的转换后的C#代码:

 public struct EWF_VOLUME_NAME_ENTRY
    {
        /// _EWF_VOLUME_NAME_ENTRY*
        public System.IntPtr Next;
        /// WCHAR[1]
         public string Name;
    }

增强的写过滤器api c#

您的尝试实际上非常接近,它只需要一些属性来帮助编译器(事实上,如果没有它们,它可能会工作)

[StructLayout(LayoutKind.Sequential)]
public struct EWF_VOLUME_NAME_ENTRY 
{    
    /// _EWF_VOLUME_NAME_ENTRY*
    public System.IntPtr Next;
    /// WCHAR[1]    
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=1)]
    public string Name;
}

要使用它,您的方法的p/Invoke签名将是.

[DllImport("ewfapi.dll")]   
public static extern IntPtr EwfMgrGetProtectedVolumeList();

你还需要一些更多的功能

[DllImport("ewfapi.dll")]   
public static extern void EwfMgrVolumeNameListDelete(IntPtr list);
[DllImport("ewfapi.dll")]   
public static extern bool EwfMgrVolumeNameListIsEmpty(IntPtr list);
[DllImport("ewfapi.dll")]   
public static extern void EwfMgrVolumeNameEntryPop(ref IntPtr list);

然后你可以得到这样的受保护卷的列表。

public IEnumerable<string> GetProtectedVolumeNames()
{
    var listptr = EwfMgrGetProtectedVolumeList();
    if(listptr == IntPtr.Zero)
        throw new Win32Exception(); //the default constuctor calls Marshal.GetLastWin32Error() for you.
    try
    {
        while(!EwfMgrVolumeNameListIsEmpty(listPtr))
        {
            var currentStruct = Marshal.PtrToStructure<EWF_VOLUME_NAME_ENTRY>(listPtr); 
            // Pre .NET 4.5.1 version
            // var currentStruct = (EWF_VOLUME_NAME_ENTRY)Marshal.PtrToStructure(listPtr, typeof(EWF_VOLUME_NAME_ENTRY));
            yield return currentStruct.Name;
            EwfMgrVolumeNameEntryPop(ref listPtr);
        }
    }
    finally
    {
        if(listptr != IntPtr.Zero)
            EwfMgrVolumeNameListDelete(listptr);
    }
}

注意,这段代码是在浏览器中编写的,未经测试,但我认为它应该可以工作。

EDIT:重要提示,如果您在foreach之外使用此函数,而是手动处理IEnumerable,请确保将其处理掉,否则finally块将不会执行,并且您将出现内存泄漏(当您离开循环范围时,foreach会自动为您调用dispose)。


顺便说一句,你可能想看看MSDN杂志的这篇旧文章:"让PInvoke变得容易"。它包含一个指向程序的链接,您可以为该程序提供C/C++签名,它将为您返回.NET P/Invoke签名的粗略版本。

对斯科特的回答进行了小调整。名称是一个以null结尾的字符串,因此增加SizeConst以获得名称的其余字符:

[StructLayout(LayoutKind.Sequential)]
public struct EWF_VOLUME_NAME_ENTRY 
{    
    /// _EWF_VOLUME_NAME_ENTRY*
    public System.IntPtr Next;
    /// WCHAR[1]    
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=300)]
    public string Name;
}