расширенный фильтр записи api c #

1

Я использую Visual Studio 2010 и кодировку в С#.

 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 вместо hardcoding на "C:". Тем не менее, я все еще учился, и у меня возникли проблемы с использованием команды "EwfMgrGetProtectedVolumeList". Эта команда api вернет имя тома, в котором мне нужно запустить другие команды ewfapi. Однако эта команда возвращает переменную "PEWF_VOLUME_NAME_ENTRY", которую мне нужно определить. Здесь я застреваю. В C++ файл заголовка определяет эту переменную, но в С# заголовочные файлы не существует. Должен ли я преобразовать код C++ в код С#, чтобы использовать структуры, определенные в файле заголовка? В настоящее время я использую работу, выполняя команды с помощью командной строки, которая работает безупречно. Но мне любопытно и хочу узнать "правильный"/лучший способ сделать это в С#. Пожалуйста, дайте мне знать о любом опыте использования команд api в С#. Спасибо.

Это код, который я пытаюсь преобразовать в С#. Я не уверен, как преобразовать Declarators в C++ в С#.

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

Это преобразованный код С# без деклараторов:

 public struct EWF_VOLUME_NAME_ENTRY
    {

        /// _EWF_VOLUME_NAME_ENTRY*
        public System.IntPtr Next;

        /// WCHAR[1]
         public string Name;
    }
  • 1
    «Придется ли мне преобразовывать код C ++ в код c #, чтобы использовать структуры, определенные в заголовочном файле?», Да, вы делаете. ewfapi.dll посвящены целые сайты (я проверял, не видел ewfapi.dll ).
  • 0
    Хорошо, спасибо за ссылку на отличный сайт!
Показать ещё 1 комментарий
Теги:

2 ответа

1

Ваша попытка была действительно очень близка, ей просто нужны были некоторые атрибуты, чтобы помочь компилятору (на самом деле это могло работать без них)

[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 Easy ". Он включает ссылку на программу, которую вы можете дать ей подписи C/C++, и она вернет вам грубую версию подписи.NET P/Invoke.

0

Незначительная настройка на ответ Скотта. Имя - это строка с нулевым завершением, поэтому увеличьте 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;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню