0

I am perplexed to say the least. Currently working on a PowerShell script to deploy SharePoint Libraries to users via Intune.

I use a custom detection script, which checks the folder-attribute sync-status of a folder, before syncing (this is hacky, but apparently about as reliable as it gets when it comes to checking if a OneDrive folder is synced or not.

In the function to check the sync status, I use a -contains condition, to check if the value matches one of a list of predefined sync-status-strings:

function Test-SPFolderSyncStatus {

    param (
        [string]$folderPath
    )

    # Define lists of OneDrive status values
    $odSyncedValues = @(
        # English
        "Available when online",
        "Available on this device",
        "Always available on this device",
        "Syncing",

        # German
        "Verfügbar, wenn online",
        "Auf diesem Gerät verfügbar",
        "Immer auf diesem Gerät verfügbar",
        "Synchronisierung ausstehend",
        "Synchronisierung läuft"
    )

    # Check if folder exists
    if(!(Test-Path -Path $folderPath)) {
        return $false
    }

    # If the folder exists - check sync status
    $shell = (New-Object -ComObject Shell.Application).NameSpace((Split-Path $folderPath))
    $status = $shell.GetDetailsOf(($shell.ParseName((Split-Path $folderPath -Leaf))),303)

    if ($status -in $odSyncedValues) {
        return $true
    }
    else {
        return $false
    }
}

This function does not work as intended: even when I print $status, and it is equal to a string in my sync-value list, the function returns false.

I then tried debugging, by outputting the array to the CLI, this is where the major confusion arose.

When I put $odSyncedValues just on its own, just before the if (which I originally did to debug), the -contains starts working as intended???

So this works:

    // Rest of the script stays the same
    $odSyncedValues

    if ($status -in $odSyncedValues) {
        return $true
    }
    else {
        return $false
    }

But this doesnt:

    // Rest of the script stays the same
    // no $odSyncedValues
    if ($status -in $odSyncedValues) {
        return $true
    }
    else {
        return $false
    }

What causes this? Can I get it to work as intended without mentioning the variable?

2
  • Have you checked if $status contains invisible characters using .Trim()? Also, what PowerShell version are you using? Some behaviors differ across versions. Explicitly casting $status as [string] before checking -contains might also help troubleshoot. Commented Feb 25 at 17:12
  • Since the problem occurs with string literals containing non-ASCII chars. in your source code, the likeliest explanation is that your script file is misinterpreted by the Windows PowerShell engine, which happens if the script is saved as UTF-8 without a BOM (this is no longer a problem in PowerShell (Core) 7). Try saving your script as UTF-8 with BOM. See the linked duplicate for details. Commented Feb 25 at 17:35

1 Answer 1

0

I've found the issue - it has to do with the encoding of special characters.

My issue was with "Verfügbar, wenn online", the single reference to $odSyncedValues seems to force PowerShell to encode strings properly, while the same thing does not happen when it is referenced only in the condition?

I am still not entirely clear on how this happens, which is why I'll leave the question up for now.

But the "fix" is to do:

    $odSyncedValues = $odSyncedValues | ForEach-Object {
        [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::Default.GetBytes($_))
    }
Sign up to request clarification or add additional context in comments.

2 Comments

It sounds like this problem might be solved by simply saving the containing script file with UTF-8 encoding
UTF8 with BOM encoding

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.