Microsoft.SystemCenter.WebApplicationSolutions.SummaryMap.WebTestListDetails.Script.ps1 (Resource)

Element properties:

TypeResource
File NameWebTestListDetails.ps1
AccessibilityInternal

Source Code:

<Resource ID="Microsoft.SystemCenter.WebApplicationSolutions.SummaryMap.WebTestListDetails.Script.ps1" Accessibility="Internal" FileName="WebTestListDetails.ps1"/>

File Content: WebTestListDetails.ps1

#************************************************************************************************************

# This script returns a collection of web tests for the group by location input.
#
# Parameters:
#
# Collection of IDO with the ID of the GroupByLocation instances. The output location is set to the
# DisplayName of these groups (which should also be given as input on the same IDO).
#
#************************************************************************************************************

Param(
$TargetEntities,
$PublicKeyToken)

###############Constants###########################
$RESULTSET_ID = 1;
$RESULTSET_LAST_RESPONSE_TIME = 7;
$RESULTSET_LAST_SAMPLE_TIME = 8;

###############Help Functions###########################
#
#

function GetTimeUtc (
$time = $(throw "needs to speficy a type")
)
#-------------------------------------------------------
# Helper to convert SDK returned times to UTC.
#
# Arguments:
# time - the time that might be unspecified timezone
#
# Returns:
# time with utc kind set
#-------------------------------------------------------
{
if ($time -ne $null)
{
return new-object ([DateTime])($time.Ticks, [DateTimeKind]::Utc);
}

return $time;
}

function Get-Type (
$type = $(throw "needs to speficy a type")
)
#-------------------------------------------------------
# Helper to get the right generic type created.
#
# Arguments:
# type - the string with the type name.
# args - array of arguments or argumens list
#
# Returns:
# The matching array of types.
#-------------------------------------------------------
{
trap [System.Management.Automation.RuntimeException] { throw ($_.Exception.Message) }

$returnType = $null;

if($args -and $args.Count -gt 0)
{
$types = $args[0] -as [type[]];
if(-not $types)
{
$types = [type[]] $args;
}

$genericType = [type] ($type + '`' + $types.Count);
if($genericType -ne $null)
{
$returnType = $genericType.MakeGenericType($types);
}
}
else
{
$returnType = [type] $type;
}

return $returnType;
}

function New-GenericObject(
$type = $(throw "needs to speficy a type"),
[object[]] $typeParameters = $null,
[object[]] $constructorParameters = @()
)
#-------------------------------------------------------
# Helper to instantiate a generic type.
#
# Arguments:
# type - the type (closed one, or a string to be closed).
# typeParameters - generic types to create generic, if not spefified or null then closed type assumed in input.
# constructors - parameters for constructor if not using the default one
#
# Returns:
# The matching array of types.
#-------------------------------------------------------
{
$closedType = (Get-Type $type $typeParameters)
,[Activator]::CreateInstance($closedType, $constructorParameters)
}

function Get-ParametersTypes
#-------------------------------------------------------
# Helper to generate an array of parameter types
# from the actual parameters. Note that it won' work
# if passed argument is null or contain a null value
# in its content.
#
# Arguments:
# params - array of arguments.
#
# Returns:
# The matching array of types.
#-------------------------------------------------------
{
param (
[object[]]$params = $null
)

$paramsTypes = new-object object[] $params.Length;
$idx = 0;
foreach($p in $params)
{
$paramsTypes[$idx] = $params[$idx].GetType();
$idx = $idx + 1;
}

return $paramsTypes;
}

function Invoke-GenericMethod-WithTypes
#-------------------------------------------------------
# Makes a generic and call it returning whatever it
# returns
#
# Arguments:
# myType - Type containing the generic method.
# myMethod - Method name
# myMethodArgumentTypes - Argument types for the method (support overload)
# genericTypes - Generic passing in types
# object - Object to call the generic on
# params - Parameters for the call
#
# Returns:
# The matching array of types.
#-------------------------------------------------------
{
param (
[type]$myType,
[string]$myMethod,
[type[]]$myMethodArgumentTypes,
$genericTypes,
$object,
[object[]]$params = $null
)

$method = $myType.GetMethod($myMethod, $myMethodArgumentTypes);
$genericMethod = $method.MakeGenericMethod($genericTypes);

$ret = $genericMethod.Invoke($object, $params);

return ,$ret;
}

function Invoke-GenericMethod
#-------------------------------------------------------
# Makes a generic and call it returning whatever it
# returns
#
# Arguments:
# myType - Type containing the generic method.
# myMethod - Method name
# genericTypes - Generic passing in types
# object - Object to call the generic on
# params - Parameters for the call
#
# Returns:
# The matching array of types.
#-------------------------------------------------------
{
param (
[type]$myType,
[string]$myMethod,
$genericTypes,
$object,
[object[]]$params = $null
)

$paramsTypes = Get-ParametersTypes($params);

$ret = Invoke-GenericMethod-WithTypes `
$myType `
$myMethod `
$paramsTypes `
$genericTypes `
$object $params;

return ,$ret;
}

#
#
###############Help Functions###########################

function Initialize-Script
#-------------------------------------------------------
# Initialization for testing.
#-------------------------------------------------------
{
if ($global:scriptContext -eq $null)
{
Write-Error "Missing the proper context argumet.";
exit;
}
}

function Initialize-SDK
#-------------------------------------------------------
# Initialize any objects we need from the SDK
#-------------------------------------------------------
{
# The mg
$script:mg = $global:scriptContext.ManagementGroup;

# DW stuff.
$script:dw = $script:mg.Reporting.GetDataWarehouse();

# Read/Cache SDK types...
$mp = $script:mg.ManagementPacks.GetManagementPack("Microsoft.SystemCenter.WebApplicationSolutions.Library", $global:publicKeyToken, $null);
$script:groupByLocationContainsWebTest = $script:mg.EntityTypes.GetRelationshipClass("Microsoft.SystemCenter.WebApplicationSolutions.WebTestGroupByLocation.Contains.WebTest", $mp);
}

function Populate-LastResponseTime
#-------------------------------------------------------
# Creates the initial fetch of web test objects.
#-------------------------------------------------------
{
# No tests, nothing to do
if ($script:webTests.Count -eq 0)
{
return;
}

# need to find a target to go get the current DisplayName of the grouper.
$sampleWebTest = $null;
foreach ($target in $script:webTests.Values)
{
$sampleWebTest = $target;
break;
}
if ($sampleWebTest -eq $null)
{
return;
}

$counters = new-object ([System.Text.StringBuilder]);

[void]$counters.Append("<Counters>");

foreach($id in $script:webTests.Keys)
{
$webTest = $script:webTests[$id];
$entry = "<Counter><MeId>{0}</MeId></Counter>" -f $id;
[void]$counters.Append($entry);
}
[void]$counters.Append("</Counters>");

$params = new-object ([Microsoft.EnterpriseManagement.Warehouse.StoredProcedureParameterCollection]);

$param1 = new-object ([Microsoft.EnterpriseManagement.Warehouse.StoredProcedureParameter])("ManagementGroup", $mg.Id);
$param2 = new-object ([Microsoft.EnterpriseManagement.Warehouse.StoredProcedureParameter])("CountersXml", $counters.ToString());

$mp = $script:mg.ManagementPacks.GetManagementPack("Microsoft.SystemCenter.WebApplicationTest.Library", $global:publicKeyToken, $null);
$ruleId = $mp.GetRule("Microsoft.SystemCenter.WebApplicationTest.Performance.CollectTransactionResponseTime").Id;

$param3 = new-object ([Microsoft.EnterpriseManagement.Warehouse.StoredProcedureParameter])("RuleId", $ruleId);
$param4 = new-object ([Microsoft.EnterpriseManagement.Warehouse.StoredProcedureParameter])("InstanceNamePattern", "");

$params.Add($param1);
$params.Add($param2);
$params.Add($param3);
$params.Add($param4);

$rs = $dw.GetDataWarehouseData('SDK.Microsoft_SystemCenter_WebApplicationSolutions_Library_LastPerformanceSampleValueAndTimeGet', $params);

$webTest = $null;
foreach ($result in $rs.Results)
{
$id = $result.Values[$RESULTSET_ID];
$value = $result.Values[$RESULTSET_LAST_RESPONSE_TIME];
$time = GetTimeUtc $result.Values[$RESULTSET_LAST_SAMPLE_TIME];

# Convert value to precision we want...
$value = [Math]::Round($value, 4);

if ($script:webTests.TryGetValue($id, [ref]$webTest))
{
$webTest["LastTransactionResponseTime"] = $value;
$webTest["LastSampleTime"] = $time;

if ($time -gt $webTest["ModifiedTime"])
{
$webTest["ModifiedTime"] = $time;
}
}
}
}

function Fetch-WebTestList
#-------------------------------------------------------
# Creates the initial fetch of web test objects.
#-------------------------------------------------------
{
$script:webTests = new-object ('System.Collections.Generic.Dictionary[Guid, Object]');

$params = new-object object[] 5;
$params[1] = $script:groupByLocationContainsWebTest;
$params[2] = [Microsoft.EnterpriseManagement.Configuration.DerivedClassTraversalDepth]::None;
$params[3] = [Microsoft.EnterpriseManagement.Common.TraversalDepth]::OneLevel;
$params[4] = [Microsoft.EnterpriseManagement.Common.ObjectQueryOptions]::Default;

$genericTypes = new-object type[] 1;
$genericTypes[0] = [Microsoft.EnterpriseManagement.Monitoring.MonitoringObject];

$vd = New-GenericObject System.Collections.Generic.List Microsoft.EnterpriseManagement.Monitoring.DataProviders.ValueDefinition;

$value = new-object ([Microsoft.EnterpriseManagement.Monitoring.DataProviders.ValueDefinition]);
$value.OutputPropertyName = "Id";
$value.XPath = '$Object/Property[Name=''Id'']$';
$vd.Add($value);

$value = new-object ([Microsoft.EnterpriseManagement.Monitoring.DataProviders.ValueDefinition]);
$value.OutputPropertyName = "DisplayName";
$value.XPath = '$Object/Property[Name=''DisplayName'']$';
$vd.Add($value);

$value = new-object ([Microsoft.EnterpriseManagement.Monitoring.DataProviders.ValueDefinition]);
$value.OutputPropertyName = "HealthState";
$value.XPath = '$Object/Property[Name=''HealthState'']$';
$vd.Add($value);

foreach ($target in $global:targetEntities)
{
$params[0] = [Guid]$target["Id"];
$list = Invoke-GenericMethod `
$script:mg.EntityObjects.GetType() `
"GetRelationshipObjectsWhereSource" `
$genericTypes `
$script:mg.EntityObjects `
$params;

if ($list -eq $null)
{
Write-Error "could not go from GroupByLocation to WebTests!";
exit;
}

foreach($rel in $list)
{
$smo = $rel.SourceObject;
$mo = $rel.TargetObject;

# its ok to compare before setting Kind.
$mt = $mo.LastModified;

if ($mt -lt $mo.StateLastModified)
{
$mt = $mo.StateLastModified;
}

if ($mt -lt $mo.AvailabilityLastModified)
{
$mt = $mo.AvailabilityLastModified;
}

$webTest = $global:scriptContext.CreateFromObject($mo, $vd);
if ($webTest -eq $null)
{
Write-Error "webTest object cannot be instantiated.";
exit;
}

# this test is only needed becasue of the test script library,
# instead of using a local variable.
# We are using IsChecked already there means types have been created already.
$isCreated = $webTest.Type.Properties["IsChecked"];
if ($isCreated -eq $null)
{
[void]$webTest.Type.Properties.Create("IsChecked", [bool]);
[void]$webTest.Type.Properties.Create("Color", [Microsoft.EnterpriseManagement.Presentation.DataAccess.IDataObject]);
[void]$webTest.Type.Properties.Create("LastTransactionResponseTime", [double]);
[void]$webTest.Type.Properties.Create("LastSampleTime", [DateTime]);
[void]$webTest.Type.Properties.Create("Location", [String]);
[void]$webTest.Type.Properties.Create("ModifiedTime", [DateTime]);
}

$webTest["IsChecked"] = $false;
$webTest["Color"] = $null;
$webTest["Location"] = $smo.DisplayName;
$webTest["ModifiedTime"] = GetTimeUtc $mt;

$script:webTests.Add($mo.Id, $webTest);
}
}


Populate-LastResponseTime;
}

function MergeForRefresh
#-------------------------------------------------------
# Will create or update the Returned collection.
#-------------------------------------------------------
{
$tests = new-object ('System.Collections.Generic.List[object]')($global:scriptContext.ReturnCollection);

$fetchWebTest = $null;
foreach($webTest in $tests)
{
$id = [Guid]$webTest["Id"];
if ($script:webTests.TryGetValue($id, [ref]$fetchWebTest))
{
$fetchTime = $fetchWebTest["ModifiedTime"];
$oldTime = $webTest["ModifiedTime"];

if ($fetchTime -gt $oldTime) # we update...
{
$webTest["HealthState"] = $fetchWebTest["HealthState"];
$webTest["DisplayName"] = $fetchWebTest["DisplayName"];
$webTest["Location"] = $fetchWebTest["Location"];
$webTest["LastTransactionResponseTime"] = $fetchWebTest["LastTransactionResponseTime"];
$webTest["LastSampleTime"] = $fetchWebTest["LastSampleTime"];
$webTest["ModifiedTime"] = $fetchTime;
}

# flag that it is not to be added since it was modified or simply didn't change.
$script:webTests[$id] = $null;
}
else # remove the object
{
$global:scriptContext.ReturnCollection.Remove($webTest);
}
}

foreach($id in $script:webTests.Keys)
{
$webTest = $script:webTests[$id];
if ($webTest -ne $null)
{
$global:scriptContext.ReturnCollection.Add($webTest);
}
}
}

function Main
#-------------------------------------------------------
# Main entry point.
#-------------------------------------------------------
{
if ($TargetEntities -eq $null)
{
Write-Error "The parameter TargetEntities is null.";
exit;
}

if ($PublicKeyToken -eq $null)
{
Write-Error "The parameter PublicKeyToken is null.";
exit;
}

$global:targetEntities = $TargetEntities;

$global:publicKeyToken = $PublicKeyToken;

Initialize-Script;

Initialize-SDK;

Fetch-WebTestList;

MergeForRefresh;
}

Main