亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

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);     }    }

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
性金发美女69hd大尺寸| 亚洲欧美国产一区二区三区| 亚洲男人的天堂在线播放| 成人国产亚洲精品a区天堂华泰| 久久综合久久美利坚合众国| 亚洲一区二区久久| 黄色一区二区在线观看| 日本高清久久天堂| 亚洲美女又黄又爽在线观看| 国产精品久久久久久久久男| 亚洲天堂男人天堂女人天堂| 国产美女精品视频免费观看| 成人美女av在线直播| 日韩在线观看免费全| 91在线观看免费网站| 国产精品色婷婷视频| 日韩精品免费视频| 欧美午夜精品久久久久久浪潮| 亚洲xxxxx| 亚洲视频一区二区| 日韩在线观看电影| 国产精品美女久久久久av超清| 国内精品模特av私拍在线观看| 在线观看亚洲视频| 国产精品视频自在线| 亚洲国产小视频| 高清一区二区三区四区五区| 日韩精品视频中文在线观看| 国产欧美日韩专区发布| 日韩电影在线观看中文字幕| 精品久久久中文| 成人国产精品日本在线| 久久久久久久久久久免费精品| 欧美激情在线狂野欧美精品| 欧美性生交大片免费| 日韩激情av在线播放| 一区二区三区无码高清视频| 色婷婷**av毛片一区| 日韩欧美亚洲一二三区| 一本久久综合亚洲鲁鲁| 亚洲精品网址在线观看| 欧美视频一区二区三区…| 日韩欧美国产网站| 欧美大片第1页| 色综合色综合网色综合| 欧美精品18videos性欧美| 久久av资源网站| 最近2019好看的中文字幕免费| 国产精品久久久久久久美男| 欧美日韩视频在线| 欧美老肥婆性猛交视频| 精品久久久久久久大神国产| 亚洲欧美国产制服动漫| 亚洲精品第一国产综合精品| 欧美高清视频在线播放| 日韩69视频在线观看| 成人黄色生活片| 91精品啪在线观看麻豆免费| 国产精品视频一区国模私拍| 欧美性猛交xxxxx免费看| 国产精品2018| 国产精品人成电影在线观看| 97成人精品视频在线观看| 欧美黑人性视频| 色综合伊人色综合网站| 日韩一区二区福利| 国产成人一区二区三区电影| 欧美日韩人人澡狠狠躁视频| 理论片在线不卡免费观看| 少妇高潮久久久久久潘金莲| 欧美亚洲国产日韩2020| 国产精品福利无圣光在线一区| 亚洲图片在线综合| 国产精品免费久久久久久| 亚洲白拍色综合图区| 国产免费亚洲高清| 国产精品日韩欧美| 亚洲天堂av在线免费观看| 日韩中文在线观看| 日韩国产欧美精品一区二区三区| 日韩中文字幕免费视频| 2019av中文字幕| 国产一区玩具在线观看| 91九色精品视频| 亚洲丁香婷深爱综合| 亚洲精品wwwww| 久久久久久国产精品三级玉女聊斋| 国产精品中文久久久久久久| 日本久久中文字幕| 国产日韩在线视频| 亚洲最新av在线| 欧美性猛交xxxxx水多| 久久精品久久精品亚洲人| 成人久久久久爱| 51视频国产精品一区二区| 2019国产精品自在线拍国产不卡| 亚洲精品720p| 精品亚洲一区二区| 亚洲综合中文字幕68页| 91精品国产综合久久香蕉922| 国产精品视频一区二区三区四| 久久久亚洲网站| 欧美性理论片在线观看片免费| 亚洲福利视频久久| 久久精品99久久久香蕉| 午夜精品一区二区三区视频免费看| 夜夜嗨av一区二区三区免费区| 亚洲国产欧美自拍| 国产日韩av高清| 亚洲二区在线播放视频| 97久久精品国产| 国产精品日韩久久久久| 国产精品一区二区久久精品| 国产极品jizzhd欧美| 日韩在线观看免费高清完整版| 麻豆精品精华液| 日韩视频欧美视频| 日韩中文字幕在线播放| 亚洲精品久久视频| 国产精品毛片a∨一区二区三区|国| 国产精品入口福利| 高跟丝袜一区二区三区| 欧美日韩免费看| 91久久精品视频| 尤物99国产成人精品视频| 国模视频一区二区| 欧美丝袜美女中出在线| 国产视频精品一区二区三区| 国产精品一区二区三区免费视频| 中文字幕日本精品| 亚洲欧美精品伊人久久| 一区二区亚洲欧洲国产日韩| 中文字幕久热精品在线视频| www.久久草.com| 中文欧美在线视频| 久久精品国产清自在天天线| 亚洲精品白浆高清久久久久久| 91精品久久久久久久久久久久久久| 国产91九色视频| 久久视频在线看| 26uuu亚洲伊人春色| 91国产美女视频| 国产美女高潮久久白浆| 久久99久久99精品中文字幕| 日韩视频中文字幕| 成人女保姆的销魂服务| 欧美亚洲第一页| 亚洲精品自拍第一页| 久久久久久久亚洲精品| 九九综合九九综合| 国产精品偷伦免费视频观看的| 亚洲激情在线视频| 色中色综合影院手机版在线观看| 欧洲成人在线视频| 亚洲嫩模很污视频| 亚洲老头老太hd| 欧美国产视频一区二区| 国产精品一区二区三区久久久| 国产精品对白刺激| 97热精品视频官网| 91精品国产电影| 中文字幕精品一区二区精品| 国产精品99久久久久久久久久久久| 中文字幕亚洲一区二区三区|