Powershell App Pool set periodicRestart syntax - powershell

I'm trying to set the periodicRestart property using a powershell script, but I'm trying to use a slightly different syntax than what I've seen in code samples.
Here's one way to do according to Set the specific times to recycle an application pool with PowerShell:
Clear-ItemProperty $iisAppPoolName -Name Recycling.periodicRestart.schedule
Set-ItemProperty $iisAppPoolName -Name Recycling.periodicRestart.schedule `
-Value #{value="01:00:00"}
However, I already have a block of code where I'm setting properties on the $appPool itself like this:
$appPool = New-WebAppPool $iisAppPoolName
$appPool.managedPipelineMode = "Classic"
$appPool.managedRuntimeVersion = "c4.0"
$appPool.recycling.periodicRestart.time = [TimeSpan]"00:00:00"
$appPool | Set-Item
Which works fine, so I'd like to add the following line:
$appPool.recycling.periodicRestart.schedule = #{value="01:00:00"}
But I can't get the syntax for #{value="01:00:00"} to take. The schedule property is expecting a hashtable which is what I'm passing it.
Any ideas?

It's interesting that you're seeing it as a [Hashtable]. I see it as a [Microsoft.Iis.Powershell.Framework.ConfigurationElement].
It has a method called .UpdateCollection() which expects a [PSObject[]], so it's looking for an array of objects.
The thing is, calling that method, whether on a pool object returned from New-WebAppPool or from Get-Item IIS:\AppPools\ExistingPool, results in an error stating that it's read only.
I tried replacing the entire .Collection with a new arraylist with timespan objects added to it, and I got no errors, but it didn't set the values.
I also tried creating a ConfigurationElement object, but it seems to have no constructor, so it's probably a private class somewhere in the code.
I'm not saying there's definitely no way to do it like you want, but it seems like you'll be best off just using Set-ItemProperty as it seems that some of these attributes were designed to be updated only through the PS Provider.

Related

How to use Remove-LocalGroupMember to remove from a server?

I have the following script that is supposed to remove members from a server:
$ssasInstance = ""
$accountName= ""
Import-Module SqlServer
[Microsoft.AnalysisServices.Server]$SSASserver = New-Object ([Microsoft.AnalysisServices.Server])
$SSASserver.Connect($ssasInstance)
$role= $SSASserver.Roles["Administrators"]
$role.Members.Remove($accountName)
$role.Update()
The problem is for some reason Remove() is not really working, no errors generated, but it doesnt remove the user.
I tested the script by instead adding a user, $role.Members.Add($accountName) and this works great! so i know that it must be a bug with the remove() method, and the only option I have is to use Remove-LocalGroupMember
I tried just using it like this:
$ssasInstance = ""
$accountName= ""
Import-Module SqlServer
[Microsoft.AnalysisServices.Server]$SSASserver = New-Object ([Microsoft.AnalysisServices.Server])
$SSASserver.Connect($ssasInstance)
$role= $SSASserver.Roles["Administrators"]
Remove-LocalGroupMember -Group "Administrators" -Member "$accountName"
$role.Update()
but that doesnt work either...although i think its because it doesnt know exactly where its removing from...
I tried this too, but to no avail:
Remove-LocalGroupMember -Group "$role" -Member "$accountName"
So how can i integrate this module into my script?
This is an unfortunate confluence of circumstances: when you do
$role.Members.Add("member")
This works because, under water, the string "member" is implicitly converted by PowerShell to a RoleMember with a Name of member and an empty Sid. All fine. However, if you then do
$role.Members.Remove("member")
Nothing happens, because you will create a new RoleMember instance, and since RoleMember has no implementation of .Equals() (a fairly bizarre oversight), different instances will never be considered the same.
This means you can only remove members by getting the actual instance in the collection (or by index, I suppose):
$member = $role.Members.Where{$_.Name -eq "member"} | Select -First 1
$role.Members.Remove($member)
Note that you will not get an error if there is no such member (because Remove allows $null, again in a rather bizarre oversight), so you may want to check for $member -eq $null if you want to verify that.
Definitely do not use Remove-LocalGroupMember -- that cmdlet is part of a completely different module and removes members from local Windows groups, not SSAS roles.

How to get service recovery options from Powershell?

I'm having issues figuring out an easy way to get the recovery options of a particular service in powershell.
Using command line sc: sc qfailure [servicename] [buffer size] works.
I also know that HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\\[service] will contain a FailureActions but i cant find any documentation on interpreting those values.
Is it just a matter of executing SC.EXE and parsing that data or is there a better way of doing this?
This will provide you Binary Value and you will have interpret it as follow which is tough part.
$actions = get-itemproperty hklm:\system\currentcontrolset\services\<ServiceShortName> | select -Expand FailureActions
typedef struct _SERVICE_FAILURE_ACTIONS {
DWORD dwResetPeriod;
LPTSTR lpRebootMsg;
LPTSTR lpCommand;
DWORD cActions;
SC_ACTION *lpsaActions;
} SERVICE_FAILURE_ACTIONS, *LPSERVICE_FAILURE_ACTIONS;
If you are using .NET
Follow this.
jborean93 has created a custom type that exposes the native C# service objects and methods to PowerShell. The included Get-ServiceRecovery and Set-ServiceRecovery functions make it easy to view and change service recovery settings within PowerShell.
https://gist.github.com/jborean93/889288b56087a2c5def7fa49b6a8a0ad
.\ServiceRecovery.ps1
(Get-ServiceRecovery -Name 'MyService').Actions
The ServiceController object that Get-Service doesn't contain all the properties for what a service can do.
To get access to more things try connecting to WMI. Try this command to see the properties we can see in WMI.
Get-WmiObject Win32_service | select -first 1 -property *

Why does powershell executes my property getters

I have a C# project that I'm consuming with PowerShell.
A method returns an object that have not been fully initialized and that calls P/Invoke under the hood through get properties.
When I call the method, the script crashes because of an accessViolationException that is caused by the call of a property on that partially initialized object, but I didn't call it.
Why do Powershell act like this? is there an option to disable that "eager property evaluation"?
The original issue is the one posted here: https://github.com/ZeBobo5/Vlc.DotNet/issues/330
Add-Type -Path ".\Other\VLC\Vlc.DotNet.Core.dll"
Add-Type -Path ".\Other\VLC\Vlc.DotNet.Core.Interops.dll"
$Cameras = New-Object System.Collections.ArrayList
$Test = New-Object System.Uri("rtsp://192.168.0.50/axis-media/media.amp?camera=1")
$Cameras.Add($Test)
$VlcLibDirPath = (Get-Location).Path + ".\Other\VLC\libvlc_x64"
$VlcLibDir = New-Object System.IO.DirectoryInfo($VlcLibDirPath)
$VlcOpt = "--rtsp-user=admin", "--rtsp-pwd=12345"
$Plyr = New-Object Vlc.DotNet.Core.VlcMediaPlayer($VlcLibDir, $VlcOpt)
for ($i=0; $i -lt $Cameras.Count; $i++)
{
$Plyr.SetMedia($Cameras[$i]) #Fails here with System.AccessViolationException
$Plyr.Play
$Plyr.Stop
}
SetMedia returns a VlcMedia, which contains a Statistics property, which is automatically invoked by PowerShell.
Code for VlcMedia can be found here : https://github.com/ZeBobo5/Vlc.DotNet/blob/develop/src/Vlc.DotNet.Core/VlcMedia/VlcMedia.cs
It's difficult to tell without seeing your code, but there's tons of ways this could be happening. If the object is being displayed at all, the properties are probably all being read.
You should change those to methods, and then they won't get read without specifically being invoked.
Or, change your getters to detect an uninitialized object (you should be doing this already if it's possible for consumers to end up with such an object).
Edit:
With your code posted, it's clear:
$Plyr.SetMedia($Cameras[$i]) #Fails here with System.AccessViolationException
SetMedia returns a VlcMedia, which contains a Statistics property, which is automatically invoked by PowerShell.
Everything returned in PowerShell goes somewhere. If you don't assign it or redirect it, it gets sent to the pipeline.
It seems that you don't want or need the output from this method, so you should either assign it to a variable or dispose of the return in one of a few ways:
[null]$Plyr.SetMedia($Cameras[$i])
$null = $Plyr.SetMedia($Cameras[$i])
$Plyr.SetMedia($Cameras[$i]) | Out-Null
(note: piping to Out-Null is the least performant, which is magnified since you're doing this in a loop)
If you want to use the value later (not shown in your code), assign it and use it later.

How to make a PSCustomObject with Nested Values

I am trying to create a PSCustomObject with nested values and am having a really tough time, I see plenty of examples of hash tables and pscustom objects but for only extremely basic sets of data.
I am trying to create a a pscustom object that will have a server name property and then another property that has an array of services as well as their current running status.
I was able to make a hash table of the services and their running status but when I try to make an object with the has table it doesnt work very well:
hash table contains service names and their running status (stopped or running)
$hashtable
$myObject = [PSCustomObject]#{
Name = "$server"
Services = "$hashtable"
}
I am open to anything really, I have plenty of examples of how to convert items from JSON or XML and would love be able to use those as well but still having the same issue with being able to format the data in the first place.
edit: sorry about some of the vagueness of this post. As some people have already mentioned, the problem was the double qoutes around the hashtable. Everything is working now
As #t1meless noted in the comments, when you enclose a variable in double quotes it will attempt to convert that value to a string. For a Hashtable object, rather than give any information on from the object this will return "System.Collections.Hashtable". If you remove the double quotes, it will store the value of the hashtable as you are intending.
Here is a full example of what pulling the service information from a server and storing the values in a custom object. Note that $server can still be left in quotes as it is a string, but since it's already a string this would be unnecessary.
$myObject = Foreach ($Server in $Servers) {
$hashtable = #{}
Get-Service -ComputerName $Server | ForEach-Object { $hashtable.Add($_.name,$_.Status}
[PSCustomObject]#{
Name = "$Server"
Services = $hashtable
}
}

Setting a DateTime to $null/empty using PowerShell and the SCSM cmdlets

I'm currently trying to sync additional attributes from the AD (Active Directory) for user objects in SCSM (System Center Service Manager) using a PowerShell script.
The extension I wrote for this, includes an attribute for the expiration date of a AD user account (DateTime value, named DateTimeAttribute in the example) if the user account doesn't expire it should be empty/null.
Using Import-SCSMInstance, which should be similar to a CSV import, it kind of works by passing "null" for the field. The problem is that Import-SCSMInstance seems to be quite unreliable and it doesn't offer any kind of information of why it works or doesn't work. Using Update-SCSMClassInstance seems to work a lot better but I can't figure out a way to clear the field using this and even using [DateTime]::MinValue will result in an error, stating that it's an invalid value.
So would anyone have an idea on how to clear the value using Update-SCSMClassInstance or figure out why Import-SCSMInstance might or might not work?
A simple example for this could look like the following:
$server = "<ServerName>"
$extensionGuid = "<GUID>"
Import-Module 'C:\Program Files\System Center 2012 R2\Service Manager\Powershell\System.Center.Service.Manager.psd1'
New-SCManagementGroupConnection -ComputerName $server
$extensionClass = Get-SCSMClass -Id $extensionGuid
$scsmUserObject = Get-SCSMClassInstance -Class $extensionClass -Filter 'UserName -eq "<User>"'
# Error
$scsmUserObject.DateTimeAttribute = ""
# Works but fails on Update-SCSMClassInstance
$scsmUserObject.DateTimeAttribute = $null
$scsmUserObject.DateTimeAttribute = [DateTime]::MinValue
# Works
$scsmUserObject.DateTimeAttribute = "01-01-1970"
Update-SCSMClassInstance -Instance $scsmUserObject
It seems that you can't clear a date once it's filled. When you write $null, it sets the date to 1-1-0001 01:00:00, which is an invalid date causing the update-scsmclassinstance to fail.
What we have set as a user's AD property when we don't want something to expire, is 2999-12-31 (yyyy-MM-dd). Perhaps this could help, although it's not directly what you asked for...
Also, you can use the pipeline to update a property in SCSM:
Get-SCSMClassInstance -Class $extensionClass -Filter 'UserName -eq "<User>"' | % {$_.DateTimeAttribute = <date>; $_} | update-scsmclassinstance
It doesn't look like it's currently possible to clear custom date attributes using the PowerShell cmdlets.