PowerShell alias - No restrictions on name - powershell

I have written a simple SetDifference function, by using the Compare-Object function:
Function SetDifference {
param(
[Parameter(Mandatory=$true)]$ReferenceObject,
[Parameter(Mandatory=$true)]$DifferenceObject
)
Compare-Object $ReferenceObject $DifferenceObject |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { $_.InputObject }
}
I've noticed that ANY alias can be used without PowerShell complaining:
Set-Alias '\' 'SetDifference'
Set-Alias '.' 'SetDifference'
Set-Alias '+' 'SetDifference'
Shouldn't there be restrictions on what the alias name can be - to stop you from using symbols that are already part of PowerShell syntax?

You should get an error, when using i.e. the '+'.
See here, you should follow this: "You can use any alphanumeric characters in an alias, but the first character cannot be a number."
Also resuing an already defined alias will throw an error.

Related

Powershell Compare string to folders

I am completely new to Powershell and I want to know if a language code is contained on a folder list. I am using this little script.
set-executionpolicy remotesigned -Scope CurrentUser
$path = "C:\Projects\Eg_Proyect\2022_834"
$lang = "DE-DE"
$Lsta2 = Get-ChildItem -Path $path -Name
$Lsta2
$Lsta2.Count
$Lsta2 -contains $lang
The result is:
0_SOURCE
10_EN-GB_PL
11_EN-GB_CS
12_EN-GB_DE-DE
13_EN-GB_TR
1_EN-GB_ES-ES
2__
3_EN-GB_IT-IT
4_EN-GB_IT-IT
5_EN-GB_HU
6_EN-GB_HU
7_EN-GB_NL-NL
8_EN-GB_NL-NL
9_EN-GB_PT-PT
14
**False**
Why it does not return True?
There is always confusion about the string method .Contains() which looks to find a certain substring withing another string and the PowerShell -contains operator, which looks for a complete, exact (case-insensitive) item in an array.
Since in your case you have an array of strings, you could use:
[bool]($Lsta2 -match 'DE-DE') # uses RegEx. returns True or False because of the cast to `[bool]`
OR
[bool]($Lsta2 -like '*DE-DE*') # uses WildCards ('*' and/or '?')
OR use the .Contains() string operator on every string individually. This is of course a waste of time, AND it works Case-Sensitively, but to show that it can be done:
[bool]($Lsta2 | ForEach-Object { if ($_.Contains('DE-DE')) { $true }})
You can use -match to search with a regex in a string
$Lsta2 -match $lang

Powershell: ConvertFrom-Json doesn't get the variable assigned due to forward and backward compatibility

I am trying to load a variables into powershell from variables.json having the following
{
"psfp": "C:/San\/SV65\/ps",
"vmfp": "'C:/San\/SV65\/hyper-packer\/hyper-packer\/output-centos8-9\/Virtual Machines'",
"psmp": "C:/San\/SV65\/ps",
"vmname": ""
}
Trying to import with
$jvariables=Get-Content -Raw -Path '.\variables-ps.json' | ConvertFrom-Json
Output on powershell
PS C:\San\SV65\ps> Write-host $jvariables.psfp
C:/San/SV65/ps
PS C:\San\SV65\ps> Write-host $jvariables.vmfp
'C:/San/SV65/hyper-packer/hyper-packer/output-centos8-9/Virtual Machines'
PS C:\San\SV65\ps> Write-host $jvariables.psmp
C:/San/SV65/ps
These forward slash not incompatible on powershell for a windows path! ConvertFrom-Json doesn't accept backslash on the variables tried with '' as well
Hence could not load my modules on these path
any other way to achieve the above case?
Want to use json as it easy for the end user to update rather a txt files
Please share
you can loop through the object properties and change the path separator like this:
$jvariables.psobject.properties | where {$_.membertype -eq "NoteProperty"} |
foreach {$data.($_.name) = $_.value.replace("/","\")}
or a simpler approach would be to escape backslash in config file, like this :
{
"psfp": "C:\\San\\SV65\\ps",
"vmfp": "'C:\\San\\SV65\\hyper-packer\\hyper-packer\\output-centos8-9\\Virtual Machines'",
"psmp": "C:\\San\\SV65\\ps",
"vmname": ""
}

Is there a way to show all functions in a PowerShell script?

Is there any command to list all functions I've created in a script?
Like i created function doXY and function getABC or something like this.
Then I type in the command and it shows:
Function doXY
Function getABC
Would be a cool feature^^
Thanks for all your help.
You can have PowerShell parse your script, and then locate the function definitions in the resulting Abstract Syntax Tree (AST).
Get-Command is probably the easiest way to access the AST:
# Use Get-Command to parse the script
$myScript = Get-Command .\path\to\script.ps1
$scriptAST = $myScript.ScriptBlock.AST
# Search the AST for function definitions
$functionDefinitions = $scriptAST.FindAll({
$args[0] -is [Management.Automation.Language.FunctionDefinitionAst]
}, $false)
# Report function name and line number in the script
$functionDefinitions |ForEach-Object {
Write-Host "Function '$($_.Name)' found on line $($_.StartLineNumber)!"
}
You can also use this to analyze the functions' contents and parameters if necessary.
Where your script is named things.ps1, something like...
cat ./things.ps1 | grep function
For MacOS/Linux or...
cat ./things.ps1 | select-string function
For Windows.
This is a built-in feature as shown in the PowerShell help files.
About_Providers
Similar questions have been asked before. So, this is a potential duplicate of:
How to get a list of custom Powershell functions?
Answers... Using the PSDrive feature
# To get a list of available functions
Get-ChildItem function:\
# To remove a powershell function
# removes `someFunction`
Remove-Item function:\someFunction
Or
Function Get-MyCommands {
Get-Content -Path $profile | Select-String -Pattern "^function.+" | ForEach-Object {
[Regex]::Matches($_, "^function ([a-z.-]+)","IgnoreCase").Groups[1].Value
} | Where-Object { $_ -ine "prompt" } | Sort-Object
}
Or this one
Get List Of Functions From Script
$currentFunctions = Get-ChildItem function:
# dot source your script to load it to the current runspace
. "C:\someScript.ps1"
$scriptFunctions = Get-ChildItem function: | Where-Object { $currentFunctions -notcontains $_ }
$scriptFunctions | ForEach-Object {
& $_.ScriptBlock
}
As for this...
Thanks, this is kind of what i want, but it also shows functions like
A:, B:, Get-Verb, Clear-Host, ...
That is by design. If you want it another way, then you have to code that.
To get name of functions in any script, it has to be loaded into memory first, then you can dot source the definition and get the internals. If you just want the function names, you can use regex to get them.
Or as simple as this...
Function Show-ScriptFunctions
{
[cmdletbinding()]
[Alias('ssf')]
Param
(
[string]$FullPathToScriptFile
)
(Get-Content -Path $FullPathToScriptFile) |
Select-String -Pattern 'function'
}
ssf -FullPathToScriptFile 'D:\Scripts\Format-NumericRange.ps1'
# Results
<#
function Format-NumericRange
function Flush-NumberBuffer
#>
This function will parse all the functions included in a .ps1 file, and then will return objects for each function found.
The output can be piped directly into Invoke-Expression to load the retuned functions into the current scope.
You can also provide an array of desired names, or a Regular Expression to constrain the results.
My use case was I needed a way for loading individual functions from larger scripts, that I don't own, so I could do pester testing.
Note: only tested in PowerShell 7, but I suspect it will work in older versions too.
function Get-Function {
<#
.SYNOPSIS
Returns a named function from a .ps1 file without executing the file
.DESCRIPTION
This is useful where you have a blended file containing functions and executed instructions.
If neither -Names nor -Regex are provided then all functions in the file are returned.
Returned objects can be piped directly into Invoke-Expression which will place them into the current scope.
Returns an array of objects with the following
- .ToString()
- .Name
- .Parameters
- .Body
- .Extent
- .IsFilter
- .IsWorkFlow
- .Parent
.PARAMETER -Names
Array of Strings; Optional
If provided then function objects of these names will be returned
The name must exactly match the provided value
Case Insensitive.
.PARAMETER -Regex
Regular Expression; Optional
If provided then function objects with names that match will be returned
Case Insensitive
.EXAMPLE
Get all the functions names included in the file
Get-Function -name TestA | select name
.EXAMPLE
Import a function into the current scope
Get-Function -name TestA | Invoke-Expression
#>
param (
$File = "c:\fullpath\SomePowerShellScriptFile.ps1"
,
[alias("Name", "FunctionNames", "Functions")]
$Names
,
[alias("NameRegex")]
$Regex
) # end function
# get the script and parse it
$Script = Get-Command /Users/royomi/Documents/dev/javascript/BenderBot_AI/Import-Function.ps1
$AllFunctions = $Script.ScriptBlock.AST.FindAll({$args[0] -is [Management.Automation.Language.FunctionDefinitionAst]}, $false)
# return all requested functions
$AllFunctions | Where-Object { `
( $Names -and $Names -icontains $_.Name ) `
-or ( $Regex -and $Names -imatch $Regex ) `
-or (-not $Names -and -not $Regex) `
} # end where-object
} # end function Get-Function

How do I invoke a powershell script to define a function so one can use it in the calling powershell script?

Suppose I have scripts AAA.ps1 and script BBB.ps1. Assume they are in the same location (directory).
Script BBB.ps1 defines a function BFunc which I want to invoke from AAA.ps1
How do I modify AAA.ps1 so that it can define-and-use BFunc?
As a test I have tried the following two commands in a script.
& "$PSScriptRoot\BBB.ps1"
get-childitem function:* | Select-Object Name | where { $_ -match "BFunc" }
If the above worked then I should see some output that BFunc is defined but nothing comes out.
Ah, sometimes it is too simple. It turns out that what PS expects is that BBB.ps1 be included into AAA.ps1. This means that the AAA.ps1 file could look like this:
. "$PSScriptRoot\BBB.ps1"
get-childitem function:* | Select-Object Name | where { $_ -match "BFunc" }
And that works!

PowerShell if -like error

Not sure what's wrong with this script
$SSODelete= "Delete"
$SSOfiles = "SSo.xml"
$channlename = "INC8-Patch"
write-host $channlename
if ($channelname -like *INC8*){
$SSOarg = "$SSODelete $SSOfiles"
Write-Host $SSOarg
}
It throws following error:
You must provide a value expression following the '*' operator.
At line:5 char:25
+ if ($channelname -like *INC8*){
+ ~~~~~
Unexpected token 'INC8*' in expression or statement.
Tried using "*INC8*" and '*INC8' but it then it does not qualify if statement.
Adding screenshot for script and it's results
Simple Script and results
The PowerShell -like operator should be used with the matching string quoted, e.g., $variable -like "*pattern*". -like accepts the simple wildcard (*) only; you can compare against regular expressions (regexps) by using -match. See Get-Help about_Comparison_Operators.
Thanks , it was due to variable name i was comparing ... i need to be more cautious