Rending problem when converting to windows service?

I have a working PoshUD that renders 5 pages in addition to the main page. It works fine when I run it by hand from the ISE or whatever.

When I use Publish-UDDashboard and the service starts, the little menu burger in the upper left disappears and none of the subpages render any content. The main page works entirely as expected except for the menu disappearing.

Thoughts? How can I troubleshoot this?

Thanks!

Here’s the code:

Get-UDDashboard | Stop-UDDashboard
function Get-CFANSLMStats {

    $KnownLMUtil = @(
        "C:\Program Files\QTModeler_8071_ux64\lmutil.exe", # LMUtil from QT Modeler
        "C:\Program Files (x86)\Exelis\IDL83\bin\bin.x86\lmutil.exe", # LMUtil from Exelis
        "C:\Program Files (x86)\Hexagon\Geospatial Licensing 2018\program\lmutil.exe" # LMUtil from Hexagon
    )

    $servicesObj = @(
        [PSCustomObject]@{
            ServiceAbbr = "ecog9"
            ServiceName = "eCognition 9"
            Port        = "27000"
            Server      = "cfans-rsl01.oit.umn.edu"
        },
        [PSCustomObject]@{
            ServiceAbbr = "qtm"
            ServiceName = "QT Modeler"
            Port        = "27001"
            Server      = "cfans-rsl01.oit.umn.edu"
        }
        [PSCustomObject]@{
            ServiceAbbr = "interg"
            ServiceName = "Intergraph"
            Port        = "27002"
            Server      = "cfans-rsl01.oit.umn.edu"
        }
        [PSCustomObject]@{
            ServiceAbbr = "exelis"
            ServiceName = "Exelis"
            Port        = "27004"
            Server      = "cfans-rsl01.oit.umn.edu"
        },
        [PSCustomObject]@{
            ServiceAbbr = "cfansecog9"
            ServiceName = "eCognition 9"
            Port        = "27000"
            Server      = "cfansecog.oit.umn.edu"
        }
    )

    foreach ($lm in $KnownLMUtil) {
        if (Test-Path $lm) {
            #TODO: Fix the search for working LMUtil?
            $LicenseManagerUtil = $lm
        }
    }

    ForEach ($ser in $servicesObj) {
        $port = $ser.Port
        $server = $ser.Server
        $abbr = $ser.ServiceAbbr
        $fullName = $ser.ServiceName
        $statusCheckDate = (Get-Date).ToString()
        $licenseInfo = (&$LicenseManagerUtil lmstat -a -c $port@$Server).Split("`r").Trim()
        if ($licenseInfo[4] -match "Error") {
            $licenseObj += @{
                $ser.ServiceAbbr =
                [PSCustomObject]@{
                    FullName      = $fullName
                    Abbreviation  = $abbr
                    CheckDate     = $statusCheckDate
                    DaemonName    = "DOWN"
                    DaemonStatus  = "DOWN"
                    DaemonVersion = "DOWN"
                    LicenseServer = "$($server)"
                    LicenseFile   = "DOWN"
                    Features      = @()
                }
            }
        }
        else {
            $licenseObj += @{
                $ser.ServiceAbbr =
                [PSCustomObject]@{
                    FullName      = $fullName
                    Abbreviation  = $abbr
                    CheckDate     = $statusCheckDate
                    DaemonName    = (($licenseInfo[11]).Split()[0]).TrimEnd(":")
                    DaemonStatus  = ($licenseInfo[11]).Split()[1]
                    DaemonVersion = ($licenseInfo[11]).Split()[2]
                    LicenseServer = ((($licenseInfo[4]) -Split ":")[1]).Trim()
                    LicenseFile   = ((($licenseInfo[5]) -Split ":\s")[1]).Trim().TrimEnd(":")
                    Features      = @()
                }
            }
        }
        foreach ($line in $licenseInfo) {
            if ($line -match "Users of") {
                $feature = (($line -Split " ")[2]).TrimEnd(":")
                $licenseObj.$abbr.Features += $Feature
                $licenseObj.$abbr | Add-Member -Name $Feature -MemberType NoteProperty -Value @{
                    LicensesTotal = ($line -Split " ")[6]
                    LicensesUsed  = ($line -Split " ")[12]
                    LicenseUsers  = @()
                }
            }
        }

        for ($i = 0; $i -le $licenseObj.$abbr.Features.Length - 1; $i++) {
            $feature = $licenseObj.$abbr.Features[$i]
            if ($licenseObj.$abbr.$feature.LicensesUsed -gt 0) {
                $userInfo = (&$LicenseManagerUtil lmstat -c $port@$Server -f $feature).Split("`r").Trim()
                foreach ($l in $userInfo) {
                    if ($l -match ", start") {
                        $licenseObj.$abbr.$feature.LicenseUsers += $l
                    }
                }
            }
        }

    }
    $licenseObj
}


$every60Seconds = New-UDEndpointSchedule -Every 60 -Second

$Schedule = New-UDEndpoint -Schedule $every60Seconds -Endpoint {
    $Cache:licenseData = Get-CFANSLMStats
}

$rslPages = @()

#$Cache:licenseData = Get-CFANSLMStats

$rslPages += New-UDPage -Name "Main" -DefaultHomePage -Content {
    New-UDRow -Endpoint {
        foreach ($service in $Cache:licenseData.keys) {
            New-UDColumn -LargeSize 3 -MediumSize 6 -SmallSize 12 -Content {
                $Color = "PaleGreen"
                if ($Cache:licenseData.$service.DaemonStatus -ne "UP") {$Color = "IndianRed"}
                New-UDCard -Title "$($Cache:licenseData.$service.FullName) - $($Cache:licenseData.$service.DaemonName)" -Size Medium -Content {
                    New-UDRow {"Daemon status: " + $Cache:licenseData.$service.DaemonStatus}
                    New-UDRow {"Last check: " + $Cache:licenseData.$service.CheckDate}
                    New-UDRow {"Server: " + $Cache:licenseData.$service.LicenseServer}
                    New-UDRow {"Features available: " + ($Cache:licenseData.$service.features).length}
                    $totalSessions = 0
                    foreach ($f in $Cache:licenseData.$service.features) {
                        $totalSessions = $totalSessions + $Cache:licenseData.$service.$f.LicensesUsed
                    }
                    New-UDRow {"Total Active Feature Sessions: $($totalSessions)"}
                } -BackgroundColor $Color -Links @(
                    if ($Cache:licenseData.$service.DaemonStatus -eq "UP") {
                        New-UDLink -Url "/$($Cache:licenseData.$service.Abbreviation)" -Text "More info" -FontColor "LightSlateGray" -Icon "question"
                    }
                )
            }
        }
    }
}

foreach ($service in $Cache:licenseData.keys) {
    $headBGColor = "PaleGreen"
    if ($Cache:licenseData.$service.DaemonStatus -ne 'UP') { $headBGColor = "IndianRed"}
    $rslPages += New-UDPage -Name $Cache:licenseData.$service.Abbreviation -Content {
        New-UDRow -Endpoint {
            New-UDCard -Title $Cache:licenseData.$service.FullName -Content {
                New-UDRow {"Daemon status: " + $Cache:licenseData.$service.DaemonStatus}
                New-UDRow {"Server: " + $Cache:licenseData.$service.LicenseServer}
                New-UDRow {"License File: " + $Cache:licenseData.$service.LicenseFile}
                New-UDRow {"LMtools version: " + $Cache:licenseData.$service.DaemonVersion}
                New-UDRow {"Features available: " + ($Cache:licenseData.$service.features).length}
                $totalSessions = 0
                foreach ($f in $Cache:licenseData.$service.features) {
                    $totalSessions = $totalSessions + $Cache:licenseData.$service.$f.LicensesUsed
                }
                New-UDRow {"Total Active Feature Sessions: $($totalSessions)"}
            } -BackgroundColor $headBGColor
        }
        New-UDRow -Endpoint {
            $featureNum = 0
            foreach ($feature in $Cache:licenseData.$service.Features) {
                $featureNum++
                if ( ($featureNum % 2) -eq 0 ) { $featureBackgroundColor = "LightGray"} else { $featureBackgroundColor = "White"}
                New-UDcard -Endpoint {
                    New-UDCollection -Header "Feature: $($feature)" -Content {
                        New-UDCollectionItem -Content { "Total Licenses: $($Cache:licenseData.$service.$feature.LicensesTotal)" }
                        New-UDCollectionItem -Content { "Total Licenses: $($Cache:licenseData.$service.$feature.LicensesUsed)" }
                        if ($Cache:licenseData.$service.$feature.LicensesUsed -gt 0) {
                            New-UDColumn -LargeOffset 1 -LargeSize 12 -Content {
                                New-UDCollectionitem -Content {
                                    New-UDCollection -Header "Active Sessions" -Content {
                                        foreach ($session in $Cache:licenseData.$service.$feature.LicenseUsers) {
                                            New-UDCollectionItem -Content {$session}
                                        }
                                    }
                                }
                            }
                        }
                    }
                } -BackgroundColor $featureBackgroundColor
            }

        }
    }
}

$ei = New-UDEndpointInitialization -Function Get-CFANSLMStats
$Dashboard = New-UDDashboard -Title "Remote Sensing Lab Licensing Services" -Pages $rslPages -EndpointInitialization $ei
Start-UDDashboard -Port 80 -Dashboard $Dashboard -Endpoint @($Schedule)

I’ve rerun this a number of times and still am having the same problem. Any ideas?

Has anyone run a PoshUD as a service with nssm?

Thanks!

I played around with NSSM and wasn’t ultimately successful.

I have since done a diff between the file I have and the one that gets copied into the PoshUD module and they are identical. I can even run that version of the script by hand and it works fine.

So the questions I have are:

  1. Are there any features or functionality that I am using that might be incompatible when running a service? E.g. should I take out calls to get-uddashboard | stop-uddashboard? Do I no longer need to schedule the endpoints?

  2. More generally, what problems have people seen that would stop sub-pages from rendering like this and how have you fixed them?

  3. Are there other viable ways to run a PoshUD as a service?

I hope someone can throw some thoughts at me; what I wrote works great but it needs to run as a service…

1 - Scheduled endpoints are still needed. You can probably take out the Get-UDDashboard | Stop-UDDashboard but I don’t think it’s hurting anything.
2 - I have never seen this before. Can you open the F12 developer tools to see if you have any errors in there. When you say the menu disappears, is it there to begin with and then it actually vanishes or is it never there when you run as a service?
3 - You can run in IIS but aside from that running it in the UD service process is probably the best way.

After looking at your dashboard a bit more, the problem is probably that you are creating new pages based on a cache variable.

Creating a static page in a dynamic manner is fine but it only happens one during service start up. So if you don’t have the cache value populated, it won’t create those pages. The scheduled endpoint is probably starting after your loop to create the pages.

If you could populate this variable (outside of your scheduled endpoint), before you start your dashboard, I think that this would work.

If new items are added to the cache after the start up, they won’t be turned into pages because that code never runs again. You will need to do something with dynamic pages instead.

@adam Thanks so much for looking at things.

I believe i have corrected the issue with your advice. I simply added a call out to the function that creates all of the data and pumped into $Cached before all of the endpoint stuff and page creation.

Things look like they are working now. Thanks so much!!

1 Like