2

I am working on a PowerShell script that creates a Fedora WSL using docker, it all works, but I cannot get to work the code part which sets the icon in the settings.json file.

Relevant part of the JSON:

"profiles": 
    {
        "defaults": {},
        "list": 
        [
            {
                "commandline": "PATH\\TO\\WSL",
                "guid": "{your-guid}",
                "hidden": false,
                "name": "fedora",
                "icon": "PATH\\TO\\ICON"
            },
            {
                "commandline": "cmd.exe",
                "guid": "{your-guid}}",
                "hidden": false,
                "name": "Command Prompt"
            },
            {
                "guid": "{your-guid}}",
                "hidden": false,
                "name": "Azure Cloud Shell",
                "source": "Windows.Terminal.Azure"
            },

Here is what I've tryied:

$settings = Get-Content $env:localappdata'\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json' -raw | ConvertFrom-Json
$settings.profiles.list | % {if($_.name -eq $WSLname){$_.icon=$InstallPath\fedora.ico}}
$settings | ConvertTo-Json -depth 32| set-content $env:localappdata'\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'

Variables are taken from params in first part of the script.
My goal is to chech if the profile name with given input by the user exists, if so, changes or adds the "icon" property to the fedora.ico path.

Edit: This part of the script needs to run after windows terminal has been relaunched.

Lauren Yim
  • 12,700
  • 2
  • 32
  • 59
Okazakee
  • 23
  • 4
  • Can you show us the (relevant part) of the settings.json file? – Theo Sep 05 '22 at 12:36
  • What is ```$settings.update | % { ... }``` trying to do? There's no ```update``` field in your example json document. Also ```$_$WSLname``` should probably be ```$_.$WSLname```. – mclayton Sep 05 '22 at 13:13
  • I am gonna add an image with relevant part on the op – Okazakee Sep 05 '22 at 13:24
  • @mclayton I was just tinkering and trying some snippets I've found here in other posts. I am completely new to Powershell, any suggestion is well accepted. First and last string of $settings work fine, i just need the logic working. – Okazakee Sep 05 '22 at 13:34
  • What would be `$WSLname` in your current code, just to know if it can actually match with any value of the `Name` properties on your json. Your code at first glance should work properly for updating the object(s) as long as the objects actually have an `Icon` property (not all objects in `.profiles.list` have this property and you would actually have to add it in case it's not there) – Santiago Squarzon Sep 05 '22 at 15:55
  • @SantiagoSquarzon WSLname is a given input string by user for the wsl profile name automatically created by wsl import command. In this case will be "fedora" the majority of the time, in my case I wanna be sure to just edit or add "icon" property ONLY in the scope of $WSLname profile properties, not other "icon"s in other profiles. – Okazakee Sep 05 '22 at 16:16
  • There is no entry in your [Json](https://raw.githubusercontent.com/AndrewGrant31/windows-terminal-settings/main/settings.json) where `Name` = "Fedora" not sure I'm following – Santiago Squarzon Sep 05 '22 at 16:19
  • my bad, I had to specify that i took a random json snippet online for the settings, I will now create a fame profile in op. – Okazakee Sep 05 '22 at 17:07
  • Now it makes sense and your code seems correct, you only need to use quotes on the assignment of `$_.Icon` => `$_.Icon = "$InstallPath\fedora.ico"` - this is assuming `$InstallPath` is defined. I don't see any other issue with your code – Santiago Squarzon Sep 05 '22 at 17:41
  • It now works ONLY if the "icon" property already exists, which is not. I will now try to add an if that checks that and test. – Okazakee Sep 05 '22 at 20:29

1 Answers1

2

Here is how you can approach the logic for your code to check if the icon property exists and assign a new value to it and if it doesn't exist, add a new property to the object with the new value. Hope the inline comments helps you understand the logic.

$settings = Get-Content 'path\to\settings.json' -Raw | ConvertFrom-Json
# enumerate all objects in `.profiles.list`
foreach($item in $settings.profiles.list) {
    # if the `Name` property is not equal to `$WSLName`
    if($item.name -ne $WSLname) {
        # we can skip this object, just go next
        continue
    }
    # if we're here we know `$item.name` is equal to `$WSLname`
    # so we need to check if the `icon` property exists, if it does
    if($item.PSObject.Properties.Item('icon')) {
        # assign a new value to it
        $item.icon = "$InstallPath\fedora.ico"
        # and go to the next element
        continue
    }
    # if we're here we know `$item.name` is equal to `$WSLname`
    # but the `icon` property does not exist, so we need to add it
    $item.PSObject.Properties.Add([psnoteproperty]::new('icon', "$InstallPath\fedora.ico"))
}
$settings | ConvertTo-Json -Depth 32 | Set-Content 'path\to\newsetting.json'
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • I think now the main issue is that this block of code should run after windows terminal restarts, as the wsl updates the json on the go and it does not immediately apply to already opened instance. If there's a way to tell powershell to restart and THEN execute this block, it should work perfectly. – Okazakee Sep 06 '22 at 00:42