%3CLINGO-SUB%20id%3D%22lingo-sub-974653%22%20slang%3D%22en-US%22%3ERules%20Extensions%20%E2%80%93%20MA%20Extension%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-974653%22%20slang%3D%22en-US%22%3E%0A%20%26lt%3Bmeta%20http-equiv%3D%22Content-Type%22%20content%3D%22text%2Fhtml%3B%20charset%3DUTF-8%22%20%2F%26gt%3B%3CSTRONG%3EFirst%20published%20on%20MSDN%20on%20Jun%2023%2C%202017%20%3C%2FSTRONG%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20The%20following%20is%20just%20an%20example%20of%20what%20an%20MA%20Extension%20would%20like%20like%20and%20should%20only%20be%20used%20as%20a%20reference%20on%20how%20to%20build%20your%20own%20MA%20Extension%2C%20I%20use%20this%20post%20as%20a%20reference%20for%20all%20my%20MA%20Extension%20Post%20which%20I%20have%20broken%20up%20into%20sections%20%3CBR%20%2F%3E%3CBLOCKQUOTE%3E%3CBR%20%2F%3E%3CH4%20id%3D%22toc-hId-1458549729%22%20id%3D%22toc-hId-1458696985%22%3E%3CA%20href%3D%22https%3A%2F%2Fblogs.msdn.microsoft.com%2Fconnector_space%2F2016%2F09%2F02%2Frules-extensions-shouldprojecttomv%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Rules%20Extensions%20%E2%80%93%20ShouldProjectToMV%20%3C%2FA%3E%3C%2FH4%3E%3CBR%20%2F%3E%3CH4%20id%3D%22toc-hId--1093607232%22%20id%3D%22toc-hId--1093459976%22%3E%3CA%20href%3D%22https%3A%2F%2Fblogs.msdn.microsoft.com%2Fconnector_space%2F2016%2F02%2F12%2Frules-extensions-mapattributesforimport%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Rules%20Extensions%20%E2%80%93%20MapAttributesForImport%20%3C%2FA%3E%3C%2FH4%3E%3CBR%20%2F%3E%3CH4%20id%3D%22toc-hId-649203103%22%20id%3D%22toc-hId-649350359%22%3E%3CA%20href%3D%22https%3A%2F%2Fblogs.msdn.microsoft.com%2Fconnector_space%2F2016%2F02%2F08%2Frules-extensions-mapattributesforjoin%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Rules%20Extensions%20%E2%80%93%20MapAttributesForJoin%20%3C%2FA%3E%3C%2FH4%3E%3CBR%20%2F%3E%3CH4%20id%3D%22toc-hId--1902953858%22%20id%3D%22toc-hId--1902806602%22%3E%3C%2FH4%3E%3CBR%20%2F%3E%3CH4%20id%3D%22toc-hId--160143523%22%20id%3D%22toc-hId--159996267%22%3E%3CA%20href%3D%22https%3A%2F%2Fblogs.msdn.microsoft.com%2Fconnector_space%2F2014%2F11%2F04%2F2-way-account-expires-rules-extension-modified-to-include-lastlogontimestamp-and-pwdlastset%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%202%20Way%20Account%20Expires%20Rules%20Extension%20%3C%2FA%3E%3C%2FH4%3E%3CBR%20%2F%3E%3C%2FBLOCKQUOTE%3E%3CBR%20%2F%3E%3CBLOCKQUOTE%3E%3CBR%20%2F%3E%20using%20System%3B%20%3CBR%20%2F%3E%20using%20Microsoft.MetadirectoryServices%3B%20%3CBR%20%2F%3E%20using%20System.Globalization%3B%20%3CBR%20%2F%3E%20using%20System.Security.Principal%3B%20%3CBR%20%2F%3E%20%2F%2F%20Date%20Changed%2023%20June%202017%20%3CBR%20%2F%3E%20namespace%20Mms_ManagementAgent_MAExtension%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%2F%20%3CSUMMARY%3E%20%3CBR%20%2F%3E%20%2F%2F%2F%20Summary%20description%20for%20MAExtensionObject.%20%3CBR%20%2F%3E%20%2F%2F%2F%20%3C%2FSUMMARY%3E%20%3CBR%20%2F%3E%20public%20class%20MAExtensionObject%20%3A%20IMASynchronization%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20const%20string%20FSP%20%3D%20%22foreignSecurityPrincipal%22%3B%20%3CBR%20%2F%3E%20const%20string%20ADMA1%20%3D%20%22Contoso%20ADMA%22%3B%20%3CBR%20%2F%3E%20const%20string%20ADMA2%20%3D%20%22Fabrikam%20ADMA%22%3B%20%3CBR%20%2F%3E%20const%20string%20ADMA3%20%3D%20%22Fabrikam%20SPMA%22%3B%20%3CBR%20%2F%3E%20public%20MAExtensionObject()%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20Add%20constructor%20logic%20here%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20void%20IMASynchronization.Initialize()%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20initialization%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20void%20IMASynchronization.Terminate()%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20termination%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%2F%2Fbool%20IMASynchronization.ShouldProjectToMV(CSEntry%20csentry%2C%20out%20string%20MVObjectType)%20%3CBR%20%2F%3E%20%2F%2F%7B%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20MVObjectType%20%3D%20%22foreignSecurityPrincipal%22%3B%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20bool%20ShouldProject%20%3D%20false%3B%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20if%20(csentry%5B%22whatever%22%5D.StringValue.Length%20%26gt%3B%3D%2030)%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%7B%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20ShouldProject%20%3D%20true%3B%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%7D%20%3CBR%20%2F%3E%20%2F%2F%26nbsp%3B%26nbsp%3B%26nbsp%3B%20return%20ShouldProject%3B%20%3CBR%20%2F%3E%20%2F%2F%7D%20%3CBR%20%2F%3E%20bool%20IMASynchronization.ShouldProjectToMV(CSEntry%20csentry%2C%20out%20string%20MVObjectType)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20string%20fsp%20%3D%20%22foreignSecurityPrincipal%22%3B%20%3CBR%20%2F%3E%20bool%20ShouldProject%20%3D%20false%3B%20%3CBR%20%2F%3E%20MVObjectType%20%3D%20null%3B%20%3CBR%20%2F%3E%20switch%20(csentry.MA.Name)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20case%20ADMA1%3A%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20MVObjectType%20%3D%20%22person%22%3B%20%3CBR%20%2F%3E%20ShouldProject%20%3D%20true%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20ADMA2%3A%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20MVObjectType%20%3D%20%22group%22%3B%20%3CBR%20%2F%3E%20ShouldProject%20%3D%20true%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20ADMA3%3A%20%3CBR%20%2F%3E%20switch%20(csentry.ObjectType)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20case%20FSP%3A%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20MVObjectType%20%3D%20fsp%3B%20%3CBR%20%2F%3E%20if%20(csentry%5B%22cn%22%5D.StringValue.Length%20%26gt%3B%3D%2030)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20ShouldProject%20%3D%20true%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20default%3A%20throw%20new%20EntryPointNotImplementedException()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20return%20ShouldProject%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20DeprovisionAction%20IMASynchronization.Deprovision(CSEntry%20csentry)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20Remove%20this%20throw%20statement%20if%20you%20implement%20this%20method%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20throw%20new%20EntryPointNotImplementedException()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20bool%20IMASynchronization.FilterForDisconnection(CSEntry%20csentry)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20connector%20filter%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20throw%20new%20EntryPointNotImplementedException()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20void%20IMASynchronization.MapAttributesForJoin(string%20FlowRuleName%2C%20CSEntry%20csentry%2C%20ref%20ValueCollection%20values)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20switch%20(FlowRuleName)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20case%20%22SPAccountName%22%3A%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20join%20mapping%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20values.Add(csentry%5B%22samAccountName%22%5D.StringValue.Replace(%22SP_%22%2C%20%22%22))%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22BuildAccountName%22%3A%20%3CBR%20%2F%3E%20if%20(csentry%5B%22accountName%22%5D.IsPresent)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20values.Add(csentry%5B%22accountName%22%5D.StringValue)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20if%20(csentry%5B%22firstName%22%5D.IsPresent%20%26amp%3B%26amp%3B%20csentry%5B%22lastName%22%5D.IsPresent)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20values.Add(csentry%5B%22firstName%22%5D.StringValue%20%2B%20%22.%22%20%2B%20csentry%5B%22lastName%22%5D.StringValue)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20bool%20IMASynchronization.ResolveJoinSearch(string%20joinCriteriaName%2C%20CSEntry%20csentry%2C%20MVEntry%5B%5D%20rgmventry%2C%20out%20int%20imventry%2C%20ref%20string%20MVObjectType)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20join%20resolution%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20throw%20new%20EntryPointNotImplementedException()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20void%20IMASynchronization.MapAttributesForImport(string%20FlowRuleName%2C%20CSEntry%20csentry%2C%20MVEntry%20mventry)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20string%20csAttrib%3B%20%3CBR%20%2F%3E%20string%20mvAttrib%3B%20%3CBR%20%2F%3E%20long%20dtInt%3B%20%3CBR%20%2F%3E%20string%20targetFormat%3B%20%3CBR%20%2F%3E%20string%20sourceFormat%3B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20your%20import%20attribute%20flow%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20switch%20(FlowRuleName)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20case%20%22getDate%22%3A%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22deprovisionDate%22%3B%20%3CBR%20%2F%3E%20if%20(mventry.ConnectedMAs%5BADMA1%5D.Connectors.Count%20%3D%3D%200)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20if%20(mventry%5BmvAttrib%5D.IsPresent%20%26amp%3B%26amp%3B%20!string.IsNullOrWhiteSpace(mvAttrib))%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20DateTime%20depoDate%3B%20%3CBR%20%2F%3E%20if%20(!DateTime.TryParse(mventry%5BmvAttrib%5D.Value%2C%20out%20depoDate))%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2Fmventry%20%5B%22deprovisionDate%22%5D.Value%20%3D%20DateTime.Now.AddDays(90).ToString(%22yyyy'-'MM'-'dd'T'HH'%3A'mm'%3A'ss'.000'%22)%3B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20DateTime.Now.AddDays(90).ToString(%22yyyy-MM-ddTHH%3Amm%3Ass.000%22)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20DateTime.Now.AddDays(90).ToString(%22yyyy-MM-ddTHH%3Amm%3Ass.000%22)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20DateTime.Now.AddDays(90).ToString(%22yyyy-MM-ddTHH%3Amm%3Ass.000%22)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22removeDate%22%3A%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22deprovisionDate%22%3B%20%3CBR%20%2F%3E%20if%20(mventry.ConnectedMAs%5BADMA1%5D.Connectors.Count%20%3D%3D%201)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20if%20(mventry%5BmvAttrib%5D.IsPresent)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Values.Clear()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22employeeEndDate%22%3A%20%3CBR%20%2F%3E%20csAttrib%20%3D%20%22accountExpires%22%3B%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22employeeEndDate%22%3B%20%3CBR%20%2F%3E%20dtInt%20%3D%20csentry%5BcsAttrib%5D.IntegerValue%3B%20%3CBR%20%2F%3E%20%2F%2FtargetFormat%20%3D%20%22yyyy'-'MM'-'dd'T'HH'%3A'mm'%3A'ss'.000'%22%3B%20%3CBR%20%2F%3E%20targetFormat%20%3D%20%22yyyy-MM-ddTHH%3Amm%3Ass.000%22%3B%20%3CBR%20%2F%3E%20%2F%2FtargetFormat%20%3D%20%22M%2Fd%2Fyyyy%20h%3Amm%20tt%22%3B%20%3CBR%20%2F%3E%20sourceFormat%20%3D%20string.Empty%3B%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dtInt%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat)%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22pwdLastSet%22%3A%20%3CBR%20%2F%3E%20csAttrib%20%3D%20%22pwdLastSet%22%3B%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22pwdLastSet%22%3B%20%3CBR%20%2F%3E%20dtInt%20%3D%20csentry%5BcsAttrib%5D.IntegerValue%3B%20%3CBR%20%2F%3E%20targetFormat%20%3D%20%22M%2Fd%2Fyyyy%20h%3Amm%20tt%22%3B%20%3CBR%20%2F%3E%20sourceFormat%20%3D%20string.Empty%3B%20%3B%20%3CBR%20%2F%3E%20if%20(csentry%5BcsAttrib%5D.IsPresent%20%26amp%3B%26amp%3B%20csentry%5BcsAttrib%5D.IntegerValue%20!%3D%200)%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dtInt%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat)%3B%20%3CBR%20%2F%3E%20%2F%2F%2Fmventry%5BmvAttrib%5D.Value%20%3D%20ConvertFileTimeToFimTimeStamp(csentry%5BcsAttrib%5D.IntegerValue)%3B%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Delete()%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22pwdExpires%22%3A%20%3CBR%20%2F%3E%20csAttrib%20%3D%20%22pwdLastSet%22%3B%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22pwdExpires%22%3B%20%3CBR%20%2F%3E%20dtInt%20%3D%20csentry%5BcsAttrib%5D.IntegerValue%3B%20%3CBR%20%2F%3E%20targetFormat%20%3D%20%22M%2Fd%2Fyyyy%20h%3Amm%20tt%22%3B%20%3CBR%20%2F%3E%20sourceFormat%20%3D%20string.Empty%3B%20%3CBR%20%2F%3E%20if%20(csentry%5BcsAttrib%5D.IsPresent%20%26amp%3B%26amp%3B%20csentry%5BcsAttrib%5D.IntegerValue%20!%3D%200)%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dtInt%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat%2C%20180)%3B%20%3CBR%20%2F%3E%20%2F%2F%2Fmventry%5BmvAttrib%5D.Value%20%3D%20ConvertFileTimeToFimTimeStamp(csentry%5BcsAttrib%5D.IntegerValue)%3B%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Delete()%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22lastLogonTimestamp%22%3A%20%3CBR%20%2F%3E%20csAttrib%20%3D%20%22lastLogonTimestamp%22%3B%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22lastLogonTimestamp%22%3B%20%3CBR%20%2F%3E%20dtInt%20%3D%20csentry%5BcsAttrib%5D.IntegerValue%3B%20%3CBR%20%2F%3E%20targetFormat%20%3D%20%22M%2Fd%2Fyyyy%20h%3Amm%20tt%22%3B%20%3CBR%20%2F%3E%20sourceFormat%20%3D%20string.Empty%3B%20%3CBR%20%2F%3E%20if%20(csentry%5BcsAttrib%5D.IsPresent%20%26amp%3B%26amp%3B%20csentry%5BcsAttrib%5D.IntegerValue%20!%3D%200)%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dtInt%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat)%3B%20%3CBR%20%2F%3E%20%2F%2Fmventry%5BmvAttrib%5D.Value%20%3D%20ConvertFileTimeToFimTimeStamp(csentry%5BcsAttrib%5D.IntegerValue)%3B%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Delete()%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22createdDate%22%3A%20%3CBR%20%2F%3E%20csAttrib%20%3D%20%22whenCreated%22%3B%20%3CBR%20%2F%3E%20mvAttrib%20%3D%20%22createDate%22%3B%20%3CBR%20%2F%3E%20string%20dateStr%20%3D%20csentry%5BcsAttrib%5D.StringValue%3B%20%3CBR%20%2F%3E%20targetFormat%20%3D%20%22M%2Fdd%2Fyyyy%20h%3Amm%3Ass%20tt%22%3B%20%3CBR%20%2F%3E%20sourceFormat%20%3D%20%22yyyyMMddHHmmss.0Z%22%3B%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dateStr%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat)%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20case%20%22objectSidString%22%3A%20%3CBR%20%2F%3E%20string%20objectSidString%20%3D%20ConvertSidToString(csentry%5B%22objectSid%22%5D.BinaryValue)%3B%20%3CBR%20%2F%3E%20mventry%5B%22objectSidSTring%22%5D.StringValue%20%3D%20objectSidString%3B%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20void%20IMASynchronization.MapAttributesForExport(string%20FlowRuleName%2C%20MVEntry%20mventry%2C%20CSEntry%20csentry)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20your%20export%20attribute%20flow%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20%2F%2F%20TODO%3A%20write%20your%20export%20attribute%20flow%20code%20%3CBR%20%2F%3E%20%2F%2F%20%3CBR%20%2F%3E%20switch%20(FlowRuleName)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20case%20%22accountExpires%22%3A%20%3CBR%20%2F%3E%20CultureInfo%20provider%20%3D%20CultureInfo.InvariantCulture%3B%20%3CBR%20%2F%3E%20if%20(mventry%5B%22employeeEndDate%22%5D.ToString()%20!%3D%20%22%22)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2FDateTime%20dtFileTime%20%3D%20DateTime.ParseExact(mventry%5B%22employeeEndDate%22%5D.Value%2C%20%22yyyy'-'MM'-'dd'T'HH'%3A'mm'%3A'ss'.000'%22%2C%20provider)%3B%20%3CBR%20%2F%3E%20DateTime%20dtFileTime%20%3D%20DateTime.Parse(mventry%5B%22employeeEndDate%22%5D.Value%2C%20provider)%3B%20%3CBR%20%2F%3E%20csentry%5B%22accountExpires%22%5D.IntegerValue%20%3D%20dtFileTime.ToFileTime()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20csentry%5B%22accountExpires%22%5D.Value%20%3D%20%229223372036854775807%22%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20break%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%23region%20helper%20functions%20%3CBR%20%2F%3E%20private%20static%20void%20GetDateString(CSEntry%20csentry%2C%20MVEntry%20mventry%2C%20long%20dtInt%2C%20string%20mvAttrib%2C%20string%20sourceFormat%2C%20string%20targetFormat%2C%20int%20days%20%3D%200)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20if%20(dtInt%20%3D%3D%200%20%7C%7C%20dtInt%20%3D%3D%209223372036854775807)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20This%20is%20a%20special%20condition%2C%20do%20not%20contribute%20and%20delete%20any%20current%20value%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Delete()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20DateTime%20dtFileTime%20%3D%20DateTime.FromFileTime(dtInt).AddDays(days)%3B%20%3CBR%20%2F%3E%20if%20(targetFormat.Equals(%22LONG%22%2C%20StringComparison.OrdinalIgnoreCase))%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20dtFileTime.ToLongDateString()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20if%20(targetFormat.Equals(%22SHORT%22%2C%20StringComparison.OrdinalIgnoreCase))%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20dtFileTime.ToShortDateString()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20else%20%3CBR%20%2F%3E%20mventry%5BmvAttrib%5D.Value%20%3D%20dtFileTime.ToString(targetFormat)%3B%20%3CBR%20%2F%3E%20%2F%2F%20mventry%5BmvAttrib%5D.Value%20%3D%20DateTime.FromFileTimeUtc(dtInt).ToString(targetFormat)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%2F%2F(CSEntry%20csentry%2C%20MVEntry%20mventry%2C%20long%20dtInt%2C%20string%20mvAttrib%2C%20string%20targetFormat%2C%20int%20days%20%3D%200)%20%3CBR%20%2F%3E%20private%20static%20void%20GetDateString(CSEntry%20csentry%2C%20MVEntry%20mventry%2C%20string%20dateStr%2C%20string%20mvAttrib%2C%20string%20sourceFormat%2C%20string%20targetFormat%2C%20int%20days%20%3D%200)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20DateTime%20dt%20%3D%20DateTime.ParseExact(dateStr%2C%20sourceFormat%2C%20CultureInfo.InvariantCulture)%3B%20%3CBR%20%2F%3E%20GetDateString(csentry%2C%20mventry%2C%20dt.ToFileTime()%2C%20mvAttrib%2C%20sourceFormat%2C%20targetFormat%2C%20days)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20private%20static%20string%20ConvertFileTimeToFimTimeStamp(long%20fileTime)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20return%20DateTime.FromFileTimeUtc(fileTime).ToString(%22yyyy-MM-ddTHH%3Amm%3Ass.000%22)%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20private%20static%20string%20ConvertSidToString(byte%5B%5D%20objectSid)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20string%20objectSidString%20%3D%20%22%22%3B%20%3CBR%20%2F%3E%20SecurityIdentifier%20SI%20%3D%20new%20SecurityIdentifier(objectSid%2C%200)%3B%20%3CBR%20%2F%3E%20objectSidString%20%3D%20SI.ToString()%3B%20%3CBR%20%2F%3E%20return%20objectSidString%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%23endregion%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%7D%3C%2FBLOCKQUOTE%3E%0A%20%0A%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-974653%22%20slang%3D%22en-US%22%3EFirst%20published%20on%20MSDN%20on%20Jun%2023%2C%202017%20%26nbsp%3BThe%20following%20is%20just%20an%20example%20of%20what%20an%20MA%20Extension%20would%20like%20like%20and%20should%20only%20be%20used%20as%20a%20reference%20on%20how%20to%20build%20your%20own%20MA%20Extension%2C%20I%20use%20this%20post%20as%20a%20reference%20for%20all%20my%20MA%20Extension%20Post%20which%20I%20have%20broken%20up%20into%20sectionsRules%20Extensions%20%E2%80%93%20ShouldProjectToMVRules%20Extensions%20%E2%80%93%20MapAttributesForImportRules%20Extensions%20%E2%80%93%20MapAttributesForJoin2%20Way%20Account%20Expires%20Rules%20Extension%26nbsp%3Busing%20System%3Busing%20Microsoft.%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-974653%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3Emaextension%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Erules%20extension%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Erules%20extensions%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft
First published on MSDN on Jun 23, 2017

The following is just an example of what an MA Extension would like like and should only be used as a reference on how to build your own MA Extension, I use this post as a reference for all my MA Extension Post which I have broken up into sections

Rules Extensions – ShouldProjectToMV


Rules Extensions – MapAttributesForImport


Rules Extensions – MapAttributesForJoin



2 Way Account Expires Rules Extension




using System;
using Microsoft.MetadirectoryServices;
using System.Globalization;
using System.Security.Principal;
// Date Changed 23 June 2017
namespace Mms_ManagementAgent_MAExtension
{
/// <summary>
/// Summary description for MAExtensionObject.
/// </summary>
public class MAExtensionObject : IMASynchronization
{
const string FSP = "foreignSecurityPrincipal";
const string ADMA1 = "Contoso ADMA";
const string ADMA2 = "Fabrikam ADMA";
const string ADMA3 = "Fabrikam SPMA";
public MAExtensionObject()
{
//
// TODO: Add constructor logic here
//
}
void IMASynchronization.Initialize()
{
//
// TODO: write initialization code
//
}
void IMASynchronization.Terminate()
{
//
// TODO: write termination code
//
}
//bool IMASynchronization.ShouldProjectToMV(CSEntry csentry, out string MVObjectType)
//{
//    MVObjectType = "foreignSecurityPrincipal";
//    bool ShouldProject = false;
//    if (csentry["whatever"].StringValue.Length >= 30)
//    {
//        ShouldProject = true;
//    }
//    return ShouldProject;
//}
bool IMASynchronization.ShouldProjectToMV(CSEntry csentry, out string MVObjectType)
{
string fsp = "foreignSecurityPrincipal";
bool ShouldProject = false;
MVObjectType = null;
switch (csentry.MA.Name)
{
case ADMA1:
{
MVObjectType = "person";
ShouldProject = true;
}
break;
case ADMA2:
{
MVObjectType = "group";
ShouldProject = true;
}
break;
case ADMA3:
switch (csentry.ObjectType)
{
case FSP:
{
MVObjectType = fsp;
if (csentry["cn"].StringValue.Length >= 30)
{
ShouldProject = true;
}
}
break;
}
break;
default: throw new EntryPointNotImplementedException();
}
return ShouldProject;
}
DeprovisionAction IMASynchronization.Deprovision(CSEntry csentry)
{
//
// TODO: Remove this throw statement if you implement this method
//
throw new EntryPointNotImplementedException();
}
bool IMASynchronization.FilterForDisconnection(CSEntry csentry)
{
//
// TODO: write connector filter code
//
throw new EntryPointNotImplementedException();
}
void IMASynchronization.MapAttributesForJoin(string FlowRuleName, CSEntry csentry, ref ValueCollection values)
{
switch (FlowRuleName)
{
case "SPAccountName":
//
// TODO: write join mapping code
//
values.Add(csentry["samAccountName"].StringValue.Replace("SP_", ""));
break;
case "BuildAccountName":
if (csentry["accountName"].IsPresent)
{
values.Add(csentry["accountName"].StringValue);
}
else if (csentry["firstName"].IsPresent && csentry["lastName"].IsPresent)
{
values.Add(csentry["firstName"].StringValue + "." + csentry["lastName"].StringValue);
}
break;
}
}
bool IMASynchronization.ResolveJoinSearch(string joinCriteriaName, CSEntry csentry, MVEntry[] rgmventry, out int imventry, ref string MVObjectType)
{
//
// TODO: write join resolution code
//
throw new EntryPointNotImplementedException();
}
void IMASynchronization.MapAttributesForImport(string FlowRuleName, CSEntry csentry, MVEntry mventry)
{
string csAttrib;
string mvAttrib;
long dtInt;
string targetFormat;
string sourceFormat;
//
// TODO: write your import attribute flow code
//
switch (FlowRuleName)
{
case "getDate":
mvAttrib = "deprovisionDate";
if (mventry.ConnectedMAs[ADMA1].Connectors.Count == 0)
{
if (mventry[mvAttrib].IsPresent && !string.IsNullOrWhiteSpace(mvAttrib))
{
DateTime depoDate;
if (!DateTime.TryParse(mventry[mvAttrib].Value, out depoDate))
{
//mventry ["deprovisionDate"].Value = DateTime.Now.AddDays(90).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000'");
mventry[mvAttrib].Value = DateTime.Now.AddDays(90).ToString("yyyy-MM-ddTHH:mm:ss.000");
}
else
{
mventry[mvAttrib].Value = DateTime.Now.AddDays(90).ToString("yyyy-MM-ddTHH:mm:ss.000");
}
}
else
{
mventry[mvAttrib].Value = DateTime.Now.AddDays(90).ToString("yyyy-MM-ddTHH:mm:ss.000");
}
}
break;
case "removeDate":
mvAttrib = "deprovisionDate";
if (mventry.ConnectedMAs[ADMA1].Connectors.Count == 1)
{
if (mventry[mvAttrib].IsPresent)
{
mventry[mvAttrib].Values.Clear();
}
}
break;
case "employeeEndDate":
csAttrib = "accountExpires";
mvAttrib = "employeeEndDate";
dtInt = csentry[csAttrib].IntegerValue;
//targetFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000'";
targetFormat = "yyyy-MM-ddTHH:mm:ss.000";
//targetFormat = "M/d/yyyy h:mm tt";
sourceFormat = string.Empty;
GetDateString(csentry, mventry, dtInt, mvAttrib, sourceFormat, targetFormat);
break;
case "pwdLastSet":
csAttrib = "pwdLastSet";
mvAttrib = "pwdLastSet";
dtInt = csentry[csAttrib].IntegerValue;
targetFormat = "M/d/yyyy h:mm tt";
sourceFormat = string.Empty; ;
if (csentry[csAttrib].IsPresent && csentry[csAttrib].IntegerValue != 0)
GetDateString(csentry, mventry, dtInt, mvAttrib, sourceFormat, targetFormat);
///mventry[mvAttrib].Value = ConvertFileTimeToFimTimeStamp(csentry[csAttrib].IntegerValue);
else
mventry[mvAttrib].Delete();
break;
case "pwdExpires":
csAttrib = "pwdLastSet";
mvAttrib = "pwdExpires";
dtInt = csentry[csAttrib].IntegerValue;
targetFormat = "M/d/yyyy h:mm tt";
sourceFormat = string.Empty;
if (csentry[csAttrib].IsPresent && csentry[csAttrib].IntegerValue != 0)
GetDateString(csentry, mventry, dtInt, mvAttrib, sourceFormat, targetFormat, 180);
///mventry[mvAttrib].Value = ConvertFileTimeToFimTimeStamp(csentry[csAttrib].IntegerValue);
else
mventry[mvAttrib].Delete();
break;
case "lastLogonTimestamp":
csAttrib = "lastLogonTimestamp";
mvAttrib = "lastLogonTimestamp";
dtInt = csentry[csAttrib].IntegerValue;
targetFormat = "M/d/yyyy h:mm tt";
sourceFormat = string.Empty;
if (csentry[csAttrib].IsPresent && csentry[csAttrib].IntegerValue != 0)
GetDateString(csentry, mventry, dtInt, mvAttrib, sourceFormat, targetFormat);
//mventry[mvAttrib].Value = ConvertFileTimeToFimTimeStamp(csentry[csAttrib].IntegerValue);
else
mventry[mvAttrib].Delete();
break;
case "createdDate":
csAttrib = "whenCreated";
mvAttrib = "createDate";
string dateStr = csentry[csAttrib].StringValue;
targetFormat = "M/dd/yyyy h:mm:ss tt";
sourceFormat = "yyyyMMddHHmmss.0Z";
GetDateString(csentry, mventry, dateStr, mvAttrib, sourceFormat, targetFormat);
break;
case "objectSidString":
string objectSidString = ConvertSidToString(csentry["objectSid"].BinaryValue);
mventry["objectSidSTring"].StringValue = objectSidString;
break;
}
}

void IMASynchronization.MapAttributesForExport(string FlowRuleName, MVEntry mventry, CSEntry csentry)
{
//
// TODO: write your export attribute flow code
//
//
// TODO: write your export attribute flow code
//
switch (FlowRuleName)
{
case "accountExpires":
CultureInfo provider = CultureInfo.InvariantCulture;
if (mventry["employeeEndDate"].ToString() != "")
{
//DateTime dtFileTime = DateTime.ParseExact(mventry["employeeEndDate"].Value, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000'", provider);
DateTime dtFileTime = DateTime.Parse(mventry["employeeEndDate"].Value, provider);
csentry["accountExpires"].IntegerValue = dtFileTime.ToFileTime();
}
else
{
csentry["accountExpires"].Value = "9223372036854775807";
}
break;
}
}
#region helper functions
private static void GetDateString(CSEntry csentry, MVEntry mventry, long dtInt, string mvAttrib, string sourceFormat, string targetFormat, int days = 0)
{
if (dtInt == 0 || dtInt == 9223372036854775807)
{
// This is a special condition, do not contribute and delete any current value
mventry[mvAttrib].Delete();
}
else
{
DateTime dtFileTime = DateTime.FromFileTime(dtInt).AddDays(days);
if (targetFormat.Equals("LONG", StringComparison.OrdinalIgnoreCase))
{
mventry[mvAttrib].Value = dtFileTime.ToLongDateString();
}
else if (targetFormat.Equals("SHORT", StringComparison.OrdinalIgnoreCase))
{
mventry[mvAttrib].Value = dtFileTime.ToShortDateString();
}
else
mventry[mvAttrib].Value = dtFileTime.ToString(targetFormat);
// mventry[mvAttrib].Value = DateTime.FromFileTimeUtc(dtInt).ToString(targetFormat);
}
}
//(CSEntry csentry, MVEntry mventry, long dtInt, string mvAttrib, string targetFormat, int days = 0)
private static void GetDateString(CSEntry csentry, MVEntry mventry, string dateStr, string mvAttrib, string sourceFormat, string targetFormat, int days = 0)
{
DateTime dt = DateTime.ParseExact(dateStr, sourceFormat, CultureInfo.InvariantCulture);
GetDateString(csentry, mventry, dt.ToFileTime(), mvAttrib, sourceFormat, targetFormat, days);
}

private static string ConvertFileTimeToFimTimeStamp(long fileTime)
{
return DateTime.FromFileTimeUtc(fileTime).ToString("yyyy-MM-ddTHH:mm:ss.000");
}
private static string ConvertSidToString(byte[] objectSid)
{
string objectSidString = "";
SecurityIdentifier SI = new SecurityIdentifier(objectSid, 0);
objectSidString = SI.ToString();
return objectSidString;
}
#endregion
}
}