Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

setting file comment attribute programmatically

735 views
Skip to first unread message

Bob Grimshaw

unread,
Nov 4, 2002, 11:15:50 AM11/4/02
to
Does anyone out there know how to set a file's "Comment" attribute
programmatically? I'm developing in C#, but I can't find anything in either
the .NET framework or the Win32API that does this. All I've found are posts
by other people asking the same question but getting no response. Can
anyone help me out? Thanks.

-bob grimshaw


Thomas Scheidegger [MVP] NETMaster

unread,
Nov 4, 2002, 11:49:56 AM11/4/02
to
I guess you have to use [heavy] Interop
with 'Structured Storage', like (VB.NET):

http://www.domaindlx.com/e_morcillo/ (slow site?)
http://www.domaindlx.com/e_morcillo/scripts/cod/net.asp
http://www.domaindlx.com/e_morcillo/scripts/cod/com.asp#ole_docprop

or with an extra ActiveX
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q224351

or maybe [commercial]
http://www.desaware.com/StorageToolsL2.htm


--
Thomas Scheidegger - MVP .NET - 'NETMaster'
http://www.cetus-links.org/oo_dotnet.html - http://dnetmaster.net/

"Bob Grimshaw" <Bob.Gr...@Bentley.com> wrote in message news:#lNh71BhCHA.2568@tkmsftngp11...

Bob Grimshaw

unread,
Nov 4, 2002, 1:57:32 PM11/4/02
to
Thanks a lot, I'll give that a try. Looks like its going to get ugly though
. . . this might not be the best thing for my example code in the SDK I'm
writing, we'll see.

"Thomas Scheidegger [MVP] NETMaster" <spam.ne...@swissonline.ch> wrote
in message news:OSCJEIChCHA.1760@tkmsftngp12...

Bob Grimshaw

unread,
Nov 8, 2002, 10:41:06 AM11/8/02
to
I've put together a working C# wrapper to do specifically what I was
interested in, setting the Comment attribute of a file if anyone is
interested. Many thanks to Eduardo Morcillo for his VB wrappers, which can
be found in the links provided by Thomas Scheidegger in his reply to my
initial post. For documentation, I looked at the MSDN on-line library under
Component Development -> Structured Storage. I hope this is useful to
someone and not just clutter. Warning: I only developed this to the point
of watching it work a few times, I have not thoroughly tested, intelligently
organized, or anything else good programmers should do ;)

****** Here's my calling code, just so you know what you're looking at in
the wrapper *********
// first you need to either create or open a file and its
// property set stream
IPropertySetStorage propSetStorage = null;
Guid IID_PropertySetStorage = new
Guid("0000013A-0000-0000-C000-000000000046");

uint hresult = ole32.StgOpenStorageEx(
"D:\\misc\\sspana.jdf",
(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)SummaryPropId.Comments);

//now, set the value you want in a property variant
PropVariant propertyValue = new PropVariant();
propertyValue.FromObject("Test Comment");

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

****** Here's the wrapper .cs file, in its entirety **********
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);
}
}

"Bob Grimshaw" <Bob.Gr...@Bentley.com> wrote in message

news:#a7wSQDhCHA.1860@tkmsftngp09...

0 new messages