При попытке конвертировать существующее 32-разрядное приложение в 64-разрядное, мне не удалось заставить код COM Interop работать правильно. Код обращается к структурированному API хранения, используя управляемый код, который я переводил из различных файлов заголовков/IDL Windows SDK.Структурированное хранилище Windows - 32-разрядное и 64-битное COM-взаимодействие
Код не работает, когда я пытаюсь позвонить в IPropertyStorage.ReadMultiple()
, с STG_E_INVALIDPARAMETER
. Предыдущие вызовы interop, StgOpenStorageEx
и IPropertySetStorage.Open
, как представляется, работают нормально. MSDN утверждает, что эта ошибка означает, что что-то не так с моими параметрами PROPSPEC, но те же значения параметров отлично работают при компиляции в виде 32-разрядного приложения, а возвращаемое мной значение является правильным строковым значением для указанного свойства.
Вот что я думаю, соответствующие биты:
// PropertySpecKind enumeration.
public enum PropertySpecKind : uint
{
Lpwstr = 0,
PropId = 1
}
// PropertySpec structure:
[StructLayout(LayoutKind.Explicit)]
public struct PropertySpec
{
[FieldOffset(0)] public PropertySpecKind kind;
[FieldOffset(4)] public uint propertyId;
[FieldOffset(4)] public IntPtr name;
}
// PropertyVariant Structure:
[StructLayout(LayoutKind.Explicit)]
public struct PropertyVariant
{
[FieldOffset(0)] public Vartype vt;
[FieldOffset(8)] public IntPtr pointerValue;
}
// IPropertyStorage interface
[ComImport]
[Guid("00000138-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyStorage
{
int ReadMultiple(
uint count,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 0)] PropertySpec[] properties,
[Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 0)] PropertyVariant[] values);
void WriteMultiple(
uint count,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 0)] PropertySpec[] properties,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 0)] PropertyVariant[] values,
uint miniumumPropertyId);
}
var properties = new PropertySpec[1];
properties[0].kind = PropertySpecKind.PropId;
properties[0].propertyId = 2;
var propertyValues = new PropertyVariant[1];
// This helper method just calls StgOpenStorageEx with appropriate parameters.
var propertySetStorage = StorageHelper.GetPropertySetStorageReadOnly(fileName);
var propertyStorage = propertySetStorage.Open(StoragePropertySets.PSGUID_SummaryInformation, StorageMode.Read | StorageMode.ShareExclusive);
propertyStorage.ReadMultiple(1, properties, propertyValues); // Exception is here.
РазмерConst = 0, конечно, неверно, для этого требуется SizeParamIndex. Свойство PropertySpec.name имеет неправильное смещение в 64-битном режиме, это 8.Хорошие причины для написания этого кода в C++/CLI btw. –
Это структура PROPSPEC из ShellAPI, я просто использовал более дружественные имена. Согласно MSDN, «kind» (ulKind) является ULONG, который имеет одинаковый размер как на 32, так и на 64-битных; и «propertyId» (провидный) и «имя» (lpwstr) являются союзом, поэтому оба они должны начинать со смещения 4. Я получил что-то не так? –
(также, хороший улов на SizeConst, dunno, как я пропустил это, но это, казалось, не имеет никакого значения ...) –