2

I am trying to run Lync / S4B test commands through an automated script, currently I set up a command array like this:

$HealthCheckCoreCmdlets = @{
    "AddressBookService" = "Test-CsAVConference -TargetFQDN $($fqdn)"
    "AddressBookWebQuery" = "Test-CSAddressBookWebQuery -TargetFQDN $($fqdn)"
    "ASConference" = "Test-CsASConference -TargetFQDN $($fqdn) -SenderSipAddress $($CTestUser1) -SenderCredential $($Cpass1) -ReceiverSipAddress $($CTestUser2) -ReceiverCredential $($Cpass2)"
    "AVConference" = "Test-CsAVConference -TargetFQDN $($fqdn) "
    "ClientAuthentication" = "Test-CsClientAuthentication -TargetFQDN $($fqdn) -UserSipAddress $($CTestUser1) -UserCredential $($Cpass1)"
    "DataConference" = "Test-CsDataConference -TargetFQDN $($fqdn)"
    "GroupExpansion" = "Test-CsGroupExpansion -TargetFQDN $($fqdn) -GroupEmailAddress $($CGroupEmail)"
    "GroupIm" = "Test-CsGroupIm -TargetFQDN $($fqdn)"
    "Im" = "Test-CsIm -TargetFQDN $($fqdn)"
    "LisConfiguration" = "Test-CsLisConfiguration -TargetFQDN $($fqdn) -Subnet $($CSubnet) -UserSipAddress $($CTestUser1) -UserCredential $($Cpass1)"
    "LocationPolicy" = "Test-CsLocationPolicy -TargetFQDN $($fqdn)"
    "P2PAV" = "Test-CsP2PAV -TargetFQDN $($fqdn)"
    "Presence" = "Test-CsPresence -TargetFQDN $($fqdn)"
    "Registration" = "Test-CsRegistration -TargetFQDN $($fqdn)"
    "Replica" = "`$testReplica = Test-CsReplica; if(`$testReplica -eq `$null){return 'Success'}else{return 'Failure'}"
    "Topology" = "`$testtopology = Test-CsTopology; if(`$testtopology -eq `$null){return 'Success'}else{return 'Failure'}"
    "UcwaConference" = "Test-CsUcwaConference -TargetFQDN $($fqdn)"
    "WebApp" = "Test-CsWebApp -TargetFQDN $($fqdn)"
}

And I use Invoke-Expression to run the command:

foreach ($PSHCmdlet in $HealthCheckCoreCmdlets.GetEnumerator() | Sort-Object Key) 
{ 
    Update-Status $PSHCmdlet.Key
    $Corearray."$($PSHCmdlet.Key)" += (Get-CMDLetResult $PSHCmdlet.Value) 
}

Get-CMDLetResult:

function Get-CMDLetResult ($Value) {
$CMDResult = (Invoke-Expression ("$($Value)"))

Return $CMDResult 
}

And most commands work other than the ones that require a Get-Credential passed to them (I'm storing them in the above commands as $Cpass1 etc.) - I've tried passing the variable as: `$Cpass1 / $($Cpass1) / and just plain $Cpass1.

Can anyone point me on how I can pass this object through with the command to be invoked?

HyPerRifiC
  • 23
  • 3
  • 1
    I have no idea what you're trying to do, but this doesn't look like the way to do it... What is the reason you're using `Invoke-Expression` over directly assigning the result of the operation to a variable? Are `$fqdn`, `$CGroupEmail` etc all constant? You may be better off implementing a custom object over using a hash here – arco444 Nov 10 '15 at 16:23
  • $fqdn changes as you run these commands against different Lync Pools that are identified earlier, however $CGroupEmail and credential variables are setup at the start of the script - but they will change depending on the Lync pool run against and as such cannot be predefined in the script. The script run other commands fine, but always errors when trying to run a command that requires a Get-Credential object as an argument. "Test-CsClientAuthentication -TargetFQDN $($fqdn) -UserSipAddress $($CTestUser1) -UserCredential $($Cpass1)" – HyPerRifiC Nov 10 '15 at 16:27
  • Though I will try seeing if a custom object works better, and the reason for using Invoke command is because I want to assign the result of the stored command to the new array, not store the command itself - if there is another way to do this please let me know. – HyPerRifiC Nov 10 '15 at 16:36

1 Answers1

0

First, I think you'd be much better off defining your commands as [ScriptBlock]s rather than as [String]s:

$HealthCheckCoreCmdlets = @{
    "AddressBookService" = { Test-CsAVConference -TargetFQDN $Using:fqdn }
    # ...
    "Replica" = {
        $testReplica = Test-CsReplica
        if ($testReplica -eq $null) {
            return 'Success'
        } else { 
            return 'Failure'
        }
    }
}

You can use the $Using scope modifier to embed current variable values in there, you don't have escape $ or anything else, you get the advantage of syntax highlighting and tab completion when constructing it; it's overall better.

Using $Using will also correctly embed complex objects such as a [PSCredential].

For the time being I'm just addressing your question directly, but I think arco444 might have a point about how you're going about this whole thing.

briantist
  • 45,546
  • 6
  • 82
  • 127
  • Ahh, I wasn't aware you could use script blocks in the jagged array, though arco444 is right in that it might be better to do it through a custom object. – HyPerRifiC Nov 10 '15 at 16:43
  • @HyPerRifiC what do you mean by jagged array? I only see a single hashtable here. – briantist Nov 10 '15 at 16:46
  • sorry, probably used the wrong term, I'm used to calling an array with nested data jagged, though if this was wrong I apologize. – HyPerRifiC Nov 10 '15 at 16:51
  • @HyPerRifiC Not a problem, but you don't actually have an array here. `@{...}` represents a `[hashtable]` in PowerShell. In some languages this is called an "associate array", in some it's just called a "hash" but generally it's a set of key/value pairs. The value in this case can be any kind of object, even a `[ScriptBlock]`. – briantist Nov 10 '15 at 16:54
  • That makes more sense, thank you for explaining it to me. – HyPerRifiC Nov 10 '15 at 17:08
  • Towards this end I have recently started making hashtables with scriptblocks for values that have parameters, so then I could just do things like `$HealthCheckCoreCmdlets.AddressBookService.Invoke($fqdn)` and pass `$fqdn` into the scriptblock as a parameter. That way I can run the same action against multiple objects easily. – TheMadTechnician Nov 10 '15 at 19:05
  • @TheMadTechnician yeah that's a good technique also, and it can be less confusing than using `$Using` (if not a bit longer to implement). – briantist Nov 10 '15 at 19:07