Objects returned by Get-SPOSite - powershell

Where can I find detailed documentation for the properties of the objects returned by Get-SPOSite in PowerShell? According to the type information header created by Export-Csv, they are of type Microsoft.Online.SharePoint.PowerShell.SPOSite. I'm looking specifically for information on the meaning of each of the properties.

It's good practice to use debug tool(I use PowerGUI Script Editor for PowerShell Script debug) to check the object usually.

Related

PowerShell - Passing OBJECTS to start-job - deserialize

I know that a script block executed via start-job cannot see the variables outside of the script block. To pass variables in you use the -arguments paramater. From the doco I've read though, jobs can't pass objects to each other without serialising them. Apparently this is because of how jobs works - when using Start-job, PowerShell creates a new process and runs the commands there; in order to transfer the object to the other process it needs to serialise it, then the other exe will deserialise it when it gets imported. This poses a problem when you want to use objects with start-job.
NOTE: The below are examples to demonstrate my problem - the actual cmdlets and scripts I am running are completely different and more complex, so in case you are wondering why I would even run these commands this way just bear in mind I wouldn't, they are just easy commands to demonstrate my issue.
Here is an example of the syntax I've used for a simple Get-aduser command
$user = get-aduser samaccount
When we output $user we see that the object is of type ADUser
$user|GM
TypeName: Microsoft.ActiveDirectory.Management.ADUser
Let's now serialise the object (to simulate what start-job does)
$user| Export-Clixml C:\temp\test.xml
And now rebuild it (deserialise)
$user = Import-Clixml C:\temp\test.xml
Now when when we view it's type it is different. It has the word 'derserialzed' in front.
$user|GM
TypeName: Deserialized.Microsoft.ActiveDirectory.Management.ADUser
The problem I now have is that it isn't a true representation of the orignal object. Even if all the properties and settings were identical we still have the problem that the object type is different. Now to demonstrate why this is a problem.
Get-aduser accepts a string as the input (very first example) but it also will accept a valid ADuser object. But when we now run:
get-aduser $user
We get the following error:
"Cannot convert the "AD_distinguishedname_here. I have omitted this for security reasons" value of type
"Deserialized.Microsoft.ActiveDirectory.Management.ADUser" to type "Microsoft.ActiveDirectory.Management.ADUser"."
This error is because Get-aduser expects you to provide an object of type Microsoft.ActiveDirectory.Management.ADUser but we provided Deserialized.Microsoft.ActiveDirectory.Management.ADUserand it doesn't know how to convert it. This is exactly what happens when you run command via start-job and why you can't pass objects to a job.
As I said above, I am not using get-aduser in my real code, I am just using this simple command everyone has access to, to demonstrate the issue. In my real code I must provide an object to the job.
So my question is, does anyone know how you get around this or know how to rebuild the object in it's original form?
After spending 8 hours on this straight I finally figured out what is going on. It's a long story but thr TLDR version is that you cannot get around this with any native tools - you have to essentially rebuild the object inside the start-job script block, and if you have a large complex object this just isn't feasible. I ended up findind a module you can download which runs commands via start-thread instead of the start-job and this does not use serialisation. Guide here to DL and install it. This worked when I tested it
To get the PowerShell module, go to PowerShell gallery and search for "start-thread"

How do I pass all parameters between cmdlets easily?

Using CmdletBinding, is there an easy way to regurgitate the exact parameters that a cmdlet was called with, so I can call another cmdlet with the exact same parameters?
I'm writing Powershell Cmdlets in Powershell. I'm using advanced functions. I have a cmdlet called Get-Environment, with several optional parameters like [string]EnvironmentName and [switch]Active. I have another cmdlet, called Get-Machine, with all of the same optional parameters; it calls Get-Environment. Originally, before I added the [switch]Active parameter, I simply called Get-Environment with all variables explicitly (see below).
I can't do the same thing now, because if I add "active" then it will be set. I don't want to have make a test in Get-Machine to see if Active is true and have two different versions of the Get-Environment call. I'd prefer to not have to trawl through the $PSBoundParameters hashtable and reconstruct the original strings, but that looks like the only feasible way forward (unless I'm missing something.)
Original code inside get-machine:
$environments = get-Environment -EnvironmentName $EnvironmentName
Oh for Pete's sake. I found it. I was missing the big stupid easy thing. I'll leave this up for others, and in case someone has an even better answer.
https://ss64.com/ps/psboundparameters.html
$PSBoundParameters can be used to call a subordinate function or cmdlet passing the same parameters - PowerShell will automatically splat the hash table's values instead of having to type each of the parameters:
get-otherthing #PSBoundParameters

Powershell: Dynamically gather data types for IIS configuration element validation

I'm attempting to dynamically use the Microsoft.Web.Administration namespace within a powershell cmdlet.
Is there a way to add a variable into a Namespace.Class declaration.
I'm using the namespace [Microsoft.Web.Administration] and it's class [Microsoft.Web.Administration.ApplicationPool], it has a property under it 'Recycling' that you can access using a GetProperty method.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling")
If you spit out the PropertyType of the above using this
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.FullName
You get this result,
Microsoft.Web.Administration.ApplicationPoolRecycling
which is another class. I now want to access this class dynamically within the cmdlet. How do access this class from within the code, I want the code to dynamically discover the new class of the object and then access that class. But I can't find a way to accomplish this.
Psuedocode for what I'm trying
[System.Reflection.Assembly]::LoadFrom( "C:\windows\system32\inetsrv\Microsoft.Web.Administration.dll" )
$appPoolProperty = [Microsoft.Web.Administration.ApplicationPool].GetProperty($Property)
$subClassName = $appPoolProperty.PropertyType.FullName
#This is the step I'm lost on
$subClass = New-Object $subClassName
So I'm not sure if there's a way to have a TypeName for an object put in as a string value and I can't seem to find a way to cast the variable as anything else. Sorry if this is remedial, I'm a basement grown coder and just learn things as I go.
EDIT: As requested by Mathias below in the comments, an overview of what I'm trying to achieve.
I have a script that automates the configuration of many IIS components. At this time I'm attempting to add validation to the cmdlet Set-AppPoolConfiguration that I've created that allows a configuration to be fed into the cmdlet that configures an AppPool (this is used to deploy websites/weapplications throughout a distributed web environment). Utilizing the details inside the Microsoft.Web.Administration I'm able to get enum values, as well as types of the many configuration components of an AppPool. This is saving me time to where I don't have to hard code in the data types and can just dynamically discover them and do validation on the values when the specific configuration element is chosen.
For example. If an AppPool Recycle schedule is need to be configured, I need to validate it against a TimeSpan data type. If it is not a TimeSpan data type issues will arise when being added to the ScheduleCollection. So I'm looking to validate the value provided before attempting to add it.
Since there are many AppPool configuration elements, I don't want to have to create a massive switch or if/elseif chain that checks each configuration element and statically dictate what data type it is for validation. I want the class itself to dynamically provide this information to simplify the code.
I can get the majority of these data types by simply accessing the property chain within the namespace. For example, if you want to know what type is required for the QueueLength, use this:
[Microsoft.Web.Administration.ApplicationPool].GetProperty("QueueLength").PropertyType.Name
And you'll get Int64.
It's also extremely useful for getting enums.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("ManagedPipelineMode").PropertyType.GetEnumNames()
However attempting this with Schedule and you run into a small issue as it returns ScheduleCollection. This is true of any of the configuration elements that are part of a collection.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.GetProperty('PeriodicRestart').PropertyType.GetProperty('Schedule').PropertyType.Name
However the knowledge that the schedule item inside the ScheduleCollection is only accessible from within the Schedule class. My code currently checks to see if it is a collection, and then if it is, it is attempting to access that collection/class and get the information that is required. To find out that schedule is a TimeSpan you have to access it's specific class instance:
[Microsoft.Web.Administration.Schedule].GetProperty('Time').PropertyType.Name
Now AppPools are simple, there's only a single collection group that is normally edited, so hard coding in that if you're attempting to set a new recycle schedule it will be a TimeSpan isn't that big of a deal, however when we move over to WebSite/WebApplication configurations, it becomes more tedious to statically declare data types for each configuration element that is part of a collection, and becomes more useful to try and discover these dynamically based on the configuration element selected.
This was my initial approach, I just included the above for clarity. I'm going to step back and take another look at how to attack this as this does not appear to be as easy as I had hoped, I'll post my solution here.
You can retrieve the constructor from the type literal and invoke it like so:
$type = [Microsoft.Web.Administration.ApplicationPoolRecycling]
$ctor = $type.GetConstructor('NonPublic,Instance',$null,#(),$null)
$appPoolRecyclingInstance = $ctor.Invoke($null)
Though there may be a way to do the above, in order to complete the updates to my cmdlet and proceed forward with my project I went a hybrid route.
The reason why I started exploring the [Microsoft.Web.Administration] namespace was that it provided information on the data types where the typical way I was manipulating IIS settings failed using Get/Set/Add-WebConfigurationProperty.
The specific failure is in reporting back valid data types for Enums. Take for instance ProcessModel.IdentityTypes. There is a set of valid entries for an IdentityType. However the following doesn't provide you with those valid types, so you either have to create static instances of them inside your cmdlet, or some other external data source, whereas I wanted Microsoft to provide them either through IIS itself, or through the classes attached to these configuration elements so the cmdlet would need minimal updating as IIS versions/configuration elements change.
This code returns Boolean
(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='$AppPool']" -name "AutoStart").Value.GetType().Name
However, this code returns string, which is true, but I needed to know that it is an enum and I needed to know the proper values.
(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='$AppPool']" -name "processModel").identityType.GetType().Name
Using a mix of both the Namespace and the traditional Get-WebConfigurationProperty commands I can successfully now test for data types, as well as gather proper values for enums dynamically in code. If there is interest I can post the entire validation code here that I'm using for this cmdlet.

Is there a more complete VMWare PowerCLI reference?

I'm trying to use the VMWare PowerCLI v6.0 to do some automated things. I have found the installed and online version of the cmdlet documentation and for the most part it tells you very simple information about the commands, like the parameters, return types and what the cmdlet does.
I'm trying to find more complete documentation on this because the online documentation provided by VMWare doesn't list the exceptions that a particular cmdlet might throw and definitely doesn't properly describe the types and their properties. For example:
$org = Get-Org -Name "test"
$leases = $org.ExtensionData.Settings.GetVAppLeaseSettings()
$leases.DeploymentLeaseSeconds = 0
$leases.StorageLeaseSeconds = 0
$leases.DeleteOnStorageLeaseExpiration = $False
$leases.UpdateServerData()
The example code can be found all over the internet but there's no details on it at all, just a vague "This is how you X". I've searched and searched but I can't find any documentation on what type ExtensionData returns and absolutely no documentation on the method GetVAppLeaseSettings. It seems like as far as VMWare and their documentation is concerned, this function doesn't exist.
Does anyone know where I can find documentation that lists thrown exceptions for each cmdlet and what CLR types are returned in the ExtensionData properties?
UPDATE
I watched a Pluralsight video on PowerCLI and found that you can display the ExtensionData object type and properties by simply running
$obj.ExtensionData
You can also see all the methods available for that object by running
$obj.ExtensionData | Get-Member -MemberType method
The problem with this is that you need to be connected to an existing vCloud server and even though this lists the available properties and methods, it does not show any documentation for those properties or methods. Not to mention you would need to actually have an object created to be able to query these values, for example:
$org = Get-Org -Name "test"
$org.ExtensionData | Get-Member -MemberType method
In the above example, I need to be connected to the server and already have an organization created to be able to view its properties and methods.
I'm looking for the documentation on those properties and methods and it doesn't seem like that exists anywhere that I've searched.
EDIT
If you are down voting or voting to close, please provide me with feedback. This is a serious question and I have done a lot research into answering this myself before I posted it here.
With the help of Mathias in the comments, I've determined that there is no official documentation for this portion of the PowerCLI. The only way to get any kind of documentation is to use a tool like ILSpy or through the PowerCLI terminal itself by means of commands like GetType() and Get-Member

How to find information in powershell?

I'm coming from a unix background where I've written some scripts using bash and bourne. But I need to write some scripts using powershell and I'm having a hard time finding information.
For example, in *nix, I can do man bash and read all about how to use bash and I can do man some_command to read about a specific command. So far, I found some powershell equivalents like get-command to see all available commands, but getting and using objects is really confusing me.
For instance, I'm trying to create a new scheduled task using powershell and found some sample code here on SO. Here is a snippit:
$schedule = new-object -com Schedule.Service
$schedule.connect()
$tasks = $schedule.getfolder("\").gettasks(0)
$tasks | select Name, LastRunTime
foreach ($t in $tasks) {
foreach ($a in $t.Actions) {
$a.Path
}
}
I understand what this script is doing, but without experience how would I know to do the following:
Know to use new-object -com Schedule.Service
Know that this object has a .connect method
Know that this object has a .getfolder and .gettasks object
A lot of the code seems ambiguous to me, so where would I find out the above information natively using powershell?
So you found Get-Command. That's a good start it will show you the available cmdlets. There may be even more available after importing snapins/modules. Use Get-PSSnapin -Registered and Get-Module -ListAvailable to see additional modules that may be imported to give you even more cmdlets.
The nice thing about PowerShell is that the creators built in an alias system. One of the goals of it was to make it easier to learn PowerShell when you have a bash/DOS background. For example if you type man Get-Process it will give you the documentation for the Get-Process cmdlet. To see all documentation for it use man Get-Process -Full. man doesn't actually exist, it is an alias for Get-Help which has the same functionality as man on UNIX/Linux. You can use the Get-Alias cmdlet to show the registered alias' and their definitions.
The script you found is working with a COM object. You can tell because of the -com parameter that was used for New-Object (which is actually short for -ComObject). Unlike .NET objects, COM objects are not built in to PowerShell however PowerShell has support for them the same way VBScript has support for them. The Get-Member cmdlet will unveil both .NET and COM type object members (properties and methods). More about Get-Member below.
The script you found uses the New-Object cmdlet to create an instance of the COM object named Schedule.Service. There are two main ways to find out more information about this object. The first is that you can list its properties and methods directly within PowerShell using the Get-Member cmdlet. This cmdlet works for both .NET and COM objects. It is an invaluable cmdlet that will show you what you can do with your objects. Use man or Get-Help Get-Member to learn about it. In fact you can use Get-Member to discover the object members you asked about such as the .connect method. The second way is to look up the documentation for the object on MSDN which is Microsoft's developer documentation website. This is probably the best page for that particular object.
I am not familiar with powershell scripting but found this, maybe some reference to use:
http://technet.microsoft.com/eng-us/scriptcenter/powershell%28en-us%29.aspx
http://technet.microsoft.com/en-us/library/hh857339.aspx#BKMK_wps4
On the first link are PowerShell Scripting Webcasts to find and more.
Scheduling Jobs with the Windows PowerShell API: http://msdn.microsoft.com/en-us/library/windows/desktop/jj150476%28v=vs.85%29.aspx
Guide to getting started with Windows PowerShell: http://technet.microsoft.com/library/ee221100.aspx
About Windows PowerShell, following help topics:
get-command : Gets information about cmdlets from the cmdlet code.
get-member : Gets the properties and methods of an object.
where-object : Filters object properties.
about_object : Explains the use of objects in Windows PowerShell.
about_remote : Tells how to run commands on remote computers.
Conceptual help files are named "about_", such as:
about_regular_expression.
The help commands also display the aliases of the cmdlets. These
are alternate names or nicknames that are often easier to type.
For example, the alias for the Invoke-Command cmdlet is "remote".
To get the aliases, type:
get-alias
Hopefully this will help a little.
The first hit on Google for "powershell create scheduled task" leads here, where one of the answers refers to the Schedule.Service COM object. That object's documentation gives you a list of all the methods and properties of the object.
You can also use get-member to discover all the methods & properties of any variable or object in your session.
$schedule = new-object -com Schedule.Service
TypeName: System.__ComObject#{2faba4c7-4da9-4013-9697-20cc3fd40f85}
Name MemberType Definition
---- ---------- ----------
Connect Method void Connect (Variant, Variant, Variant, Variant)
GetFolder Method ITaskFolder GetFolder (string)
GetRunningTasks Method IRunningTaskCollection GetRunningTasks (int)
NewTask Method ITaskDefinition NewTask (uint)
Connected Property bool Connected () {get}
ConnectedDomain Property string ConnectedDomain () {get}
ConnectedUser Property string ConnectedUser () {get}
HighestVersion Property uint HighestVersion () {get}
TargetServer Property string TargetServer () {get}
The Component Object Model is a core piece of Windows and there are hundreds if not thousands of COM objects available in default Windows installation for interacting with both the OS and other software installed (software can install its own set of objects as well). A lot of it can be replaced with .NET Framework assemblies and PowerShell modules, snap-ins and cmdlets now.
How do you discover COM objects? Usually via Google - running searches for the things you're trying to do, and typically you'll find someone has already posted something about similar, or your search will key off words in the object's own documentation online.
If you're using PowerShell 3, you don't need to use Schedule.Service at all - there's a set of cmdlets for working with scheduled tasks. See New-ScheduledTask for a starter.
If you're looking for a generic PowerShell tutorial, I usually point people at this one
You're on the right track in that Get-Command *foo* will list all Cmdlets containing the word foo, and Get-Help New-Object will show you the help file for the New-Object cmdlet.
However, you then go straight into using COM objects, which far predate Powershell. COM programming is old and can be quite archaic. Powershell lets you interface with COM, but it's not really the "Powershell way" of doing things.
In Powershell 3, I was able to find Register-ScheduledJob:
The Register-ScheduledJob cmdlet creates scheduled jobs on the local computer.
If possible I would say that is the preferred approach over using the COM interface, just because it's likely easier and more Powershelley.