SSRS Cache Schedule Re - powershell

I have about ~50 reports that are scheduled to be "cached" on a recurring schedule (image below).
Is this information only available in Report Server Database or can the schedule information be retrieved using Powershell? All of the "obvious" methods I've run thus far (with powershell ise) either return no information or boolean values (all 'false')

You can use GetItemHistoryOptions to get the schedule for the report item.
Then based on the type of Item property of the ScheduleDefinitionOrReference [ref] parameter of the method, you can decide how to show the information.
Type of the Item, can be one of MinuteRecurrence, DailyRecurrence, WeeklyRecurrence, MonthlyRecurrence or MonthlyDOWRecurrence.
Example
For example to format MonthlyRecurrence you can use such code:
$svcUrl = 'http://the-host-name/ReportServer/reportservice2010.asmx'
$svc = New-WebServiceProxy -Class 'RS' -Namespace 'RS' -Uri $svcUrl -UseDefaultCredential
$reports = $svc.ListChildren("/", $true) | Where-Object { $_.TypeName -eq "Report" }
$KeepExecutionSnapshots = $false
$ScheduleDefinitionOrReference = New-Object RS.ScheduleDefinitionOrReference
foreach ($report in $reports) {
$result = $svc.GetItemHistoryOptions($report.Path,
[ref]$KeepExecutionSnapshots,
[ref]$ScheduleDefinitionOrReference)
if($ScheduleDefinitionOrReference.Item -is [RS.MonthlyRecurrence])
{
"'$($report.Name)' Schedule Information:"
"StartDateTime: $($ScheduleDefinitionOrReference.StartDateTime)"
"StartDateTime: $($ScheduleDefinitionOrReference.EndDate)"
"EndDateSpecified: $($ScheduleDefinitionOrReference.EndDateSpecified)"
"Days: $($ScheduleDefinitionOrReference.Item.Days)"
$months = Get-Member `
-InputObject $($ScheduleDefinitionOrReference.Item.MonthsOfYear) `
-MemberType Property | Where-Object {
$ScheduleDefinitionOrReference.Item.MonthsOfYear.$($_.Name) -eq $true
}
"Months:$($months.Name -join ",")"
}
}
And the result will be something like this:
'MyReport' Schedule Information:
StartDateTime: 12/19/2017 18:00:00
StartDateTime: 01/01/0001 00:00:00
EndDateSpecified: False
Days: 1,3-5
Months:August,December,July,November,October,September

Related

(PowerShell) How do I filter usernames with Get-EventLog

I'm working on a Powershell script to get all users who have logged in/out of a server in the past 7 days, where their name is not like "*-organization". The below works, but no matter what I try I'm not able to filter names
$logs = get-eventlog system -ComputerName $env:computername -source Microsoft-Windows-Winlogon -After (Get-Date).AddDays(-7)
$res = #()
ForEach ($log in $logs)
{
if($log.instanceid -eq 7001){
$type = "Logon"
}
Elseif ($log.instanceid -eq 7002){
$type = "Logoff"
}
Else { Continue }
$res += New-Object PSObject -Property #{Time = $log.TimeWritten; "Event" = $type; User = (New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])}};
$res
I've tried adding this line in various places and ways, but no matter what I can't get it to filter. It either fails and tells me my operator must have a property and value, or it runs fine and ignores any username filtering.
| Where-Object $_.User -notlike "*-organization"
Is it even possible to filter the login username with this method? If so, what am I doing wrong? If it's not possible, is there another way I can get what I need?
There would have to be a property named 'user' for that to work. Get-eventlog is actually obsolete now, and replaced by get-winevent. Unfortunately, you have to get into the xml to filter by usersid. I've included a time filter.
$a = get-winevent #{logname='system';
providername='Microsoft-Windows-Winlogon'} -MaxEvents 1
$e = $a.ToXml() -as 'xml'
$e.event.EventData
Data
----
{TSId, UserSid}
get-winevent #{logname='system';providername='Microsoft-Windows-Winlogon';
data='S-2-6-31-1528843147-473324174-2919417754-2001';starttime=(Get-Date).AddDays(-7);
id=7001,7002}
In powershell 7 you can refer to the eventdata named data fields directly:
get-winevent #{logname='system';providername='Microsoft-Windows-Winlogon';
usersid='S-2-6-31-1528843147-473324174-2919417754-2001'}
The get-winevent docs say you can use "userid" in the filterhashtable, but I can't get that to work.
EDIT: Actually this works. But without limiting it too much, at least for me.
get-winevent #{logname='system';userid='js2010'}
get-winevent #{providername='Microsoft-Windows-Winlogon';userid='js2010'}
You can do this with the -FilterXPath parameter like below:
$filter = "(*[System/EventID=7001] or *[System/EventID=7002]) and *[System/Provider[#Name='Microsoft-Windows-Winlogon']]"
$result = Get-WinEvent -LogName System -FilterXPath $filter | ForEach-Object {
# convert the event to XML and grab the Event node
$eventXml = ([xml]$_.ToXml()).Event
$eventData = $eventXml.EventData.Data
$userSID = ($eventData | Where-Object { $_.Name -eq 'UserSid' }).'#text'
$userName = [System.Security.Principal.SecurityIdentifier]::new($userSID).Translate([System.Security.Principal.NTAccount])
# you can add username filtering here if you like.
# remember the $userName is in formal DOMAIN\LOGONNAME
# if ($username -notlike "*-organization") {
# output the properties you need
[PSCustomObject]#{
Time = [DateTime]$eventXml.System.TimeCreated.SystemTime
Event = if ($eventXml.System.EventID -eq 7001) { 'LogOn' } else { 'LogOff' }
UserName = $userName
UserSID = $userSID
Computer = $eventXml.System.Computer
}
# }
}
# output on screen
$result
# output to CSV file
$result | Export-Csv -Path 'X:\TheOutputFile.csv' -NoTypeInformation
Note, I have commented out the username filtering in the code. It is just there to give you an idea of where to put it. Of course, you can also filter the $result afterwards:
$result | Where-Object { $_.UserName -notlike "*-organization" }
Adding to #js2010's helpful answer, and with the assumption you're using PowerShell 5.1. I usually identify the property array index and use Select-Object to create a custom property as needed.
$WinEvents =
get-winevent #{logname='system'; providername='Microsoft-Windows-Winlogon'} |
Select-Object #{Name = 'Time'; Expression = {$_.TimeCreated}},
#{Name = 'Event'; Expression = { If($_.ID -eq 7001){'Logon'} ElseIf($_.ID -eq 7002){ 'Logoff' } } },
#{Name = 'User'; Expression = { [System.Security.Principal.SecurityIdentifier]::new( $_.Properties[1].Value ).Translate([System.Security.Principal.NTAccount]) } }
In your case this should add a property called User with a value like DomainName\UserName to the objects. I also added expressions to derive the other properties you were adding to your custom objects. Select-Object emits custom objects as well so this should give the result you're looking for.
Let me know if this helps.
Update
Respectfully, the other 2 answers make the assumption that you are looking for logon/off events for a specific user. That's not how I read the question; in particular:
"get all users who have logged in/out of a server"
While PowerShell 7+ does let you directly cite UserID in the FilterHashtable, it's not very useful here because we're not seeking events for a specific user. Furthermore, it seems unhelpful for the ultimate output as by default it echoes as a SID. It would still need to be translated, not only for display but for further filtering. I'm also not positive that UserID will always be the same as Properties[1], there's certainly some variance when looking at other event IDs.
The XML work is very cool, but I don't think it's called for here.
There were some issues with my answer as well. I overlooked filtering the event IDs & dates up front. I also realized we don't need to instantiate [System.Security.Principal.SecurityIdentifier] class because the property is already typed as such. Along with some readability improvements I corrected those issues below.
# Should be the 1st line!
using NameSpace System.Security.Principal
$ResolveEventType = #{ 7001 = 'Logon'; 7002 = 'Logoff' }
$FilterHashTable =
#{
LogName = 'system'
ProviderName = 'Microsoft-Windows-Winlogon'
ID = 7001,7002
StartTime = (Get-Date).AddDays(-7)
}
[Array]$WinEvents =
Get-WinEvent -FilterHashtable $FilterHashTable |
Select-Object #{ Name = 'Time'; Expression = { $_.TimeCreated } },
#{ Name = 'Event'; Expression = { $ResolveEventType[ $_.ID ] } },
#{ Name = 'User'; Expression = { $_.Properties[1].Value.Translate( [NTAccount] ) } }
$WinEvents |
Where-Object{ $_.UserName -notlike "*-organization" } |
Format-Table -AutoSize
This tested good in PowerShell 5.1 & 7.0. I added Format-Table to display the output, but you can just change that out for an Export-Csv command as needed
Note: The last 2 pipelines can be combined, but I thought this was a
little more readable.
Let me know if this helps.

Format the results of a PowerShell script

I'm trying to retrieve Azure service bus queues who has exceeded a specific message count, and the script is working well so far, but when it retrieves the values, it just does it in the following format:
The limit has been exceeded for the following queues:q1-monitoring-endpoint q1-monitoring-endpoint q2-monitoring-endpoint q3-monitoring-endpoint
I need to retrieve them in a better format.
Here is the script, I'm using:
$NS = Get-AzureRmServiceBusNamespace
foreach ($NS in $NS)
{
$Queue = Get-AzureRmServiceBusQueue -ResourceGroupName $NS.ResourceGroup -Namespace $NS.Name
if ($Queue.MessageCount -eq 0 )
{
"The limit has been exceeded for the following queues:" + $Queue.Name
}
}
I don't have access to an Azure subscription at the moment to test this, but consider doing something along these lines:
Get-AzureRmServiceBusNamespace |
ForEach-Object {
Get-AzureRmServiceBusQueue -ResourceGroupName $_.ResourceGroup -Namespace $_.Name |
ForEach-Object {
[PsCustomObject]#{
Queue = $_.Name
LimitExceeded = ($_.MessageCount -eq 0)
}
}
}
This will (hopefully) produce output similar to the following:
Queue LimitExceeded
------ -------------
Queue1 False
Queue2 True
Queue3 False
Not only is this a neater format than the original string output, it means you get some objects as output, which can be further manipulated.
You should explain "in a better format". However, your main issue is within your foreach loop where you try to iterate over $NS but assign the current object to $NS. You need to choose a different variable:
$NS = Get-AzureRmServiceBusNamespace
foreach ($N in $NS)
{
$Queue = Get-AzureRmServiceBusQueue -ResourceGroupName $N.ResourceGroup -Namespace $N.Name
if ($Queue.MessageCount -eq 0 )
{
"The limit has been exceeded for the following queues:" + $Queue.Name
}
}
Note: I would recommend to retrieve all empty queues and save it in a variable (which enables you to use it later):
$emptyQueue = Get-AzureRmServiceBusNamespace |
ForEach-Object {
Get-AzureRmServiceBusQueue -ResourceGroupName $_.ResourceGroup -Namespace $_.Name
} |
Where-Object MessageCount -eq 0
Finally, output it in your desired format:
Write-Host "The limit has been exceeded for the following queues: $($Queue.Name -join ',')"
You can try the Format commands available in powershell to get the output in a better format.
You can define your custom format as well with Format-Custom command.
Reference for Format commands in Powershell : https://learn.microsoft.com/en-us/powershell/scripting/getting-started/cookbooks/using-format-commands-to-change-output-view?view=powershell-6

Display test-connection successes and failures in Out-Gridview

I am trying to get a list of servers and the last time they rebooted to show in a table. However, if it doesn't respond to a ping, I just need it to show in the list. I can't seem to figure out how to get it to add to the table after else.
Import-CSV $Downtime | % {
if(Test-Connection $_.server -Quiet -count 1){
Get-WmiObject Win32_OperatingSystem -ComputerName $_.server |
select #{LABEL="Name"; EXPRESSION = {$_.PSComputerName}}, #{LABEL="Last Bootup"; EXPRESSION = {$_.convertToDateTime($_.LastBootupTime)}}
}
else{#{LABEL="Name"; EXPRESSION = {$_.server}}
}
} | Out-GridView
I can always save the else results in a text file but this would be more convenient.
You need to make the same object, with the same properties!, in both cases so that PowerShell will understand the association between the two. The follwing example builds a custom hashtable using the if/else and outputs the object for each loop pass.
Import-CSV $Downtime | ForEach-Object {
$props = #{}
$server = $_.server
if(Test-Connection $server -Quiet -count 1){
$wmi= Get-WmiObject Win32_OperatingSystem -ComputerName $server
$props.Name = $wmi.PSComputerName
$props."Last Bootup" = $wmi.convertToDateTime($wmi.LastBootupTime)
}else{
$props.Name = $server
$props."Last Bootup" = "Could not contact"
}
New-Object -TypeName psobject -Property $props
} | Out-GridView
I used $server as the $_ changes context a couple of time so we wanted to be able to refer to the current row in the CSV we are processing.
I don't know what your PowerShell version is so I will assume 2.0 and create objects that support that.
In both cases an object is created with a Name and Last Bootup property which is populated based on the success of the ping.
As an aside I had a similar question a while ago about created similar object based output.

Get the users who are having server access for my server

We need to extract a report every month for our servers which should report who all are having the server admin access .This will help us remove the people for whom access is no more needed. Its taking lot of time to extract manually and I read on blogs that PowerShell is used to automate such kind of administration jobs.
Other details:
Server - Win 2008 R2
Powershell 1.0
Could any one help me how to I extract this report?
Here's a quick way to enumerate the list of administrators for a server.
$group = [ADSI]"WinNT://./Administrators"
#($group.Invoke("Members")) | foreach {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
You can then use an email cmdlet to send it or however you want to send it back to you.
See: http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/27/the-admin-s-first-steps-local-group-membership.aspx
There's no need for ADSI and PSRemoting. Example:
$cComputerNames = #("computer1", "computer2")
$cRows = #()
foreach ($sComputerName in $cComputerNames) {
$cAdminAccounts = Get-WmiObject -ComputerName $sComputerName `
-Class "Win32_GroupUser" `
| Where-Object {
($_.GroupComponent -split '"')[3] -eq "Administrators"
}
foreach ($cAdminAccount in $cAdminAccounts) {
$oRow = New-Object -TypeName PSObject -Property #{
"ComputerName" = $sComputerName
"AccountDomain" = ($cAdminAccount.PartComponent -split '"')[1]
"AccountName" = ($cAdminAccount.PartComponent -split '"')[3]
}
$cRows += $oRow
}
}
$cRows | Export-Csv -Path "admin-accounts.csv" -NoTypeInformation
You can use an associators of ... query to get more detailed info about accounts. See this blog post.

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation