1

I am trying to build a small program that shutdown WSL and other programs that are running WSL in it like Windows Terminal.

I want the user to be able to set TRUE or FALSE in a .conf file variable depending on if the Windows Terminal wants to be closed or not by checking it with a conditional but when i add the if statement checking for the variable the program just simply doesn't work.Any ideas on where i could be making the mistake?

Here is the code:

# Gets the settings from the conig file
Foreach ($i in $(Get-Content stop.conf))
{
    Set-Variable -Name $i.split("=")[0] -Value $i.split("=",2)[1]
}

# Cheks for open processes and saves it to a variable
$IDE = Get-Process $EDITOR -ErrorAction SilentlyContinue
$windowsTerminal = Get-Process $windowsterminal -ErrorAction SilentlyContinue
$linuxsys = Get-Process $DISTRO -ErrorAction SilentlyContinue

# OPTIONAL
# Checks if Windows Terminal is open and closes it
if ($WINTERMINAL -eq $true)
{
    if ($windowsTerminal)
    {
        # Try gratefully first
        $windowsTerminal.CloseMainWindow()
        Sleep 5
        if (!$windowsTerminal.HasExited)
        {
            $windowsTerminal | Stop-Process -Force
        }
    }
}

Just in case the .conf file looks like this:

DISTRO=ubuntu2004
EDITOR=code
WINTERMINAL=$true
Flamiing
  • 13
  • 5
  • 1
    Wouldn't it be better to use `conf.json` file then you wouldn't have a need to manually parse your file? – Santiago Squarzon Oct 14 '22 at 18:16
  • You can use `if([bool]::Parse($WINTERMINAL.TrimStart('$'))) { .... # condition for true here }` tho I'm against it :) – Santiago Squarzon Oct 14 '22 at 18:21
  • I am starting to think that the good option is going to be to go for the json file as nothing seems to work, thank you for your help tho! Is helping me a lot to learn! – Flamiing Oct 14 '22 at 23:46

2 Answers2

0

Since you're reading from a plain-text file, your dynamically created variables based on the file's content will contain string values.

Thus, use a verbatim (single-quoted) string ('...') to check for a string with verbatim value $true (as opposed to the automatic (built-in) $true variable (conceptually, a constant), which is a Boolean)[1]:

if ($WINTERMINAL -eq '$true') # Note the '...' quoting; ditto for '$false'

If you want to be more flexible and also accept verbatim true and yes (or any case variation thereof - note that PowerShell is generally case-insensitive by default):

if ($WINTERMINAL -in '$true', 'true', 'yes')

Note:

  • While using JSON as your config file's format, as suggested, would indeed give you support for a few data types (other than string), including Booleans, maintaining JSON files manually is error-prone.

  • A friendlier format that is also type-aware, which PowerShell does not natively support, however, is TOML, which you can think of as a typed superset of INI files (.ini)


[1] When you coerce a Boolean to a string, such as in an -eq operation with a string as the LHS, $true and $false become verbatim strings True and False, respectively. E.g., 'True' -eq $true is true.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • I have tryed but it does not seem to work, i don't know why, but thank you so much for the help and for all the interesting information i did not know about! : ) – Flamiing Oct 14 '22 at 23:51
  • Glad to hear the information was helpful, @ZumoDeZumos. However, _in what way_ did the solution in this answer not work? With your sample file content and the code for reading it from your question, it does work for me. – mklement0 Oct 15 '22 at 01:47
  • Tbh i don't fully know how to respond to your question as this is actually my first time making and learning how to make a powershell script and i am not quite sure of all the mistakes i was able to solve. The thing is that the main problem was several Syntax Errors. – Flamiing Oct 16 '22 at 01:28
0

I agree with @santiago-squarzon that a .JSON file would be easier here. Part of the reason it would be easier here would be that you would automatically get support for certain data types, like Boolean.

However, I think your code could work with a couple of minors changes:

# Gets the settings from the conig file
Foreach ($i in $(Get-Content stop.conf))
{
    # Change one, using $executionContext here (speed)
    $varName, $varValue = $i.Split("=", 2)
    $executionContext.SessionState.PSVariable.Set($varName, $varValue)
}

# Cheks for open processes and saves it to a variable
$IDE = Get-Process $EDITOR -ErrorAction SilentlyContinue
$windowsTerminal = Get-Process $windowsterminal -ErrorAction SilentlyContinue
$linuxsys = Get-Process $DISTRO -ErrorAction SilentlyContinue

# At this point, your variables are all strings.  There's two ways forward from here:
# 1. Make it an actual boolean
# 2. Match potential yes values (I'll do #2)
if ($WINTERMINAL -match "^(?>$true|yes|y)$")
{
    if ($windowsTerminal)
    {
        # Try gratefully first
        $windowsTerminal.CloseMainWindow()
        Sleep 5
        if (!$windowsTerminal.HasExited)
        {
            $windowsTerminal | Stop-Process -Force
        }
    }
}

The reason I'm choosing to match instead of [bool]::Parse($winTerminal) is that your original code had a truth value of "Yes", not "True". If you want to provide a more human-friendly option than "true" or "false", this is the way to go.

Start-Automating
  • 8,067
  • 2
  • 28
  • 47
  • Thank you so much for the effort to help, but sadly idk why it does not seem to work, i will try to implement this with a json config file, hope i have more luck! – Flamiing Oct 14 '22 at 23:52
  • What is your expected value for true? – Start-Automating Oct 15 '22 at 00:57
  • I was expecting that `$WINTERMINAL` to return true but i think i finally solved the problem. Thanks to the help i was able to figure out what i was doing wrong which was several things. – Flamiing Oct 15 '22 at 01:12