<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Shawn's MIIS/ILM/FIM Code Experiment</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/therabournidentity/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/therabournidentity/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 16 Apr 2019 05:32:21 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>MIIS/ILM/FIM Code Experiment: Dynamics AX Management Agent (part 3)</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilmfim-code-experiment-dynamics-ax-management-agent-part-3</link>
      <pubDate>Wed, 30 Jun 2010 14:55:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2010/06/30/miisilmfim-code-experiment-dynamics-ax-management-agent-part-3/</guid>
      <description><![CDATA[Hello!&nbsp; 
One of the things I was tasked with was to set the initial Dynamics AX password for a...]]></description>
      <content:encoded><![CDATA[<p>Hello!&nbsp; </p>
<p>One of the things I was tasked with was to set the initial Dynamics AX password for a new user.&nbsp;&nbsp;I used information derived from our HR source to create the first password.&nbsp; This information&nbsp;needed to be encrypted in Dynamics AX on export, so the password encryption piece was added into the AX management agent.&nbsp; We'll actually call an internal Dynamics X++ method to perform the encryption.</p>
<p>I mentioned a global variable in the previous post</p>
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;">Axapta ax = new Axapta();</span></code></pre>
<p>This is an Axapta class object from the <a target="_blank" href="http://msdn.microsoft.com/en-US/library/microsoft.dynamics.businessconnectornet(v=AX.50).aspx">Microsoft.Dynamics.BusinessConnectorNet</a> namespace.</p>
<p>In the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms697211(v=VS.85).aspx">ExportEntry()</a> method, we loop through the different tables in Dynamics and populate attributes, but first we need to create an <a href="http://msdn.microsoft.com/en-US/library/microsoft.dynamics.businessconnectornet.axaptarecord.aspx">AxaptaRecord</a> class object against a table in Dynamics AX.&nbsp; In this example, "table" is a string "RBOSTAFFTABLE."</p>
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;">AxaptaRecord axRec;
<br />axRec.</span><a href="http://msdn.microsoft.com/en-US/library/aa548203.aspx"><span style="font-size: x-small;">CreateAxaptaRecord</span></a><span style="font-size: x-small;">(table);</span></code><span style="font-size: x-small;">&nbsp;</span></pre>
<p>Since&nbsp;we're&nbsp;solely creating new users, we loop through the attributes and use the <a href="http://msdn.microsoft.com/en-us/library/aa570287.aspx">set_Field</a> property to populate the AX table with the Connector Space entry attributes.&nbsp; I am not going to bore you with those details.&nbsp;&nbsp;However, Dynamics AX requires that the password attribute be encrypted.&nbsp; Since we don't have access to the encryption method for export attribute flow or to use within the management agent, we have to handle this attribute differently.&nbsp;&nbsp;&nbsp;We set the value initially in clear text, however we actually handle changing the password after we insert the initial&nbsp;AxaptaRecord in a new table transaction session, looking up the new entry by the unique StaffID value we just populated.</p>
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;">axRec.</span><a href="http://msdn.microsoft.com/en-us/library/microsoft.dynamics.businessconnectornet.axaptarecord.insert.aspx"><span style="font-size: x-small;">Insert</span></a><span style="font-size: x-small;">();//inserting initial attribute values
<br />ax.</span><a href="http://msdn.microsoft.com/en-US/library/microsoft.dynamics.businessconnectornet.axapta.ttsbegin.aspx"><span style="font-size: x-small;">TTSBegin</span></a><span style="font-size: x-small;">();
<br />axRec.</span><a href="http://msdn.microsoft.com/en-us/library/microsoft.dynamics.businessconnectornet.axaptarecord.executestmt.aspx"><span style="font-size: x-small;">ExecuteStmt</span></a><span style="font-size: x-small;">("select forupdate * from %1 </span></code><code class="csharp"><span style="font-size: x-small;">where %1.StaffID == '" + </span><a href="http://msdn.microsoft.com/en-us/library/ms695439(VS.85).aspx"><span style="font-size: x-small;">csentry</span></a><span style="font-size: x-small;">["RBOSTAFFTABLE.StaffID"].</span><a href="http://msdn.microsoft.com/en-us/library/ms694667(v=VS.85).aspx"><span style="font-size: x-small;">Value</span></a><span style="font-size: x-small;"> + "'")</span></code><span style="font-size: small;">&nbsp;</span></pre>
<p>Once we have our object selected, we can grab the cleartext password we inserted previously, encrypt the cleartext password using the Axapta method <a href="http://msdn.microsoft.com/en-US/library/aa548188.aspx">CallStaticClassMethod</a>&nbsp;for the Dynamics X++ class "RBOUtils" and&nbsp;method "Encrypt" and set it on the object, all in one line.&nbsp; And updating the object and committing the&nbsp;transaction is merely a formality.&nbsp;&nbsp;&nbsp;</p>
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;">axRec.set_Field("Password", </span></code><code class="csharp"><span style="font-size: x-small;">ax.CallStaticClassMethod("RBOUtils", "Encrypt", axRec.get_Field("Password").ToString()));
<br /><br />axRec.Update();
<br />ax.TTSCommit()</span><br /></code></pre>
<p>&nbsp;CallStaticClassMethod is a powerful method, as you can see.&nbsp; You can&nbsp;utilize Dynamics X++ methods from your MA.&nbsp; Very cool stuff.&nbsp; </p>
<p>&nbsp;</p>
<p>--Shawn</p>
<p>&nbsp;This posting is provided "AS IS" with no warranties, and confers no rights.</p>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM/FIM Code Experiment: Dynamics AX Management Agent (part 2)</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilmfim-code-experiment-dynamics-ax-management-agent-part-2</link>
      <pubDate>Wed, 20 Jan 2010 05:20:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2010/01/20/miisilmfim-code-experiment-dynamics-ax-management-agent-part-2/</guid>
      <description><![CDATA[Hello!
Today&nbsp;I'm going to talk about&nbsp;the Dynamics AX Management agent, specifically, the...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">Hello!</span></p>
<p><span style="font-size: small;">Today&nbsp;I'm going to talk about&nbsp;the Dynamics AX Management agent, specifically, the connection made in the functions for Import and Export.&nbsp;</span></p>
<p><span style="font-size: small;">The Dynamics AX Management Agent I created&nbsp;utilizes the Extensible Connectivity Management Agent available in MIIS, ILM and FIM.&nbsp; You can&nbsp;use the extensible connectivity management agent to connect to virtually anything as long as you have a way to connect.&nbsp; In this example, we will hook the </span><a target="_blank" href="http://msdn.microsoft.com/en-US/library/microsoft.dynamics.businessconnectornet(v=AX.50).aspx"><span style="font-size: small;">Microsoft.Dynamics.BusinessConnectorNet</span></a><span style="font-size: small;"> Namespace, which is&nbsp;available with&nbsp;an installation of&nbsp;the Dynamics AX client.&nbsp;In order to connect to the Dynamics AX instance, you need to set up the client and establish a connection configuration.&nbsp; You set up the connection configuration using the AX configuration utility.&nbsp; The string name of the configuration you set up is going to be utilized in the setup of the MA.&nbsp; I use the variable name "Configuration" as a configuration parameter in the MA.&nbsp; </span></p>
<p><span style="font-size: small;">The import method, </span><a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms697231(VS.85).aspx"><span style="font-size: small;">GenerateImportFile()</span></a><span style="font-size: small;"> and the export connection method, </span><a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms697203(v=VS.85).aspx"><span style="font-size: small;">BeginExport()</span></a><span style="font-size: small;"> will use the Configuration information to connect to Dynamics AX.&nbsp; </span></p>
<p><span style="font-size: small;">Both methods take advantage of a global variable I set up </span></p>
<p><span style="color: #0000ff; font-size: xx-small;">
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;"><span style="background-color: #000000;"><span style="font-family: courier new,courier;"><span style="background-color: #ffffff;"><span style="color: #000000;"><span style="font-size: small;">Axapta ax = new Axapta();</span></span></span></span></span></span></code></pre>
</span></p>
<p><span style="font-size: small;">The import method looks like this:</span></p>
<p><span style="color: #0000ff; font-size: xx-small;">
<pre class="scroll"><code class="csharp">
<br /><span style="font-size: x-small;"><span style="font-family: courier new,courier;"><span style="color: #000000;"><span style="font-size: small;"><span style="background-color: #000000;"><span style="background-color: #ffffff;">public void GenerateImportFile(string filename, string connectTo, string user, string password, ConfigParameterCollection configParameters, bool fullImport, TypeDescriptionCollection types, ref string customData)
<br />{    
<br />            String domain = user.Remove(user.IndexOf(@"\"));
<br />            String username = user.Remove(0, user.IndexOf(@"\") + 1)
<br />\\ The string "user" comes in from the management agent as DOMAIN\username
<br />            System.Net.NetworkCredential creds = new System.Net.NetworkCredential(username, password, domain);
<br />            ax.LogonAs(username, domain, creds, "", "", "", configParameters["Configuration"].Value);
<br />\\ Seems redundant to pass the NetworkCredential in as well as username and domain in LogonAs
<br />\\ The three nulls in LogonAs are company, language and objectServer; 
<br />\\ all of which are defined in the AX configuration, 
<br />\\ which is pulled from the management agent as one of the configParameters.  
<br /> ... insert code here...
</span><br /><span style="background-color: #ffffff;">}</span></span>
</span></span></span><br /></span></code></pre>
</span></p>
<p><span style="font-size: small;">Creating the connection for&nbsp;BeginExport is identical</span></p>
<p><span style="color: #0000ff; font-size: xx-small;">
<pre class="scroll"><code class="csharp"><span style="font-size: x-small;"><span style="font-family: courier new,courier;"><span style="font-size: small;"><span style="color: #000000;">public void BeginExport(string connectTo, string user, string password, ConfigParameterCollection configParameters, TypeDescriptionCollection types)
<br />{         
<br />            String domain = user.Remove(user.IndexOf(@"\"));
<br />            String username = user.Remove(0, user.IndexOf(@"\") + 1);
<br />            System.Net.NetworkCredential creds = new System.Net.NetworkCredential(username, password, domain);
<br />            ax.LogonAs(username, domain, creds, "", "", "", configParameters["Configuration"].Value);
<br />...insert code here...
<br />}</span>
</span></span></span></code></pre>
</span>
<p><span style="font-size: small;">Seems pretty straightforward, right?&nbsp;&nbsp; Until next time...</span></p>
</p>
<p><span style="font-size: small;">--Shawn</span></p>
<p><span style="font-size: small;">&nbsp;This posting is provided "AS IS" with no warranties, and confers no rights.</span></p>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM/FIM Code Experiment:   Dynamics AX Management Agent (part 1)</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilmfim-code-experiment-dynamics-ax-management-agent-part-1</link>
      <pubDate>Wed, 23 Dec 2009 14:49:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2009/12/23/miisilmfim-code-experiment-dynamics-ax-management-agent-part-1/</guid>
      <description><![CDATA[&nbsp;
Hello Everyone!&nbsp; 
OK, I admit.&nbsp; I am lame for not posting here in 16...]]></description>
      <content:encoded><![CDATA[<P mce_keep="true">&nbsp;</P>
<P>Hello Everyone!&nbsp; </P>
<P>OK, I admit.&nbsp; I am lame for not posting here in 16 months.&nbsp; I've been very busy and I want to be able to provide valuable and helpful information but I need to table the previous topic.&nbsp; In my last post, I was building a Fantasy Football Engine with ILM 2007&nbsp;&nbsp;and I still want to do that... eventually.&nbsp;&nbsp;More appropriately, however,&nbsp;one of my last projects was the Microsoft Retail Stores and one of the outcomes of the project was a Extensible Connectivity Management Agent for Dynamics AX.&nbsp; </P>
<P>In MIIS 2003 SP1 and later (and ILM 2007/FIM 2010) the <A href="http://technet.microsoft.com/en-us/library/cc720556(WS.10).aspx" target=_blank mce_href="http://technet.microsoft.com/en-us/library/cc720556(WS.10).aspx">Extensible Connectivity Management Agent</A> is the answer to the question "Does MIIS have a management agent for X?" if X&nbsp;is not compatible&nbsp;with&nbsp;a management agent built into the product or available as an add-on or download.&nbsp; Utilizing the <A href="http://msdn.microsoft.com/en-us/library/ms697197(VS.85).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms697197(VS.85).aspx">IMAExtensibleCallExport</A>, <A href="http://msdn.microsoft.com/en-us/library/ms697216(VS.85).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms697216(VS.85).aspx">IMAExtensibleFileExport</A> and/or the <A href="http://msdn.microsoft.com/en-us/library/ms697226(VS.85).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms697226(VS.85).aspx">IMAExtensibleFileImport</A> interfaces of the Microsoft.MetadirectoryServices namespace you can hook into just about anything that is .Net to connect to a data source.&nbsp; For Dynamics AX, I utilized the <A href="http://msdn.microsoft.com/en-us/library/microsoft.dynamics.businessconnectornet.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/microsoft.dynamics.businessconnectornet.aspx">Microsoft.Dynamics.BusinessConnectorNet</A> namespace to write entries to Dynamics AX within IMAExtensibleCallExport and to import and confirm&nbsp;building a file with IMAExtensibleFileImport.&nbsp; I felt I needed to create this management agent using an Extensible MA rather than using a database MA, as Dynamics AX can utilize a couple of different versions of SQL, as well as other third party database products and I wanted to build the Management Agent to be reusable for future customers beyond the Microsoft Retail Stores.</P>
<P>Building the AX MA was not a trivial exercise.&nbsp; I came into the project knowing absolutely nothing about Dynamics AX.&nbsp; I must say, Dynamics AX is the singlemost elegant product I have ever worked with!! &nbsp;I received a list of attributes and tables that I needed to interface with to provision users and a preferred order to write them in from the Retail Store AX team and started cranking the management agent out.&nbsp;&nbsp;In the next few posts, I will address how I tackled building the management agent and some of the issues that were encountered and how they were resolved.&nbsp; </P>
<P>--Shawn</P>
<P>&nbsp;This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P mce_keep="true">&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM Code Experiment: ILM Fantasy Football</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilm-code-experiment-ilm-fantasy-football</link>
      <pubDate>Tue, 12 Aug 2008 15:46:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2008/08/12/miisilm-code-experiment-ilm-fantasy-football/</guid>
      <description><![CDATA[Hello Everyone!
I am creating a series of posts crossing this MSDN blog and my TechNet blog...]]></description>
      <content:encoded><![CDATA[<P>Hello Everyone!</P>
<P>I am creating a series of posts crossing this MSDN blog and my TechNet blog <A href="http://blogs.technet.com/shawnrab">http://blogs.technet.com/shawnrab</A> where we will be&nbsp;build our own Fantasy Football engine utilizing Identity Lifecycle Manager with Feature Pack 1 and writing Visual Basic and Visual C# Rules Extensions</P>
<P>The initial rules of engagement are posted here:&nbsp; <A href="http://blogs.technet.com/shawnrab/archive/2008/08/12/miis-ilm-tricks-ilm-fantasy-football.aspx">http://blogs.technet.com/shawnrab/archive/2008/08/12/miis-ilm-tricks-ilm-fantasy-football.aspx</A></P>
<P>Have a good day!</P>
<P>--Shawn</P>
<P>&nbsp;This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P mce_keep="true">&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM Code Experiment: Populating the Manager field in Active Directory</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilm-code-experiment-populating-the-manager-field-in-active-directory</link>
      <pubDate>Tue, 29 Apr 2008 14:52:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2008/04/29/miisilm-code-experiment-populating-the-manager-field-in-active-directory/</guid>
      <description><![CDATA[Hello again.&nbsp; This post focuses on the manager attribute in Active Directory and using ILM to...]]></description>
      <content:encoded><![CDATA[<p>Hello again.&nbsp; This post focuses on the <strong>manager</strong> attribute in Active Directory and using ILM to populate the field.&nbsp; The <strong>manager</strong> attribute is a reference value.&nbsp; So simply populating the name of the manager or some unique identifier is not enough.&nbsp; Also, how do we know what manager goes with what person?&nbsp; Well, without manual population I'd hope that ERP or a&nbsp;similar data source would provide the <strong>employeeID</strong> or an attribute like <strong>managerID</strong> that was a pointer back to the <strong>employeeID </strong>of the employee's manager.&nbsp; Ideally the ERP would provide the manager field as a reference and you could flow the reference in directly, but in some scenarios you just can't get what you want.&nbsp; This is a way to do it.&nbsp; I don't claim that it is the best way, but this is an easy way.&nbsp;&nbsp; </p>
<p>Why is the manager field important?&nbsp; In Active Directory Users and Computers, it helps with the Organization tab on the user properties.&nbsp; In populating a user's manager field, you also indirectly populate the manager's Direct Reports field.&nbsp; This also helps enhance the Exchange GAL.&nbsp; </p>
<p>This sample relies on having an <strong>employeeID</strong>&nbsp;that is unique for the enterprise and&nbsp;a <strong>managerID</strong> coming from somewhere.&nbsp; I've also seen&nbsp;an attribute named similar&nbsp;to<strong> reportsTo</strong>&nbsp;used instead of <strong>managerID.&nbsp;</strong>&nbsp; Two metaverse attributes need to be created <strong>managerID </strong>and <strong>adDN</strong>.&nbsp; The <strong>managerID</strong> attribute would be flowed in from the ERP source and the <strong>adDN </strong>attribute would be a 1-1 mapping of the DN attribute in Active Directory.&nbsp; We would set this in the <strong>MapAttributesForExport()</strong> function.&nbsp; It relies on the manager having a correct, unique employee ID and looks back at the metaverse to see if the manager has an <strong>adDN </strong>attribute.&nbsp; If the manager doesn't exist yet, the logic below will quietly fail.&nbsp; The following attribute flows are:</p>
<p>ERP&lt;-----&gt;MV&lt;-----&gt;AD</p>
<p>ERP.person:<strong>managerID</strong>---(1-1 mapping)--&gt;MV.person:<strong>managerID</strong></p>
<p>MV.person:<strong>adDN</strong>&lt;---(1-1 mapping)---AD.user:<strong>&lt;dn&gt;</strong></p>
<p>MV.person:<strong>adDN(of the manager),managerID</strong>---&gt;<strong>(rules extension mapping)</strong>---&gt;AD.user:<strong>manager</strong></p>
<p>Here is the rules extension of the Export Flow rule for populating AD.user:<strong>manager</strong></p>
<p>&nbsp;</p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">case</span> "<span style="COLOR: #c00000">cd.user:manager&lt;-mv.person:adDN,managerID</span>":</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">if</span> (mventry["<span style="COLOR: #c00000">managerID</span>"].IsPresent)</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #00b0f0">MVEntry</span>[] mveManager;</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mveManager = <span style="COLOR: #00b0f0">Utils</span>.FindMVEntries("<span style="COLOR: #c00000">employeeID</span>", mventry["<span style="COLOR: #c00000">managerID</span>"].Value); <span style="COLOR: #00b050">//performs a search</span> </span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #00b050">//on the managerID or reportsTo field coming in from ERP for entries with that corresponding employeeID<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><o:p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></o:p><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0070c0"><span style="mso-spacerun: yes">&nbsp;</span>if</span> (mveManager.Length == 1)<span style="COLOR: #00b050">//if we get only one return (which we should)<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (mveManager[0]["<span style="COLOR: #c00000">adDN</span>"].IsPresent)<span style="COLOR: #00b050">//if there is the DN on that return</span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>csentry["<span style="COLOR: #c00000">manager</span>"].Value = mveManager[0]["<span style="COLOR: #c00000">adDN</span>"].Value; <span style="COLOR: #00b050">//set the DN as the manager</span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">break</span>;</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0"><span style="mso-spacerun: yes">&nbsp;&nbsp;</span>else<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0070c0">break</span>;<span style="COLOR: #00b050">//dn may not be populated yet - it will occur on the next run<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0"><span style="mso-spacerun: yes">&nbsp;</span>else<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">break</span>;<span style="COLOR: #00b050">//should never happen (employeeID is unique)- we'll fall through if it does<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><o:p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></o:p><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">else<o:p></o:p></span></span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0070c0">break</span>;</span></span></p>
<p class="MsoNormal" style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal"><span style="font-size: small;"><span style="font-family: Calibri;"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></span></p>
<p>&nbsp;</p>
<p>This method also works with a <strong>Secretary</strong> attribute.&nbsp; You just need a <strong>secretaryID</strong> or similar and we reuse the <strong>adDN </strong>attribute.&nbsp; <strong>WARNING!!</strong> FindMVEntries() does a search of the metaverse.&nbsp; Make sure the attribute you are searching for is indexed in the metaverse.&nbsp; In this case <strong>employeeID </strong>would need to be indexed.&nbsp; </p>
<p>What if there is not a unique ID like employee ID?&nbsp; You'll have to replace the trivial FindMVEntries backward lookup with logic similar to join rules for a manager.&nbsp;&nbsp; Hopefully your ERP data provides enough to show who a person's manager is.&nbsp; </p>
<p>Have a good day!</p>
<p>&nbsp;</p>
<p>--Shawn</p>
<p>This posting is provided "AS IS" with no warranties, and confers no rights.</p>
<p>And Just in case...</p>
<p>This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys&rsquo; fees, that arise or result from the use or distribution of the Sample Code.</p>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM Code Experiment:  Generic AD/ADAM Provisioning Function</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilm-code-experiment-generic-adadam-provisioning-function</link>
      <pubDate>Mon, 11 Feb 2008 17:50:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2008/02/11/miisilm-code-experiment-generic-adadam-provisioning-function/</guid>
      <description><![CDATA[Here is a fairly simple function to provision a user in Active Directory or ADAM and can be used...]]></description>
      <content:encoded><![CDATA[<P>Here is a fairly simple function to provision a user in Active Directory or ADAM and can be used interchangably so long as ADAM uses the object class "user"&nbsp; </P>
<P mce_keep="true">&nbsp;</P>
<P>This function is making the assumption that your design will determine the RDN, the LDAP container/OU that the object will sit and the string name of the management agent you are provisioning to.&nbsp; </P>
<P mce_keep="true">&nbsp;</P><FONT size=2>
<P></FONT><FONT color=#008000 size=2>/*</P>
<P>* ProvisionLDAPUser - Generic Provisioning function</P>
<P>* mventry is the affected metaverse entry</P>
<P>* MAName is the name of the Destination Management Agent</P>
<P>* rdn is the formatted relative name (ex: CN=John Smith or CN=Smith, John)</P>
<P>* container is the formatted destination container (ex: OU=Sales,OU=East,DC=northamerica,DC=fabrikam,DC=com)</P>
<P>* </P>
<P>*/</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>void</FONT><FONT size=2> ProvisionLDAPUser(MVEntry mventry, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> MAName, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> rdn, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> container)</P>
<P>{</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConnectedMA ldapMA = mventry.ConnectedMAs[MAName];</P>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if</FONT><FONT size=2> (ldapMA.Connectors.Count == 0)<FONT color=#008000 size=2>//make sure we don't have any pre-existing connectors</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSEntry cseLDAP = ldapMA.Connectors.StartNewConnector(</FONT><FONT color=#a31515 size=2>"user"</FONT><FONT size=2>);<FONT color=#008000 size=2>//generically start a new user</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cseLDAP.DN = ldapMA.EscapeDNComponent(rdn).Concat(container);<FONT color=#008000 size=2>//Concatenate the RDN and Container, ensuring proper formatting</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cseLDAP.CommitNewConnector();<FONT color=#008000 size=2>//Commit the new connector</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>}</P></FONT>
<P mce_keep="true">&nbsp;</P>
<P>&nbsp;If you wanted to, you could bring the predetermination of the user object&nbsp;type out of the function, in case you wanted to bring the logic for the determination of object (ex: user vs. contact)</P>
<P><FONT color=#0000ff size=2>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>void</FONT><FONT size=2> ProvisionLDAP(MVEntry mventry, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> MAName, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> rdn, </FONT><FONT color=#0000ff size=2>string</FONT><FONT size=2> container, <FONT color=#0000ff>string</FONT><FONT size=2> objectType</FONT>)</P>
<P>{</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConnectedMA ldapMA = mventry.ConnectedMAs[MAName];</P>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if</FONT><FONT size=2> (ldapMA.Connectors.Count == 0)<FONT color=#008000 size=2>//make sure we don't have any pre-existing connectors</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSEntry cseLDAP = ldapMA.Connectors.StartNewConnector(objectType</FONT><FONT size=2>);<FONT color=#008000 size=2>//generically start a new object </P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cseLDAP.DN = ldapMA.EscapeDNComponent(rdn).Concat(container);<FONT color=#008000 size=2>//Concatenate the RDN and Container, ensuring proper formatting</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cseLDAP.CommitNewConnector();<FONT color=#008000 size=2>//Commit the new connector</P></FONT>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>}</P></FONT>
<P>&nbsp;There isn't any error handling on CommitNewConnector, for handling duplicates or incorrect/missing container (OU).&nbsp; I like to handle outside of this function as I predetermine the rdn variable and container and if there is a caught error, I can handle it accordingly</P>
<P mce_keep="true">&nbsp;</P>
<P>try</P>
<P>{</P><FONT size=2>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProvisionLDAPUser(mventry, </FONT><FONT color=#a31515 size=2>"Test Active Directory"</FONT><FONT size=2>, </FONT><FONT color=#2b91af size=2>String</FONT><FONT size=2>.Concat(</FONT><FONT color=#a31515 size=2>"CN="</FONT><FONT size=2>, mventry[</FONT><FONT color=#a31515 size=2>"displayName"</FONT><FONT size=2>].Value), </FONT><FONT color=#a31515 size=2>"OU=Exchange Users,DC=test,DC=fabrikam,DC=com"</FONT><FONT size=2> );</P>
<P mce_keep="true">&nbsp;</P></FONT>
<P>&nbsp;}</P>
<P>catch (ObjectAlreadyExistsException)</P>
<P>...</P>
<P mce_keep="true">&nbsp;</P>
<P>}</P>
<P mce_keep="true">&nbsp;</P>
<P>This is helpful if there is a conflict on naming.&nbsp; Notice in my case, the RDN is the string literal "CN=" and the displayName attribute.&nbsp; I can ensure some uniqueness&nbsp;in the creation of that displayName attribute and not have to worry about ObjectAlreadyExistsException.&nbsp; If I don't, I can append an integer value or maybe use another attribute to append to the constructed RDN to ensure uniqueness.&nbsp; </P>
<P>&nbsp;More to come on this concept.</P>
<P>--Shawn</P>
<P>This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P>And Just in case...</P>
<P><FONT size=0>This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.</FONT></P>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM Code Experiment: XML-based MIIS/ILM Metaverse Router (part 1)</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilm-code-experiment-xml-based-miisilm-metaverse-router-part-1</link>
      <pubDate>Tue, 11 Dec 2007 14:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2007/12/11/miisilm-code-experiment-xml-based-miisilm-metaverse-router-part-1/</guid>
      <description><![CDATA[&nbsp;
(formerly posted at...]]></description>
      <content:encoded><![CDATA[<P mce_keep="true">&nbsp;</P>
<P>(formerly posted at <A href="http://blogs.technet.com/shawnrab/archive/2007/06/28/xml-based-miis-ilm-metaverse-router-part-1.aspx">http://blogs.technet.com/shawnrab/archive/2007/06/28/xml-based-miis-ilm-metaverse-router-part-1.aspx</A>&nbsp;)&nbsp;</P>
<P>So one of the complaints of people who use MIIS/IIFP/ILM for GALSync is that there is only one field for a metaverse rules extension.&nbsp; If you wanted to add provisioning in addition and seperate from the logic in the provision() block in the GALSync DLL, you would have to extend the&nbsp;GALSync.vb code which is subject to change (and be replaced in cumulative updates and service packs).&nbsp;There is decent solution out there called the MVRouter which looks in the MIIS extensions directory and looks for any DLL that starts with "mv" or "MVExtension" in the Extensions directory underneath the MIIS installation folder(technically it has a global called PREFIX that you can set).&nbsp; It will call MV_Galsync.Provision() or MV_Extension.Provision() within MVRouter.Provision() if your PREFIX is "MV_".&nbsp; The sample is located at the MIIS developer reference&nbsp; (<A href="http://msdn2.microsoft.com/en-us/library/ms698364.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms698364.aspx">http://msdn2.microsoft.com/en-us/library/ms698364.aspx</A>) and more targeted at <A href="http://msdn2.microsoft.com/en-us/library/ms696018.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms696018.aspx">http://msdn2.microsoft.com/en-us/library/ms696018.aspx</A></P>
<P>In sporadic posts, including this one we will build upon the sample at <A href="http://msdn2.microsoft.com/en-us/library/ms696018.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms696018.aspx">http://msdn2.microsoft.com/en-us/library/ms696018.aspx</A>&nbsp;to create an XML-based MVRouter and we will use that to try some fairly cool things with MIIS.</P>
<P>I warn all of you.&nbsp;&nbsp;This is just a sample.&nbsp; We're going to grow this sample as time passes.&nbsp; Also,&nbsp;suggestions are always appreciated.&nbsp; There will always be a better way to write code.&nbsp; </P>
<P mce_keep="true">&nbsp;</P>
<P>----snip----</P><FONT color=#0000ff size=2><FONT color=#000000><FONT size=2><FONT color=#0000ff size=2><BR>using</FONT><FONT size=2> System;<BR></FONT><FONT color=#0000ff size=2>using</FONT><FONT size=2> Microsoft.MetadirectoryServices;<BR></FONT><FONT color=#0000ff size=2>using</FONT><FONT size=2> System.Xml;<BR></FONT><FONT color=#0000ff size=2><BR>namespace</FONT><FONT size=2> Miis_Metaverse<BR>{<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;</FONT>public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>class</FONT><FONT size=2> MVExtensionObject : IMVSynchronization<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IMVSynchronization[] myMVDlls; </FONT><FONT color=#008000 size=2>//global array to pop the Metaverse Sync objects<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>string</FONT><FONT size=2>[] MVsToRun; </FONT><FONT color=#008000 size=2>//global array for string literal DLL's<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlDocument doc = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> XmlDocument(); </FONT><FONT color=#008000 size=2>//global XML document - we may want to bring this local later<BR>
<P mce_keep="true"><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>void</FONT><FONT size=2> IMVSynchronization.Initialize()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>
<P mce_keep="true"></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//the variable "dlls" is a number resulting from the private function popInitializeArr which will grab the&nbsp;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//metaverse dll files from the XML file<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>short</FONT><FONT size=2> dlls = popInitializeArr();</FONT><BR><BR><FONT size=2>&nbsp;<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>// Create the array the size of the number of files we found.<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myMVDlls = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> IMVSynchronization[dlls];<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>string</FONT><FONT size=2> fileName; </FONT><FONT color=#008000 size=2>// local variable for the file name<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assembly assem; </FONT><FONT color=#008000 size=2>//local variable to use to load the DLL&nbsp;<BR></FONT><FONT color=#2b91af size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>Type</FONT><FONT size=2>[] types; </FONT><FONT color=#008000 size=2>//local variable array to get type declarations from the DLL<BR></FONT><FONT color=#2b91af size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>Object</FONT><FONT size=2> objLoaded = </FONT><FONT color=#0000ff size=2>null</FONT><FONT size=2>;<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>// Load the extension files into the array.</FONT><BR><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>for</FONT><FONT size=2>(</FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> i = 0; i &lt; dlls; i++) </FONT><FONT color=#008000 size=2>//run this for the number of dll's that we have. <BR></FONT><FONT size=2><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//We could simplify and do a foreach if we wanted to&nbsp;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//ex: foreach (string mvtorun in mvstorun)<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// Load the assembly.<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileName = MVsToRun[i];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assem = Assembly.LoadFrom(Utils.ExtensionsDirectory + </FONT><FONT color=#a31515 size=2>@"\"</FONT><FONT size=2> + fileName); </FONT><FONT color=#008000 size=2>//this checks for the file name/presence</FONT><BR><FONT color=#008000 size=2>&nbsp;<BR></FONT><FONT size=2><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//note: we don't check to ensure that it is a DLL file here - a definite future improvement, not do we handle the&nbsp;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//lack of presence - we're assuming the file stated in XML actually exists<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; types = assem.GetExportedTypes();<BR>
<P mce_keep="true"></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>foreach</FONT><FONT size=2> (</FONT><FONT color=#2b91af size=2>Type</FONT><FONT size=2> type </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> types)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>if</FONT><FONT size=2> (type.GetInterface(</FONT><FONT color=#a31515 size=2>"Microsoft.MetadirectoryServices.IMVSynchronization"</FONT><FONT size=2>) != </FONT><FONT color=#0000ff size=2>null</FONT><FONT size=2>)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// Create an instance of the MV extension object type.<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objLoaded = assem.CreateInstance(type.FullName);<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>break</FONT><FONT size=2>;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </FONT><FONT color=#008000 size=2>//end foreach</FONT><BR><FONT color=#008000 size=2>&nbsp;<BR></FONT><FONT size=2><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// If an object type within could not be found,<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// or if an instance could not be created, throw an exception.<BR></FONT><FONT size=2><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>if</FONT><FONT size=2> (</FONT><FONT color=#0000ff size=2>null</FONT><FONT size=2> == objLoaded)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>throw</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> UnexpectedDataException(</FONT><FONT color=#a31515 size=2>"Object type not found or instance not created"</FONT><FONT size=2>);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// Add this MV extension object to our array of objects.<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myMVDlls[i] = (IMVSynchronization)objLoaded;<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>// Call the Initialize() method on each MV extension object.<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myMVDlls[i].Initialize();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT></FONT><BR><BR><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>void</FONT><FONT size=2> IMVSynchronization.Terminate()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>// Call the Terminate() method on each MV extension object.<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>foreach</FONT><FONT size=2> (IMVSynchronization mvextension </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> myMVDlls)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mvextension.Terminate();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR></FONT><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>void</FONT><FONT size=2> IMVSynchronization.Provision(MVEntry mventry)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>// Call the Provision() method on each MV extension object.<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>foreach</FONT><FONT size=2> (IMVSynchronization mvextension </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> myMVDlls)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mvextension.Provision(mventry);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT></FONT><BR><BR><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2>&nbsp;</FONT><BR><BR><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>bool</FONT><FONT size=2> IMVSynchronization.ShouldDeleteFromMV(CSEntry csentry, MVEntry mventry)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>bool</FONT><FONT size=2> shouldDelete = </FONT><FONT color=#0000ff size=2>false</FONT><FONT size=2>;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>// Call the ShouldDeleteFromMV() method on each MV extension object.<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>foreach</FONT><FONT size=2> (IMVSynchronization mvextension </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> myMVDlls)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>if</FONT><FONT size=2> (mvextension.ShouldDeleteFromMV(csentry, mventry))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shouldDelete = </FONT><FONT color=#0000ff size=2>true</FONT><FONT size=2>;<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>break</FONT><FONT size=2>;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<FONT color=#008000 size=2>// end if</FONT><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<FONT color=#008000 size=2>// end for</FONT><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>return</FONT><FONT size=2> (shouldDelete);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT></FONT><BR><BR><FONT color=#008000 size=2>&nbsp;</FONT><BR><BR><FONT color=#008000 size=2>&nbsp;</FONT><BR><BR><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>/* popInitializeArr is a function created to populate a DLL array and return a number exemplifying the number of dll's in the array*/<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>short</FONT><FONT size=2> popInitializeArr()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>short</FONT><FONT size=2> numParticipatingDLLs;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numParticipatingDLLs = 0; </FONT><FONT color=#008000 size=2>//assume nothing is there<BR></FONT><FONT size=2>
<P mce_keep="true"><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//logic to dig in XML to find the number of participating dlls<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doc.Load(Utils.ExtensionsDirectory + </FONT><FONT color=#a31515 size=2>@"\MIISXML.xml"</FONT><FONT size=2>); </FONT><FONT color=#008000 size=2>//Utils.ExtensionsDirectory grabs the Extensions folder under the&nbsp;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//MIIS install folder<BR>
<P mce_keep="true"><BR></FONT><FONT size=2><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlNode node = doc.SelectSingleNode(</FONT><FONT color=#a31515 size=2>"rules-extension-properties/dllfiles"</FONT><FONT size=2>);</FONT></P>
<P mce_keep="true"><FONT size=2><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//so the base tag is &lt;rules-extension-properties&gt; and we have a single child &lt;dllfiles&gt; - we are initializing&nbsp;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>//variable "node" as &lt;dllfiles&gt;<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</FONT>if</FONT><FONT size=2> (node.HasChildNodes) </FONT><FONT color=#008000 size=2>//I love expressions that do what they say<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//right off the bat let's assume that the child nodes all correspond to dll file names<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//we'll do some checks in making this code better that ensure the DLL is present<BR></FONT><FONT size=2><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numParticipatingDLLs = (</FONT><FONT color=#0000ff size=2>short</FONT><FONT size=2>)node.ChildNodes.Count;<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//initialize the str array with the number we're running - we can concat later<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MVsToRun = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>String</FONT><FONT size=2>[numParticipatingDLLs];<BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//and we'll whittle it down and&nbsp;<BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>int</FONT><FONT size=2> index = 0;<BR><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>foreach</FONT><FONT size=2> (XmlNode child </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> node.ChildNodes)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR><BR></FONT><FONT color=#008000 size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>//we probably need to check for the text ".dll" or append it later /check for indexOf ".dll" later...<BR></FONT><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MVsToRun.SetValue(child.Name, index);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index++;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </FONT><FONT color=#008000 size=2>//end foreach<BR></FONT><FONT size=2><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT><FONT color=#008000 size=2>// end if<BR></P>
<P mce_keep="true"><BR>&nbsp;&nbsp; 
<P mce_keep="true"><BR></FONT><FONT size=2><BR></FONT><FONT color=#0000ff size=2><FONT color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>return</FONT><FONT size=2> numParticipatingDLLs;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT><FONT color=#008000 size=2>// end popInitializeArr<BR></FONT><FONT size=2><BR>&nbsp;&nbsp;&nbsp; }</FONT><FONT color=#008000 size=2>//end class<BR></FONT><FONT size=2><BR>}</FONT><FONT color=#008000 size=2>//end namespace<BR></FONT></FONT></FONT></FONT><FONT size=2>
<P mce_keep="true"><BR></FONT><FONT size=3>&nbsp; </FONT>
<P>----end snip----</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">So our requirements need to be that the file name has to correspond exactly with the XML tag and must exist in the extensions directory.&nbsp; We should probably fix that later.&nbsp; We also have some other homework to do and I have ideas to show the potential of this thing.&nbsp; </P>
<P mce_keep="true">Right now the XML tagging would look like this:</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">---snip----</P>
<P mce_keep="true">&lt;rules-extension-properties&gt;</P>
<P mce_keep="true">&nbsp;&nbsp;&nbsp; &lt;dllfiles&gt;</P>
<P mce_keep="true">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;examplemvdllname.dll&gt;&lt;/examplemvdllname.dll&gt;</P>
<P mce_keep="true">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;samplemvdllname2.dll&gt;&lt;/samplemvdllname2.dll&gt;</P>
<P mce_keep="true">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</P>
<P mce_keep="true">&nbsp;&nbsp;&nbsp; &lt;/dllfiles&gt;</P>
<P mce_keep="true">&lt;/rules-extension-properties&gt;</P>
<P mce_keep="true">----end snip----</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">Think about the potential here - we could use the tags and innertext to our advantage.&nbsp; In the future, I will show some optimization I think we need and if anyone adds insight, I can add that.&nbsp; Also I have an advancement that I want to put in place that may (or may not) work.&nbsp; </P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">--Shawn</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">&nbsp;</P>
<P mce_keep="true">&nbsp;</P>
<P>This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P>And Just in case...</P>
<P><FONT size=0>This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.</FONT></P>]]></content:encoded>
    </item>
    <item>
      <title>MIIS/ILM Code Experiment: Joining using name tables for abbreviated and similar names</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/miisilm-code-experiment-joining-using-name-tables-for-abbreviated-and-similar-names</link>
      <pubDate>Tue, 11 Dec 2007 14:10:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2007/12/11/miisilm-code-experiment-joining-using-name-tables-for-abbreviated-and-similar-names/</guid>
      <description><![CDATA[&nbsp;
(formerly posted at...]]></description>
      <content:encoded><![CDATA[<P mce_keep="true">&nbsp;</P>
<P>(formerly posted at <A href="http://blogs.technet.com/shawnrab/archive/2007/11/07/miis-ilm-rocket-science-joining-using-name-tables-for-abbreviated-and-similar-names.aspx">http://blogs.technet.com/shawnrab/archive/2007/11/07/miis-ilm-rocket-science-joining-using-name-tables-for-abbreviated-and-similar-names.aspx</A>&nbsp;)&nbsp;</P>
<P>I am tasked this week with performing joins.&nbsp; We have an Active Directory environment and a Lotus Notes environment and we're simply trying to get the similar accounts joined.&nbsp; Biggest problem is that we don't have anything consistent between the two.&nbsp; No Employee ID and the Notes ShortName is not consistently the same as samAccountName in Active Directory.&nbsp; Most of the identities have a first name, middle initial and a last name.&nbsp; Some of them do not have a middle initial. </P>
<P>&nbsp;We have around 10000 total identities and we were able to get all but 1700 joined with these three mappings:</P>
<P>1.) Lotus Notes (FirstName and&nbsp;MiddleInitial and&nbsp;LastName) ---direct mapping---&gt; MV via Active Directory (givenName and&nbsp;initials and&nbsp;sn)</P>
<P>2.) LN(FirstName and LastName) ---direct mapping---&gt; MV via AD (givenName and sn) with LN(ShortName) ---rules extension mapping---&gt;MV via AD(samAccountName)</P>
<P>3.) LN(FirstName and LastName) ---direct mapping---&gt; MV via AD (givenName and sn) with LN(ShortName) ---rules extension mapping---&gt;MV via AD(first eight letters of the samAccountName)</P>
<P>&nbsp;Where one of the entries of ShortName was "close" to samAccountName, however ShortName is multivalued </P>
<P>of the 1700 left, a&nbsp;large chunk is test accounts, service accounts and other fun items, but we found around 450 "potential" joins where we had LastName and one of the ShortName-samAccountName mappings correct however the first name was not correct.&nbsp; I found a pattern where we would have a successful join if we could correlate similar or abbreviated names.&nbsp; Example (names have been faked to protect the innocent):</P>
<P>&nbsp;Similar/Misspelled Name--&gt;Phillip D. Jones (pdjones) vs. Philip D. Jones (pdjones)</P>
<P>Abbreviated Name--&gt;Richard J. Smith (rjsmith) vs.&nbsp;Rich J. Smith (rjsmith)</P>
<P>I created a file with entries comma seperated where these associations were made. Here are some example lines:</P>
<P>&nbsp;Andrew,Andy,Drew</P>
<P>Edward,Eduard,Eddy,Eddie,Ed,Edwin</P>
<P>Jennifer,Jenifer,Jen,Jenny,Jeni,Jennie</P>
<P>Katherine,Kathleen,Kathrine,Catherine,Cathleen,Cathy,Kathy,Kate,Cate,Cathrine</P>
<P>Timothy,Tim,Timmy</P>
<P>...etc...</P>
<P mce_keep="true">&nbsp;</P>
<P>We were able to come up with over 100 names that could be abbreviated, spelled differently or easily misspelled.&nbsp; I then created a multi-valued Metaverse Attribute called AltFirstName and flowed in these names.&nbsp; To do so, I saved my flat file to the Extensions Directory (typically C:\Program Files\Microsoft Identity Integration Server\Extensions) and added the following logic to my Management Agent rules extensions (NOTE: the Notes Extension is below, the Active Directory Extension is similar, yet the attribute name givenName is used where in LN, FirstName is used.)</P><FONT color=#0000ff size=2>
<P>Public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Class</FONT><FONT size=2> MAExtensionObject</P>
<P></FONT><FONT color=#0000ff size=2>Implements</FONT><FONT size=2> IMASynchronization</P>
<P></FONT><FONT color=#0000ff size=2></FONT>&nbsp;</P>
<P><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp; Dim</FONT><FONT size=2> AltNameArr </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>String</FONT><FONT size=2>() </FONT><FONT color=#008000 size=2>' global array to populate similar names</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp; Public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Sub</FONT><FONT size=2> Initialize() </FONT><FONT color=#0000ff size=2>Implements</FONT><FONT size=2> IMASynchronization.Initialize</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AltNameArr = File.ReadAllLines(Utils.ExtensionsDirectory + </FONT><FONT color=#a31515 size=2>"\names.txt"</FONT><FONT size=2>) </FONT><FONT color=#008000 size=2>' single call to push the lines of the file to </P></FONT><FONT size=2>
<P></FONT><FONT color=#008000 size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ' a String Array - each string represents the possible alternate names</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;End</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Sub</FONT></P>
<P><FONT color=#0000ff size=2></FONT>&nbsp;</P>
<P><FONT color=#0000ff size=2>...</FONT></P><FONT color=#0000ff size=2><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp; Public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Sub</FONT><FONT size=2> MapAttributesForImport(</FONT><FONT color=#0000ff size=2>ByVal</FONT><FONT size=2> FlowRuleName </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>String</FONT><FONT size=2>, _</P></FONT><FONT color=#0000ff size=2>
<P>&nbsp;&nbsp;&nbsp; ByVal</FONT><FONT color=#000000 size=2> csentry </FONT><FONT color=#0000ff size=2>As</FONT><FONT color=#000000 size=2> CSEntry, </FONT><FONT color=#0000ff size=2>ByVal</FONT><FONT color=#000000 size=2> mventry </FONT><FONT color=#0000ff size=2>As</FONT><FONT color=#000000 size=2> MVEntry) </FONT><FONT color=#0000ff size=2>Implements</FONT><FONT size=2><FONT color=#000000> _</FONT></P>
<P>&nbsp;&nbsp;&nbsp; IMASynchronization.MapAttributesForImport</P>
<P mce_keep="true">&nbsp;</P>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Select</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Case</FONT><FONT size=2> FlowRuleName</P>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Case</FONT><FONT size=2> </FONT><FONT color=#a31515 size=2>"AltFirstName"</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Not</FONT><FONT size=2> mventry(</FONT><FONT color=#a31515 size=2>"AltFirstName"</FONT><FONT size=2>).IsPresent </FONT><FONT color=#0000ff size=2>Then</FONT><FONT size=2> </FONT><FONT color=#008000 size=2>' this is rather expensive so only do it once</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Each</FONT><FONT size=2> nameArr </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>String</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>In</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Me</FONT><FONT size=2>.AltNameArr </FONT><FONT color=#008000 size=2>' for each line</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If</FONT><FONT size=2> nameArr.IndexOf(csentry(</FONT><FONT color=#a31515 size=2>"FirstName"</FONT><FONT size=2>).Value + </FONT><FONT color=#a31515 size=2>","</FONT><FONT size=2>, StringComparison.CurrentCulture) &gt; -1 </FONT><FONT color=#0000ff size=2>Then</FONT><FONT size=2> </FONT><FONT color=#008000 size=2>' check to see if the name is present</P></FONT><FONT size=2>
<P></FONT><FONT color=#008000 size=2><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>' I added the comma so "Jo" short for "Joanne" didn't return an index for "Joe" and the case sensitivity</P></FONT><FONT size=2>
<P></FONT><FONT color=#008000 size=2><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>' StringComparison.CurrentCulture so "Ian" doesn't get confused with "Brian"</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim</FONT><FONT size=2> AltFNValues </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>String</FONT><FONT size=2>() </FONT><FONT color=#008000 size=2>' Initialize a single string array for each possibility</P></FONT><FONT size=2>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AltFNValues = nameArr.Split(</FONT><FONT color=#a31515 size=2>","</FONT><FONT size=2>) </FONT><FONT color=#008000 size=2>' Populate that array</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Each</FONT><FONT size=2> altFN </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>String</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>In</FONT><FONT size=2> AltFNValues </FONT><FONT color=#008000 size=2>' for each entry in the array</P></FONT><FONT size=2>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mventry(</FONT><FONT color=#a31515 size=2>"altFirstName"</FONT><FONT size=2>).Values.Add(altFN) </FONT><FONT color=#008000 size=2>' add a new value to the AltFirstName metaverse entry</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Next</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>If</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Next</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>If</P></FONT>
<P></FONT><FONT size=3>...</FONT></P>
<P mce_keep="true"><FONT size=3></FONT>&nbsp;</P>
<P>I then created these join mappings&nbsp; </P>
<P>1.) LN(FirstName and LastName) ---direct mapping---&gt; MV via AD (<STRONG>AltFirstName&nbsp;</STRONG>and sn) with LN(ShortName) ---rules extension mapping---&gt;MV via AD(samAccountName)</P>
<P>2.) LN(FirstName and LastName) ---direct mapping---&gt; MV via AD (<STRONG>AltFirstName</STRONG> and sn) with LN(ShortName) ---rules extension mapping---&gt;MV via AD(first eight letters of the samAccountName)</P>
<P mce_keep="true">&nbsp;</P>
<P>Now, I am sure there is a more efficient way to do this, using SQL or XML rather than a flat file to import the name associations, or using a two-dimensional array instead of looping the file into one array and splitting to get a second array, but as a first test, we were rather successful with zero false positives.&nbsp; We were able to recover 425 of the&nbsp;450 "potential" joins this way.&nbsp; </P>
<P>I'd like to mention that I received a lot of help from the customer on creating the large list of names (over 400 names) - Christine M. and my shadow this week, Raffe who also came up with a few as well.&nbsp; Both were also very good voices of reason ensuring me that I wasn't unreasonable trying to get "Brian" to map to "Brien" when the last name was Smiswartszkoether (completely made-up last name intended to sound unique) on both sides.&nbsp; </P>
<P>I am sure I am not the first person to do this, but if I can help someone out there out with their joins by posting this, I've done exactly what I've set out to do.&nbsp; </P>
<P>Have fun, and good luck</P>
<P>--Shawn</P>
<P mce_keep="true"><STRONG>UPDATE:&nbsp; 11/28 - For those people running SQL 2005, it appears that Alex Tcherniakhovski found a way to do this using functionality built in to SQL 2005 SSIS - see <A href="http://blogs.gotdotnet.com/alextch/archive/2005/07/15/init-record-linking-via-ssis.aspx">http://blogs.gotdotnet.com/alextch/archive/2005/07/15/init-record-linking-via-ssis.aspx</A></STRONG></P>
<P mce_keep="true"><STRONG>or</STRONG></P>
<P mce_keep="true"><A href="http://blogs.msdn.com/alextch/archive/2005/08/09/miis-and-ssis.aspx"><STRONG>http://blogs.msdn.com/alextch/archive/2005/08/09/miis-and-ssis.aspx</STRONG></A></P>
<P mce_keep="true"><STRONG>to find out more.&nbsp; </STRONG></P>
<P mce_keep="true">&nbsp;</P>
<P>This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P>And Just in case...</P>
<P><FONT size=0>This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.</FONT></P>
<P mce_keep="true">&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>Shawn's MIIS/ILM Code Experiment:  Obligatory First Post...</title>
      <link>https://docs.microsoft.com/archive/blogs/therabournidentity/shawns-miisilm-code-experiment-obligatory-first-post</link>
      <pubDate>Tue, 11 Dec 2007 14:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Shawn Rabourn [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/therabournidentity/2007/12/11/shawns-miisilm-code-experiment-obligatory-first-post/</guid>
      <description><![CDATA[&nbsp;
Hello!&nbsp; 
Welcome to my MIIS/ILM Code Experiment!&nbsp; My name is Shawn Rabourn and I...]]></description>
      <content:encoded><![CDATA[<P mce_keep="true">&nbsp;</P>
<P>Hello!&nbsp; </P>
<P>Welcome to my MIIS/ILM Code Experiment!&nbsp; My name is Shawn Rabourn and I am in my seventh year at Microsoft and I currently work for Application Consulting and Engineering (ACE) Services as a Security Consultant.&nbsp; This Blog is in response to a lot of the feedback I was receiving from my Technet Blog, <A href="http://blogs.technet.com/shawnrab">http://blogs.technet.com/shawnrab</A> - I have been experimenting with a lot of different coding concepts in Microsoft Identity Integration Server&nbsp;and Identity Lifecycle Manager and much of it belongs outside of the TechNet space and more in the MSDN space.&nbsp; So, today I will be&nbsp;posting&nbsp;a few posts from my Technet Blog, making sure it is in the correct area.&nbsp;&nbsp;I&nbsp;also have&nbsp;a lot of scripts and samples that I have stored away for a rainy&nbsp;day that I will post here in the future.&nbsp; </P>
<P mce_keep="true">&nbsp;</P>
<P>&nbsp;--Shawn</P>
<P>This posting is provided "AS IS" with no warranties, and confers no rights.</P>
<P>And Just in case...</P>
<P><FONT size=0>This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.</FONT></P>]]></content:encoded>
    </item>
  </channel>
</rss>