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
CodePudding user response:
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.
CodePudding user response:
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
)- GitHub issue #9035, which was declined, asked for INI-file support, in the context of which TOML support was discussed too.
- As of this writing, there are no TOML modules in the PowerShell Gallery.
- You can use a .NET library such as
Tomlyn
directly, but use of NuGet packages in PowerShell is currently cumbersome, unfortunately - see this answer for an example.
- You can use a .NET library such as
[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.