lithnet / resourcemanagement-powershell

Lithnet FIM/MIM Service PowerShell Module
MIT License
37 stars 12 forks source link

The given key was not present in the dictionary #9

Closed MWOITC closed 7 years ago

MWOITC commented 7 years ago

I've got a PowerShell script which gets triggered when users enter a set. The script uses the lithnet rma module (this is the first script I'm, using it for) and needs to look up a 'person' object by objected.

I have used: Get-Resource -ID $ID Get-Resource -ID $ID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName Search-Resources -Xpath "/Person[(ObjectID = '$ID')]" -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName

but always get mixed results as in: not all object are found (34 in total). With a number of them (and this number varies) I get the following error "The given key was not present in the dictionary".

If I run the script from the command line and use a list of objectids as input, I don't get any errors (not with my own account or the account used within MIM). Issue only seems to happen when the script gets run from a workflow.

ryannewington commented 7 years ago

I haven't done much from workflows myself, but I know the workflow engine uses .NET 3.5, whereas the LithnetRMA module requires .NET 4.0. However, I wouldn't have exepected the module to even be able to load in that context. Did you do something to be able to load the .net 4 code?

If you could print the output of

$error[0].Exception.ToString()

after that error, it might give me some clues as to what is going on

MWOITC commented 7 years ago

Thanks for the reply Ryan. Yes - I have modified the MIM config file to allow for .Net 4 support, primarily to see if I could use the Lithnet modules instead of the MS FImAutomation modules. So the short of it is that it works but the results seem to be a bit unpredictable. The set I'm using only has 34 members and I might get 80% success on the 'get-resource' command and 20% fails. The failed ObjectIDs are not always the same.

Have run the workflow again and added your 'line' to my script. Results are as follows:

If I use: Get-Resource -ID $UserID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName I can see the following error:

System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
   at System.ThrowHelper.ThrowKeyNotFoundException()
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Lithnet.ResourceManagement.Client.ResourceObject.PopulateResourceFromPartialResponse(IEnumerable`1 objectElements)
   at Lithnet.ResourceManagement.Client.ResourceObject..ctor(IEnumerable`1 objectElements, ResourceManagementClient client, CultureInfo locale)
   at Lithnet.ResourceManagement.Client.ResourceManagementService.ResourceClient.Get(UniqueIdentifier id, IEnumerable`1 attributes, CultureInfo locale)
   at Lithnet.ResourceManagement.Client.ResourceManagementClient.GetResource(UniqueIdentifier id, IEnumerable`1 attributesToGet, CultureInfo locale)
   at Lithnet.ResourceManagement.Client.ResourceManagementClient.GetResource(String id, IEnumerable`1 attributesToGet, CultureInfo locale)
   at Lithnet.ResourceManagement.Automation.GetResource.ProcessRecord() in D:\github\lithnet\resourcemanagement-powershell\src\Lithnet.ResourceManagement.Automation\GetResource.cs:line 85
   at System.Management.Automation.CommandProcessor.ProcessRecord()

If I use:

Get-Resource -ObjectType "Person" -AttributeName ObjectID -AttributeValue $UserID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName
I
``` can see the following error:
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
   at System.ThrowHelper.ThrowKeyNotFoundException()
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Lithnet.ResourceManagement.Client.ResourceObject.PopulateResourceFromFragment(XmlElement element)
   at Lithnet.ResourceManagement.Client.ResourceObject..ctor(XmlElement element, ResourceManagementClient client, CultureInfo locale)
   at Lithnet.ResourceManagement.Client.SearchResultPager.<EnumerateResultSet>d__19.MoveNext()
   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
   at Lithnet.ResourceManagement.Client.SearchResultCollection.GetNextPage()
   at Lithnet.ResourceManagement.Client.SearchResultCollection.GetObjectAtIndex(Int32 index)
   at Lithnet.ResourceManagement.Client.SearchResultEnumerator.get_Current()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at Lithnet.ResourceManagement.Client.ResourceManagementClient.GetResourceByKey(String objectType, Dictionary`2 attributeValuePairs, IEnumerable`1 attributesToGet, CultureInfo locale)
   at Lithnet.ResourceManagement.Client.ResourceManagementClient.GetResourceByKey(String objectType, String attributeName, Object value, IEnumerable`1 attributesToGet, CultureInfo locale)
   at Lithnet.ResourceManagement.Automation.GetResource.ProcessRecord() in D:\github\lithnet\resourcemanagement-powershell\src\Lithnet.ResourceManagement.Automation\GetResource.cs:line 125
   at System.Management.Automation.CommandProcessor.ProcessRecord()

Thanks,
ryannewington commented 7 years ago

I have a suspicion I know what is going on. There could be a race condition taking place. Can you send me the whole script, including the part where you initialize the connection using Set-ResourceManagementClient.

I suspect this is happening when multiple workflows are running simultaneously? Have you seen it happen when only a single workflow instance is triggered?

ryannewington commented 7 years ago

Can you give this build a try?

Lithnet.ResourceManagement.Automation.msi.zip

MWOITC commented 7 years ago

Hi Ryan, thanks for the quick reply over the weekend. Just tested the new DLL and this time it errors out straightaway.

If I use $TargetUser = Get-Resource -ID $TargetID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName

I get the following error: System.TypeInitializationException: The type initializer for 'Lithnet.ResourceManagement.Client.ResourceManagementClient' threw an exception. ---> System.InvalidOperationException: This operation is not supported for a relative URI. at System.Uri.get_Fragment() at System.UriBuilder.Init(Uri uri) at Lithnet.ResourceManagement.Client.EndpointManager..ctor(Uri baseUri, EndpointIdentity spn) at Lithnet.ResourceManagement.Client.ResourceManagementClient.InitialResourceManagementClientDefaults() at Lithnet.ResourceManagement.Client.ResourceManagementClient..cctor() --- End of inner exception stack trace --- at Lithnet.ResourceManagement.Client.ResourceManagementClient..ctor() at Lithnet.ResourceManagement.Automation.RmcWrapper.get_Client() in D:\github\lithnet\resourcemanagement-powershell\src\Lithnet.ResourceManagement.Automation\RmcWrapper.cs:line 23 at Lithnet.ResourceManagement.Automation.GetResource.ProcessRecord() in D:\github\lithnet\resourcemanagement-powershell\src\Lithnet.ResourceManagement.Automation\GetResource.cs:line 85 at System.Management.Automation.CommandProcessor.ProcessRecord()

I have attached the script I’m using in the workflow. As you can see it is as simple as can be – just wanted to see if I can get all users entering a set (in my case only 34). Once that works I can start expanding the script with updating settings etc.

Cheers Mike

From: Ryan Newington [mailto:notifications@github.com] Sent: Sunday, 13 August 2017 10:06 PM To: lithnet/resourcemanagement-powershell resourcemanagement-powershell@noreply.github.com Cc: Mike Wieggers OITC mike.wieggers@orange-itc.com; Author author@noreply.github.com Subject: Re: [lithnet/resourcemanagement-powershell] The given key was not present in the dictionary (#9)

Can you give this build a try?

Lithnet.ResourceManagement.Automation.msi.ziphttps://github.com/lithnet/resourcemanagement-powershell/files/1220451/Lithnet.ResourceManagement.Automation.msi.zip

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/lithnet/resourcemanagement-powershell/issues/9#issuecomment-322039532, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AM0i3NV6ngJ6xsO5FYJwnvhcZC5lv-ewks5sXu2YgaJpZM4O0P9F.

<#

Script Name: WF_BasicSettings

Description: ??

Author: Company:

Revision History: dd/mm/yy 0.2 INITIALS What changed dd/mm/yy 0.1 INITIALS Initial Release

>

Set location for scripts folder.

$ScriptsFolder = "C:\MIM" Set-Location -Path $ScriptsFolder

Include Custom PowerShell libary.

. $ScriptsFolder\MIMLibrary.ps1

Load configuration settings.

LoadConfig -ConfigFile "$ScriptsFolder\MIM.config"

Load the Lithnet MIM PowerShell Module.

Import-Module LithnetRMA

Connect to the MIM service instance.

Set-ResourceManagementClient -BaseAddress http://localhost:5725

$Error.clear()

TargetID would be something like "b3be567e-269b-43d9-ad79-ae4d2e32ede9"

$TargetID = ($fimwf.TargetId.Guid).ToString()

Get target user.

$TargetUser = Get-Resource -ID $TargetID

$TargetUser = Get-Resource -ID $TargetID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName

$TargetUser = Get-Resource -ObjectType "Person" -AttributeName ObjectID -AttributeValue $TargetID -AttributesToGet ObjectID,AccountName,TargetOU,FirstName,LastName

$error[0].Exception.ToString() >> c:\temp\ryan.txt

$targetUser >> c:\temp\userinfo.txt

exit

ryannewington commented 7 years ago

This is coming from a different section of code. It's trying to load the default <resourceManagementClient> section from the relevant web.config file and not liking something that is in there. Can you send me a copy of that section?

MWOITC commented 7 years ago

Sure, see attached. web.zip

Thanks

ryannewington commented 7 years ago

Workflow might be executing in the context of the fim service. Can you send me the ResourceManagementService.exe.config file?

MWOITC commented 7 years ago

Microsoft.ResourceManagement.Service.zip

ryannewington commented 7 years ago

Ok I think the problem is that we are expecting a URL in this field

<resourceManagementClient resourceManagementServiceBaseAddress="idmportal" />

Now, if FIM is ok with this, we should be too, and I'll go ahead and fix it, but can you try change it to

<resourceManagementClient resourceManagementServiceBaseAddress="http://idmportal:5725" />

just to prove that is what the problem is

MWOITC commented 7 years ago

HI Ryan, I changed the Microsoft.ResourceManagement.Service.exe.config to

and now get no errors and a 100% score on retrieving user information for the 34 users entering the test set.

The line

in the Microsoft.ResourceManagement.Service.exe.config is generated by MM at install time so it is not something I manually changed.

ryannewington commented 7 years ago

Excellent. I'll update the logic to accept a hostname only in that section.

You should be able to drop the Set-ResourceManagementClient line from your powershell. It's making the connection using the information in the app.config file (which was why this new problem appeared). Using it will just be destroying that connection and re-setting up this connection every time.

This was actually the source of the problem originally. Set-ResourceManagementClient would FORCE a schema refresh (a very expensive operation on its own). Because the schema code was not thread safe, the schema was in the middle of being updated while another client on another thread was trying to read it (then you get the key not found error).

I've made Set-ResourceManagementClient not force the schema refresh (there is a -RefreshSchema switch on the cmdlet now to do that). The change to the schema code is unfortunately a breaking change for consumers of the rmc library. I'll publish the details about this soon.

Thanks for working through this one with me

MWOITC commented 7 years ago

Great, did some more testing: based on that.

Will for now leave the Microsoft.ResourceManagement.Service.exe.config running with the modified clientbase address setting.

Happy to help and to test once you've got a new release.

Cheers

ryannewington commented 7 years ago

Could I trouble you to test this final build before I release it?

Lithnet.ResourceManagement.Automation.msi.zip

MWOITC commented 7 years ago

Doing it now

MWOITC commented 7 years ago

Success! Before starting the test I changed 'Microsoft.ResourceManagement.Service.exe.config' back to its original (ie 'resourceManagementClient resourceManagementServiceBaseAddress="idmportal") and ran the test again. 34 users in the set, 34 users found by 'get-resource'.

Running it now on a different MIM setup as well. Will keep you posted.

MWOITC commented 7 years ago

2nd test on different MIM setup and script(s) work. :)

ryannewington commented 7 years ago

Brilliant. Thanks Mike! I'll publish the new version now

ryannewington commented 7 years ago

Fixed in https://github.com/lithnet/resourcemanagement-powershell/releases/tag/v1.0.6435