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

Active Directory U&C PropertySheetExtension with C# and MMC 3.0

588 views
Skip to first unread message

Patrick

unread,
Sep 13, 2006, 1:17:18 PM9/13/06
to
Hi,
I'm new to MMC programming and want to develop an extension to the
user's property sheet (Adress, etc.) of ADUC. My propertysheet is
already visible but my problem is that I don't know how to access the
userdata. I want to access (read/write) the value of
"extensionProperty1". Is CFSTR_DSOBJECTNAMES a good way to start? Any
hints or sample code would be great!

Thanks!

Patrick

Patrik Hellgren

unread,
Sep 16, 2006, 5:11:12 PM9/16/06
to
I started with the SDK sample "ExtensionToPropertySheetSample" and made
some modifications to get it to work as a user property page in Users
and Computers. As you say that you have got to the point where you can
display the propertypage correctly i will not go in to that here.
I did some cutting and pasting to get this post together so I am not
100 percent sure it works as is but will hopefully get you going.

Here goes:

Changes made to ExtensionToPropertySheet.cs

public ExtensionToPropertySheet()
{
sharedDataItem = new SharedDataItem(@"DSOBJECTNAMES");
this.SharedData.Add(sharedDataItem);
}

protected override void
OnAddPropertyPages(PropertyPageCollection propertyPageCollection)
{
const int OFFSET_SELECTED_OBJECTS_COUNT = 16;

MarshalBuffer buffer = new
MarshalBuffer(sharedDataItem.GetData());
int selectedCount =
buffer.ReadInt(OFFSET_SELECTED_OBJECTS_COUNT);

//Propertypage should not be displayed if multiple objects
are selected.
if (selectedCount == 1)
{
// add extension page.
// UserPropertyPage is the class inherited from
PropertyPage and is called MachinePropertyPage in the SDK sample.
UserPropertyPage userPropertyPage = new
UserPropertyPage(sharedDataItem);
propertyPageCollection.Add(userPropertyPage);
}
}


UserPropertiesControl.cs (this is called MachinePropertiesControl.cs in
the SDK sample and this is the changes I made to it besides changing
the name)

//Object count in DSOBJECTNAMES is at byte 16
//Every object is 16 bytes
//First object starts at byte 20 offset for Name is at 28
offset for Class is at 32
//Second object starts at 36 offset for Name is at 44 offset
for Class is at 48 and so on for the following objects.
const int OFFSET_SELECTED_OBJECTS_COUNT = 16;
const int SIZE_OF_DSOBJECT = 16;
const int OFFSET_FIRST_DSOBJECT = 20;
const int OFFSET_NAME = 8;
const int OFFSET_CLASS = 12;

public void RefreshData(SharedDataItem sharedDataItem)
{
string distinguishedName = "";
MarshalBuffer buffer = new
MarshalBuffer(sharedDataItem.GetData());
//This commented code could be used when using multi select
to get to the different objects.
//string text = "";
//int selectedCount =
buffer.ReadInt(OFFSET_SELECTED_OBJECTS_COUNT);
//for (int i = 0; i < selectedCount; i++)
//{
// int offsetName = buffer.ReadInt((uint)(i *
SIZE_OF_DSOBJECT + OFFSET_FIRST_DSOBJECT + OFFSET_NAME));
// int offsetClass = buffer.ReadInt((uint)(i *
SIZE_OF_DSOBJECT + OFFSET_FIRST_DSOBJECT + OFFSET_CLASS));
// text += buffer.ReadString((uint)offsetClass) + "\r\n"
+ buffer.ReadString((uint)offsetName) + "\r\n";
//}
int offsetName =
buffer.ReadInt((uint)(OFFSET_FIRST_DSOBJECT + OFFSET_NAME));
distinguishedName += buffer.ReadString((uint)offsetName);
DirectoryEntry tempDSObject = new
DirectoryEntry(distinguishedName);
string customAttribute1 =
tempDSObject.Properties["extensionProperty1"].ToString();
userPropertyPage.Dirty = false;
}

public void UpdateData(SharedDataItem sharedDataItem)
{
string distinguishedName = "";
MarshalBuffer buffer = new
MarshalBuffer(sharedDataItem.GetData());
int offsetName =
buffer.ReadInt((uint)(OFFSET_FIRST_DSOBJECT + OFFSET_NAME));
distinguishedName += buffer.ReadString((uint)offsetName);
DirectoryEntry tempDSObject = new
DirectoryEntry(distinguishedName);
if (this.textBox1.Text != "")
{
tempDSObject.Properties["extensionProperty1"].Value =
this.textBox1.Text;
}
else
{
tempDSObject.Properties["extensionProperty1"].Clear();
}
tempDSObject.CommitChanges();
userPropertyPage.Dirty = false;
}

I hope this helps

Patrik Hellgren

Patrik Hellgren

unread,
Sep 18, 2006, 9:41:16 AM9/18/06
to
Sorry, forgot the MarshalBuffer class used to convert the byte array. I
got the idea for this from
http://www.webpronews.com/it/applicationdevelopment/wpn-19-20050202MovingCStructuresintoNETwithCustomMarshaling.html
but made some modifications to it to allow for strings.

Here is the class as used with the propertypage:

public class MarshalBuffer
{
byte [] _buffer = null;

public MarshalBuffer (uint size)
{
_buffer = new byte[size];
}

public MarshalBuffer (byte[] buffer)
{
_buffer = buffer;
}

public int ReadInt(uint offset)
{
return BitConverter.ToInt32(_buffer,(int)offset);
}

public long ReadChar(uint offset)
{
return BitConverter.ToChar(_buffer, (int)offset);
}

public string ReadString(uint offset)
{
StringBuilder str = new StringBuilder();
uint i = 0;
while (this.ReadChar(offset + i) != (char)0)
{
str.Append((char)this.ReadChar(offset + i));
i = i + 2;
}
return str.ToString();
}
}

That should be all

Patrik Hellgren

0 new messages