Debugging Universal Apps

Hello,

I am running version 5.0.15.
I am trying to debug part of an app I wrote for internal use but I can’t seem to get the debugging working. Sadly, the help page for debugging an app doesn’t help me much either. The part I want to debug is this:

New-UDTextbox -Placeholder "UserID" -Id "UserID" -Style @{
  'margin-top' = 10
}

New-UDButton -Id "Search" -Icon (New-UDIcon -Icon 'Search') -Text " Search" -ShowLoading -OnClick {
  Sync-UDElement 'sync1'
} -Style @{
  'margin-left' = 20;
  'margin-right' = 20;
}

New-UDDynamic -Id 'sync1' -Content {
  New-UDTransferList -Item {
    $Server = "domain.name";
    $ListItems = @();
    $MemberOf = @();

    $InputUserID = (Get-UDElement -ID "UserID").Value;

    $Check = [System.String]::IsNullOrWhiteSpace($InputUserID);

    if (-not $Check){
      $ADUser = Get-ADUser -Server $Server -Identity $InputUserID -properties memberOf;
      $MemberOf = $ADUser.memberOf;
    }

    Foreach($group in $MemberOf){
      $Item = "";
      $temp = "";
      $temp = ($group.Split('='))[1];
      $Item = ($temp.Split(','))[0];
      if($group -like "D3T*"){$ListItems += $Item}
    }

    foreach($item in $ListItems){
      New-UDTransferListItem -Name $item -value $item
    }
  } -Id "TransferList" -LeftTitle "Current groups" -RightTitle "Groups to remove" -Dense
}

To be more precise, I want to debug the if statement, as it does not seem to be working.
How should I go about debugging apps?

Right before your if, include Wait-Debugger.

 $Check = [System.String]::IsNullOrWhiteSpace($InputUserID);
Wait-Debugger
    if (-not $Check){

Back in the admin console, for the app, you can then go to the session for your user. Look for the endpoint with the longest execution time, since it’s just waiting on the breakpoint. If you click the +, you will see a debug console for the endpoint. From there, you can run commands, inspect variables and step through code.

I have to admit, we need to make it easier to find endpoints that are waiting in the debugging state like this.

The other option is to use Show-UDToast to print out values in the UI from execution in the script.

   $InputUserID = (Get-UDElement -ID "UserID").Value;
    Show-UDToast $InputUserID -Persist
    $Check = [System.String]::IsNullOrWhiteSpace($InputUserID);

    if (-not $Check){

Hello there. I’m a Coworker of Sebastian.P and with your help we discovered some things. There are some questions left, for which we would be very grateful, if someone (perhaps you? ;)) can provide with answers.

This is the code of our demo app:

$Pages += New-UDPage -Name 'Demo' -Content {
    New-UDCard -Content{

        New-UDTextbox -Placeholder "UserID" -ID "UserID" -Style @{
            'margin-top' = 10
        }

        New-UDButton -ID "Search" -Icon (New-UDIcon -Icon 'Search') -Text " Search" -ShowLoading -OnClick {
            Sync-UDElement 'sync1'
        } -Style @{
            'margin-left' = 20;
            'margin-right' = 20;
        }

        New-UDDynamic -Id 'sync1' -Content {

            $Server = "domain.loc";
            $InputBox = Get-UDElement -Id "UserID";
            $ListItems = @();

            if (-not [System.String]::IsNullOrWhiteSpace($InputBox.value)){

                $ADUser = $null;
                $ADUser = Get-ADUser -Identity $InputBox.value -Server $Server -properties memberOf;

                foreach($g in $ADUser.memberOf){
                    $groupname = "";
                    if ($g -like "*,OU=*"){
                        $groupname = $g.Split(",OU=")[0].SubString(3);
                    } else {
                        $groupname = $g.Split(",CN=")[0].SubString(3);
                    };
                    if ($groupname.StartsWith("RES")){
                        #Show-UDToast -Message $groupname -Duration 4000;
                        $ListItems += New-UDTransferListItem -Name $groupname -Value $groupname;
                    }
                }

                #Wait-Debugger;
            }

            if ($ListItems.Count -ne 0){
                New-UDTransferList -Item { $ListItems } -ID "TransferList" -LeftTitle "Current groups" -RightTitle "Groups to remove" -Dense
            }
        }
    }
}

$Navigation = @(
    New-UDListItem -Label "Demo" -Href "/Demo"
)

New-UDApp -Title "Hello, World!" -Pages $Pages -Navigation $Navigation

The good news first: this code works. We get the transfer list filled with the groups which fullfills the condition we’ve set.

The bad news: We don’t know why it didn’t worked before.

During analyzing with Show-UDToast and Debugging we saw that the value of the InputBox was readed successfully and the Get-ADUser-Request was successfull too. The second Show-UDToast proved that the variable $groupname is filled with the intended value and the debugger showed, that the array of ListItems will be created as intended (an array of hashtables, each element with the keys name, value and disabled).

The last change we did was to move the New-UDTransferList-Cmdlet in an if-statement to make sure it only appears if at least one listitem exist.

After that, we get the list. Before the last change, the list appears but had never any items.

I’m assuming, that Powershell Universal is doing some sort of parallelizing and because the $listItems variable is now part of an if-statement, PSU now “knows” it has to wait for it. But we didn’t found any hints in the documentation for this behavior.

Because we want to use this demo for some apps for other Coworkers and our customers we want to make sure to understand, why it didn’t work before and why it works now.

Any hints are appreciated!

Thx and Greetings,
Ronny K

edit: Fixing spelling errors and stuff (me english is not very good… :|)

I wonder if this could be a client side rendering issue. PSU isn’t doing anything funky on the PowerShell end here. The if statement is just run as is and no additional parallelization is done with this code.

Does the list update again if you try to search a second time? The reason I ask is because you are using a static ID for the transfer list, and just from experience, I’ve seen certain components won’t update properly is the ID already exists on the page.

For example, when you page loads the first time, the list is empty. It then doesn’t create the transfer list. Once you search, the list has values, and the transfer list is created. If you search again, I’d be curious if it actually updates the transfer list again.

In the first example, it would always create the empty transfer list and would not updated on the second sync after you searched.

If my theory holds true, the root cause is a bug in the transfer list rendering. The work around would be to create a dynamic ID for the transfer list to force it to render a new list. You could store the ID in a session scope variable if you need to list ID later.

Ah ok, i didn’t had a possible bug in my mind.

I will give it a try

ty :slight_smile:

Using a session variable for storing the dynamically generated id for transfer list was the trick. Thank you for that :slight_smile:

For reference here the working code:

$Pages += New-UDPage -Name 'Demo' -Content {
    New-UDCard -Content{

        New-UDTextbox -Placeholder "UserID" -ID "UserID" -Style @{
            'margin-top' = 10
        }

        New-UDButton -ID "Search" -Icon (New-UDIcon -Icon 'Search') -Text " Search" -ShowLoading -OnClick {
            Sync-UDElement 'sync1'
        } -Style @{
            'margin-left' = 20;
            'margin-right' = 20;
        }

        New-UDDynamic -Id 'sync1' -Content {

            $Server = "domain.loc";
            $InputBox = Get-UDElement -Id "UserID";
            $ListItems = @();

            if (-not [System.String]::IsNullOrWhiteSpace($InputBox.value)){

                $ADUser = $null;
                $ADUser = Get-ADUser -Identity $InputBox.value -Server $Server -properties memberOf;

                foreach($g in $ADUser.memberOf){
                    $groupname = "";
                    if ($g -like "*,OU=*"){
                        $groupname = $g.Split(",OU=")[0].SubString(3);
                    } else {
                        $groupname = $g.Split(",CN=")[0].SubString(3);
                    };
                    if ($groupname.StartsWith("RES")){
                        #Show-UDToast -Message $groupname -Duration 4000;
                        $ListItems += New-UDTransferListItem -Name $groupname -Value $groupname;
                    }
                }

                #Wait-Debugger;
            }

            if ($ListItems.Count -ne 0){
                $Session:IdTransferListGroupSelect = (New-Guid).ToString();
                New-UDTransferList -Item { $ListItems } -ID $Session:IdTransferListGroupSelect -LeftTitle "Current groups" -RightTitle "Groups to remove" -Dense
            }
        }
    }
}

$Navigation = @(
    New-UDListItem -Label "Demo" -Href "/Demo"
)

New-UDApp -Title "Hello, World!" -Pages $Pages -Navigation $Navigation

Hi Adam, I also had put in a ticket for this but didn’t get much help. This used to be easier to find in v4. Any reason this was removed? I found it a handy feature for sure. But will be looking at your new method posted now.