我的以前的测试报告程序需要在倒完测试数据报告后,在文件摘要中加上一些类似版权说明的文字等等. 因此需要对文件摘要信息进行编辑. 我的记忆中以前好像只有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是一个COM,一直想引用,结果发现它只是一个函数库, 必须对它进行dllimport.具体代码可以看后面. 另外,我还发现以前微软的virsual studio 6 里面的Depends工具,依然在virsual studio 2005中提供了,目录在?:/Program Files/Microsoft Visual Studio 8/Common7/Tools 用这个工具可以查看一个函数库有哪些公开方法.
补充点知识,先
调用方法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); } }