Dynamically build an object based on another object and a string

Yeah, I know - that’s a very odd title. Not sure how to explain it succinctly. :slight_smile:

Anyway, I have an issue that I’m struggling with. I have an open ticket with Microsoft regarding some breaking changes that I’ve found with Windows Server 2012 R2. I’m not optimistic that they’ll be able to solve it, so I’m going to approach the idea from a different angle. It’s past my knowledge, though, so I could use some help.

In short, I’m having problems with a PowerShell script that uses the SharePoint Client Side Object Model (CSOM). To do CSOM, you need to get a context object and then explicitly load any collections or properties which aren’t populated by default. For example, to load up the list of subsites in a site, you would do something like this:

    $ctx.Load($ctx.Web.Webs)
    $ctx.ExecuteQuery()

That will then populate $ctx.Web.Webs.

The function that I have takes $ctx and $ctx.Web.Webs as parameters. The breaking change (or so it seems) is that the function will evaluate $ctx.Web.Webs at call time and fail (because it hasn’t been loaded yet), whereas on non-2012-R2 it works perfectly fine. So I’m thinking of another way to do it.

I’m thinking one way to solve the issue would be to go ahead and pass in the $ctx object but then instead of having the object as the second parameter I instead have a string. So instead of calling

Load-CSOMObject –context $ctx –object $ctx.Web.Webs
I’d call
Load-CSOMObject –context $ctx –objectString “Web.Webs”
. Then, inside the function I’d need to build the equivalent of $ctx.Web.Webs using $ctx and “Web.Webs”. However, I have no idea whether or not this is possible. Does anyone know if it’s possible to dynamically build a an object that references a property or collection in another object using a string? Something like
$object = $ctx[$objectString]
or
$object = $ctx.$objectString
?

Thanks, everyone, for the help. I know this is a weird question. :slight_smile:

Brian

I’m not sure how dynamically attempting to build the object is going to get you anything if the properties simply aren’t available. You’ve mentioned that it has not loaded yet, which insinuates that it’s a timing issue and eventually is populated. Have you tried performing a sleep before the load to see if works? if you added a 30 second sleep and it works, you could write a while loop to validate that ctx is not null before calling methods.

Yeah, the idea doesn’t make a lot of sense considering how PowerShell normally works. However, I’m trying to work around what I think is a bug that I’ve found on Windows Server 2012 R2. I have a case open with MS right now regarding it.

Unfortunately, it’s not something that a Start-Sleep will resolve. It’s a matter of how the SharePoint CSOM populates its objects. You have to explicitly load the object and execute a query in order to get it populated. My function takes the base context object and takes the object I want to load (a property or collection in that context object) and does the load/execute to populate it. It’s got retry logic and the like, hence the use of a function. If I don’t use the function and just do the load/execute inline with the calling code, it works just fine. It’s not an issue with the loading/executing per se. Instead, the issue appears to be PowerShell (again, only on 2012 R2) throwing a critical error when attempting to pass that non-initialized object in the function call. The error that’s return is the same error that you would get if you tried to access the property directly (“The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.”). Again, it’s doing a kind of early validation/evaluation of the object when it’s done in 2012 R2 that either doesn’t happen in previous Windows or doesn’t result in a fatal error.

So I was thinking that I could perhaps avoid this early evaluation by finding some way to not pass the object in the function call. Passing the context object is fine. That’s why I was thinking of instead passing a string description of the property/collection that I want to load and then build that object inside the function. It’s a funky workaround, but something like that might be my only way of working around the issue.

Thanks for your feedback, Rob!

there is a way to build an object by property ‘path’ but it’s tricky.

There is idea how it could be done (I use VMware cli for example of object with deep needed property path)

in the -end you get your needed property in $obj