国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#如何編輯文件的摘要信息

2019-11-14 16:27:11
字體:
來源:轉載
供稿:網友

我的以前的測試報告程序需要在倒完測試數據報告后,在文件摘要中加上一些類似版權說明的文字等等. 因此需要對文件摘要信息進行編輯. 我的記憶中以前好像只有office文檔才可以又摘要信息, 現在看來基本上所有文件(windows2000以上的平臺)都可以有摘要信息..

在網絡上搜尋一番發現一些有用的網址 1.如何編輯文件的摘要 http://groups.google.com/group/microsoft.public.dotnet.framework/msg/99a5dd5c80c084b5?hl=zh-CN&lr=&ie=UTF-8&oe=UTF-8&rnum=4 2.微軟知識庫關于ole32.dll 中函數的說明 http://msdn2.microsoft.com/en-us/library/aa380328.aspx 3.新手對COM的認識及疑惑 http://www.cn-doc.com/_soft_visual_c_tech_doc/2005_08_18_23/20050818230216780.htm [原處]http://dev.csdn.net/user/putongren

下面是對本問題的總結:

剛開始,我以為是shell32里面的方法可以完成,因此引用了Microsoft Shell Controls And Automation, (shell32.dll),但經過分析后沒有找到相關的方法. shell32是COM可以托管引用. 引用shell32可以查出文件的摘要信息,但無法編輯保存,下面是關于這個問題的答案. 如何用C#獲得文件信息以及擴展信息 

 

多次網上查詢后,我發現這篇在微軟討論組的文章(居然用google搜出來,沒有用msdn搜出),實際已經解決我的問題 setting file comment attribute PRogrammatically  

主要思路定義相關結構體(以接口方式定義)及輸入參數的枚舉值 引入ole32.dll 定義靜態方法對應函數 通過靜態方法返回接口, 此接口實際上就是一個指針(可以調用它的函數) 調用接口函數

 

開始我以為ole32.dll是一個COM,一直想引用,結果發現它只是一個函數庫, 必須對它進行dllimport.具體代碼可以看后面. 另外,我還發現以前微軟的virsual studio 6 里面的Depends工具,依然在virsual studio 2005中提供了,目錄在?:/Program Files/Microsoft Visual Studio 8/Common7/Tools 用這個工具可以查看一個函數庫有哪些公開方法.

補充點知識,先

對于使用COM或者函數庫的總結,來之(http://dev.csdn.net/user/putongren), 引用一部分

1. 想辦法知道 com 組件的 clsid (一個編號,16字節長,全球唯一);如果不知道 clsid,則要知道名字(progid),如 Excel.application

2. 開始與 ole32.dll 打交道吧 ! 如果進程尚未裝載它,那就 loadlibrary,然后再 getprocaddress ...

3. 不管三七二十一,先運行調用 coinitializeex,ole32.dll 內的一個函數,以便 ole32.dll 內部為線程記錄相應的數據,并允許你調用 ole32.dll 內的其他函數。

4. 如果已知道 clsid,則此步跳過。否則調用 clsidfromprogid 根據名字計算出 clsid。

這個 ole32.dll 內的函數實際上是在注冊表中進行查找,位置在: /hkey_classes_root/名字(progid),其下有一個 /clsid,里面就是clsid,其實自己去注冊表查找也可以。 excel.application 對應的 clsid = {00024500-0000-0000-c000-000000000046}。

5. 調用 ole32.dll 內的 cogetclassobject 建立一個 clsid 的 object。也可以調用 cocreateinstance / cocreateinstanceex。

這個 object 可以想象成操作系統在內存中加載了一個動態鏈接庫,或獨立啟動了一個進程,它不返回 object 的句柄,所以不要想通過一個句柄進行進一步訪問——像 getwindow(hwnd, ...),也趁早放棄通過 getprocaddress 取得函數入口位置進行進一步訪問的想法。到底怎么訪問呢,往下看...

6. 調用 cogetclassobject 建立一個 clsid 的 object 的同時,根據一個接口編號參數 iid_i... (全世界統一固定編號)返回一個接口指針,一個接口可以想象成一個函數的集合。

根據 clsid 產生的 object 可能有若干個不同的函數集合,每一個函數集合都有一個接口編號與其對應,iunknown 這個編號對應的接口是每個 object 都有的。每個函數集的前三個函數都一樣:queryinterface、addref、release。把其他接口編號作為參數調用 queryinterface 就可以找到其對應的函數集。

7. 關于 clsid 和 接口 iid

clsid 是一個 16 字節長的全球唯一編號,ole32.dll 根據它在注冊表中尋找對應的dll文件(也可以是exe文件)。參考程序與進程的概念,clsid 的實例化是加載一個 dll,或運行一個 exe 進程。dll 或 exe 被 ole32.dll 加載后,在 ole32.dll 的地址空間為其建立若干函數入口地址表(當然根據 dll 或 exe 的自身定義),并為每一個函數入口表建立一個保存其開始地址的指針(這個指針是地址中的一個長字)。

iid -- 接口,也是一個 16 字節長的全球唯一編號,ole32.dll 根據它在 clsid 的實例的所有 函數入口地址表的 指針 中找到一個對應的,返回來。所以接口的實例就是那個返回來的指針。

c 程序員可以把接口認為是一個結構,其成員是若干函數;c++ 程序員可以把接口認為是一個類 class。

至于通過 iid 找到的 函數入口表 中的各函數如何調用,去看那個 dll 或 exe 的開發接口文檔吧。在調用一個具體的函數時,當然可以把參數壓入堆棧,然后 call 那個函數,不過這好像是匯編中的低級做法,比較麻煩,在 vc 中定義一個類指針來保存接口返回來的指針,然后訪問類成員,用起來比較方便——參數壓入堆棧的問題編譯器替你解決了。

8. com

所以 com,概括起來說,就是用兩級編號,通過 ole32.dll 調用某個 dll 或 exe 提供的函數的方式。

當然在這基礎上還有 automation 等,定義了更多標準的接口編號及訪問方式,完成更復雜的功能。 

 調用方法SetProperty

 /*pls visit this article  * * http://msdn2.microsoft.com/en-us/library/aa380328.aspx  * To open an existing file, use the StgOpenStorageEx function instead.  notice: Applications written for Windows 2000, Windows Server 2003 and Windows xp must use StgCreateStorageEx rather than StgCreateDocfile to take advantage of the enhanced Windows 2000 and Windows XP Structured Storage features.  *     */   using System; using System.Collections.Generic; using System.Text; using StructuredStorageWrapper;   namespace WindowsApplication8 {     class FileSummary     {         public static void SetProperty(string filename,string msg , SummaryPropId summaryType)         {             // first you need to either create or open a file and its              // property set stream              //申明接口(指針)             ipropertySetStorage propSetStorage = null;             //com 組件的 clsid 參見IPropertySetStorage定義             Guid IID_PropertySetStorage = new Guid("0000013A-0000-0000-C000-000000000046");              //Applications written for Windows 2000, Windows Server 2003 and Windows XP must use StgCreateStorageEx rather than StgCreateDocfile to take advantage of the enhanced Windows 2000 and Windows XP Structured Storage features                         uint hresult = ole32.StgOpenStorageEx(                 filename,                 (int)(STGM.SHARE_EXCLUSIVE | STGM.READWRITE),                 (int)STGFMT.FILE,                 0,                 (IntPtr)0,                 (IntPtr)0,                 ref IID_PropertySetStorage,                 ref propSetStorage); //返回指針               // next you need to create or open the Summary Information property set              Guid fmtid_SummaryProperties = new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9");             IPropertyStorage propStorage = null;               hresult = propSetStorage.Create(                 ref fmtid_SummaryProperties,                 (IntPtr)0,                 (int)PROPSETFLAG.DEFAULT,                 (int)(STGM.CREATE | STGM.READWRITE | STGM.SHARE_EXCLUSIVE),                 ref propStorage);               // next, you assemble a property descriptor for the property you              // want to write to, in our case the Comment property              PropSpec propertySpecification = new PropSpec();             propertySpecification.ulKind = 1;             propertySpecification.Name_Or_ID = new IntPtr((int)summaryType);               //now, set the value you want in a property variant              PropVariant propertyValue = new PropVariant();             propertyValue.FromObject(msg);               // Simply pass the property spec and its new value to the WriteMultiple              // method and you're almost done              propStorage.WriteMultiple(1, ref propertySpecification, ref  propertyValue, 2);               // the only thing left to do is commit your changes.  Now you're done!              hresult = propStorage.Commit((int)STGC.DEFAULT);               //下面的很關鍵,如何關閉一個非托管的指針,如果不關閉,則本程序不關閉,文件被鎖定!             System.Runtime.InteropServices.Marshal.ReleaseComObject(propSetStorage);             propSetStorage = null;             GC.Collect();         }     } }  把ole32一些方法進行COM封裝 using System; using System.Text; using System.Runtime.InteropServices;   namespace StructuredStorageWrapper {     public enum SummaryPropId : int     {         Title = 0x00000002,         Subject = 0x00000003,         Author = 0x00000004,         KeyWords = 0x00000005,         Comments = 0x00000006,         Template = 0x00000007,         LastSavedBy = 0x00000008,         RevisionNumber = 0x00000009,         TotalEditingTime = 0x0000000A,         LastPrinted = 0x0000000B,         CreateDateTime = 0x0000000C,         LastSaveDateTime = 0x0000000D,         NumPages = 0x0000000E,         NumWords = 0x0000000F,         NumChars = 0x00000010,         Thumbnail = 0x00000011,         AppName = 0x00000012,         Security = 0x00000013     }       public enum STGC : int     {         DEFAULT = 0,         OVERWRITE = 1,         ONLYIFCURRENT = 2,         DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,         CONSOLIDATE = 8     }       public enum PROPSETFLAG : int     {         DEFAULT = 0,         NONSIMPLE = 1,         ANSI = 2,         UNBUFFERED = 4,         CASE_SENSITIVE = 8     }           public enum STGM : int     {         READ = 0x00000000,         WRITE = 0x00000001,         READWRITE = 0x00000002,         SHARE_DENY_NONE = 0x00000040,         SHARE_DENY_READ = 0x00000030,         SHARE_DENY_WRITE = 0x00000020,         SHARE_EXCLUSIVE = 0x00000010,         PRIORITY = 0x00040000,         CREATE = 0x00001000,         CONVERT = 0x00020000,         FAILIFTHERE = 0x00000000,         DIRECT = 0x00000000,         TRANSACTED = 0x00010000,         NOSCRATCH = 0x00100000,         NOSNAPSHOT = 0x00200000,         SIMPLE = 0x08000000,         DIRECT_SWMR = 0x00400000,         DELETEONRELEASE = 0x04000000     }       public enum STGFMT : int     {         STORAGE = 0,         FILE = 3,         ANY = 4,         DOCFILE = 5     }       [StructLayout(LayoutKind.Explicit, Size = 8, CharSet = CharSet.Unicode)]     public struct PropSpec     {         [FieldOffset(0)]         public int ulKind;         [FieldOffset(4)]         public IntPtr Name_Or_ID;     }       [StructLayout(LayoutKind.Explicit, Size = 16)]     public struct PropVariant     {         [FieldOffset(0)]         public short variantType;         [FieldOffset(8)]         public IntPtr pointerValue;         [FieldOffset(8)]         public byte byteValue;         [FieldOffset(8)]         public long longValue;           public void FromObject(object obj)         {             if (obj.GetType() == typeof(string))             {                 this.variantType = (short)VarEnum.VT_LPWSTR;                 this.pointerValue = Marshal.StringToHGlobalUni((string)obj);             }         }     }       [ComVisible(true), ComImport(),     Guid("0000013A-0000-0000-C000-000000000046"),     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]     public interface IPropertySetStorage     {         uint Create(             [In, MarshalAs(UnmanagedType.Struct)] ref System.Guid rfmtid,       [In] IntPtr pclsid,       [In] int grfFlags,             [In] int grfMode,       ref IPropertyStorage propertyStorage);           int Open(             [In, MarshalAs(UnmanagedType.Struct)] ref System.Guid rfmtid,             [In] int grfMode,                   [Out] IPropertyStorage propertyStorage);     }       [ComVisible(true), ComImport(),     Guid("00000138-0000-0000-C000-000000000046"),     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]     public interface IPropertyStorage     {         int ReadMultiple(             uint numProperties,             PropSpec[] propertySpecifications,             PropVariant[] propertyValues);           int WriteMultiple(             uint numProperties,             [MarshalAs(UnmanagedType.Struct)] ref PropSpec propertySpecification,             ref PropVariant propertyValues,             int propIDNameFirst);           uint Commit(             int commitFlags);     }       public enum HResults : uint     {         S_OK = 0,         STG_E_FILEALREADYEXISTS = 0x80030050     }       public class ole32     {         [StructLayout(LayoutKind.Explicit, Size = 12, CharSet = CharSet.Unicode)]         public struct STGOptions         {             [FieldOffset(0)]             ushort usVersion;             [FieldOffset(2)]             ushort reserved;             [FieldOffset(4)]             uint uiSectorSize;             [FieldOffset(8), MarshalAs(UnmanagedType.LPWStr)]             string pwcsTemplateFile;         }           [DllImport("ole32.dll", CharSet = CharSet.Unicode)]         public static extern uint StgCreateStorageEx(             [MarshalAs(UnmanagedType.LPWStr)] string name,             int accessMode, int storageFileFormat, int fileBuffering,             IntPtr options, IntPtr reserved, ref System.Guid riid,             [MarshalAs(UnmanagedType.Interface)] ref IPropertySetStorage propertySetStorage);           [DllImport("ole32.dll", CharSet = CharSet.Unicode)]         public static extern uint StgOpenStorageEx(             [MarshalAs(UnmanagedType.LPWStr)] string name,             int accessMode, int storageFileFormat, int fileBuffering,             IntPtr options, IntPtr reserved, ref System.Guid riid,             [MarshalAs(UnmanagedType.Interface)] ref IPropertySetStorage propertySetStorage);     }    }

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安泽县| 珠海市| 龙江县| 高青县| 涞源县| 江口县| 新巴尔虎右旗| 鄱阳县| 桃园县| 宝应县| 内黄县| 广水市| 南充市| 清水河县| 从江县| 营口市| 井陉县| 庄河市| 云安县| 鄂尔多斯市| 桦川县| 简阳市| 怀安县| 顺平县| 赤峰市| 弋阳县| 东海县| 绥宁县| 孝感市| 庄浪县| 渭南市| 稻城县| 河源市| 商河县| 阳城县| 绥宁县| 昌邑市| 阆中市| 永丰县| 西华县| 永丰县|