#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
Комментариев нет:
Отправить комментарий