Страницы

Поиск по вопросам

воскресенье, 5 января 2020 г.

Как создать/перезаписать свойства и группы свойств файла со Structured Storage API?

#c_sharp #cpp


Работаю с программой SolidEdge от Siemens. Мне необходимо читать/создавать/редактировать
свойства и группы свойств файлов. Для этих целей имеется официальное COM API, но оно
требует установленную SolidEdge с лицензией и помимо этого работает очень медленно.
Но так как файлы программы являются составными (Compound Files) и поддерживают API
структурированного хранилища (Structured Storage), то это можно использовать для решения
задачи. Для чтения свойств файла уже существует SolidEdge.Community.Reader, с помощью
которого можно читать свойства файлов не используя COM интерфейс, но он поддерживает
только чтение свойств. На форуме Siemens автор библиотеки предлагает добавить функциональность
создания/редактирования свойств, если это необходимо, но каким образом не уточняет.
Как бы то ни было, с помощью Structured Storage API решить проблему возможно. В этом
я убедился используя Structured Storage Viewer, с помощью которого можно редактировать
свойства файлов, создавать группы свойств и т.д.. После продолжительного поиска ничего
конкретного для работы со составными файлами с помощью C# я не нашёл. В связи с чем
имеются пару вопросов:


каким образом создавать/редактировать/удалять группы свойств в составных файлах?  
каким образом создавать/редактировать/удалять свойства в составных файлах?
в идеале хотелось бы узнать, каким образом расширить функционал библиотеки SolidEdge.Community.Reader
для возможности записи свойств?




Ссылки по теме


вопрос на enSO
Compound Files
Structured Storage
SolidEdge.Community.Reader на GitHub
Structured Storage Viewer
OpenMcdf на GitHub


P.S.: файл SolidEdge для тестов.
    


Ответы

Ответ 1



Вот пример записи значения строкового свойства в набор свойств Structured Storage: using System; using System.Collections; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { [DllImport("ole32.dll")] static extern int StgOpenStorageEx( [MarshalAs(UnmanagedType.LPWStr)] string pwcsName, uint grfMode, uint stgfmt, uint grfAttrs, IntPtr pStgOptions, IntPtr reserved2, [In] ref Guid riid, out IPropertySetStorage ppObjectOpen); const uint STGM_DIRECT = 0; const uint STGM_READWRITE = 0x2; const uint STGM_SHARE_EXCLUSIVE = 0x10; const uint STGFMT_ANY = 4; const uint VT_LPWSTR = 31; const uint PID_FIRST_USABLE = 2; const uint STGC_DEFAULT = 0; const uint PRSPEC_LPWSTR = 0; static void Main(string[] args) { IPropertySetStorage pPropSetStg = null; IPropertyStorage pPropStg = null; int hr; PROPSPEC propspec=new PROPSPEC(); PROPVARIANT propvarWrite=new PROPVARIANT(); Guid guidPropertySetStorage = typeof(IPropertySetStorage).GUID; string path = "c:\\Test\\Test.stg"; //путь к файлу Guid fmtid = Guid.Parse("F29F85E0-4FF9-1068-AB91-08002B27B3D9"); //GUID набора свойств try { //открываем файл hr = StgOpenStorageEx(path, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, ref guidPropertySetStorage, out pPropSetStg); if (hr != 0) throw Marshal.GetExceptionForHR(hr); //открываем набор свойств pPropSetStg.Open(fmtid, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, out pPropStg); //имя свойства... propspec.ulKind = PRSPEC_LPWSTR; propspec.unionmember = Marshal.StringToHGlobalUni("Property"); //значение свойства... propvarWrite.vt = (ushort)VT_LPWSTR; propvarWrite.unionmember = Marshal.StringToHGlobalUni("Value"); //записываем свойство pPropStg.WriteMultiple(1, ref propspec, ref propvarWrite, PID_FIRST_USABLE); pPropStg.Commit(STGC_DEFAULT); } finally { //освобождение ресурсов if (propspec.unionmember != IntPtr.Zero) Marshal.FreeHGlobal(propspec.unionmember); if (propvarWrite.unionmember != IntPtr.Zero) Marshal.FreeHGlobal(propvarWrite.unionmember); if (pPropSetStg != null) Marshal.ReleaseComObject(pPropSetStg); if (pPropStg != null) Marshal.ReleaseComObject(pPropStg); } } } [ComImport] [Guid("00000138-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPropertyStorage { void a(); void WriteMultiple(uint cpspec, ref PROPSPEC rgpspec, ref PROPVARIANT rgpropvar, uint propidNameFirst); void b( ); void c( ); void d(); void e(); void Commit(uint grfCommitFlags); void f(); void g(); void h( ); void x(); void y(); } [StructLayout(LayoutKind.Sequential)] public struct PROPSPEC { public uint ulKind; public IntPtr unionmember; } [StructLayout(LayoutKind.Sequential)] public struct PROPVARIANT { public ushort vt; public byte wReserved1; public byte wReserved2; public uint wReserved3; public IntPtr unionmember; } [ComImport] [Guid("0000013A-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPropertySetStorage { void Create(ref Guid rfmtid, ref Guid pClsid, uint grfFlags, uint grfMode, out IPropertyStorage ppprstg); void Open( ref Guid rfmtid, uint grfMode, out IPropertyStorage ppprstg); void Delete(ref Guid rfmtid); void f(); } } Создание нового набора свойств: pPropSetStg.Create(fmtid, new Guid(), 0,STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, out pPropStg); Источник: https://docs.microsoft.com/ru-ru/windows/desktop/Stg/writeread-sample

Комментариев нет:

Отправить комментарий