PowerShell Native Cmdlet Set-Alias with Function and Switch - powershell

Question:
Is it possible to set an alias that calls both a function and a switch?
Here is an example I am working with.
Set-Alias -Name myidea -Value 'Test-FunctionIdea -SwitchIdea'
function Test-FunctionIdea {
param(
[switch]$SwitchIdea
)
if($SwitchIdea)
{
Write-Host 'Good Idea'
}
}
Here is the error I am having:
myidea : The term 'Test-FunctionIdea -SwitchIdea' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if
a path was included, verify that the path is correct and try again.
At line:1 char:1
+ myidea
+ ~~~~~~
+ CategoryInfo : ObjectNotFound: (Test-FunctionIdea -SwitchIdea:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
If it is possible please let me know how it's done. I've searched the internet for this and came up with no results.

You can check $MyInvocation.InvocationName and adjust the parameters inside the function:
function Some-Function([switch] $foo) {
if ($MyInvocation.InvocationName -eq 'foo') { $foo = $true }
}
Set-Alias foo Some-Function
The [usually negligible] advantage is that it doesn't create an additional execution context for the new function scope.

Related

Write-Error doesn't result useful information when used inside class methods | Powershell

I used a method with and without a class and the Write-Error seems to produce different outputs. In case of class, it doesn't specify the function and the line number is always 1,1
function oper1() {
Try {
[string] $cmd = ".\some_exe_which_does_not_exist.exe"
iex $cmd
}
Catch {
Write-Error $_.Exception.Message
}
}
oper1
Output for above:
oper1 : The term '.\some_exe_which_does_not_exist.exe' is not
recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again. At
F:\debug\encryption_concat_tests\Untitled1.ps1:11 char:1
+ oper1
+ ~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,oper1
When I enclosed the same function in a class, I got this:
class Operator {
[void] oper1() {
Try {
[string] $cmd = ".\some_exe_which_does_not_exist.exe"
iex $cmd
}
Catch {
Write-Error $_.Exception.Message
}
}
}
[Operator] $operator = New-Object Operator
$operator.oper1()
The term '.\some_exe_which_does_not_exist.exe' is not recognized as
the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify
that the path is correct and try again. At line:1 char:1
+ F:\debug\encryption_concat_tests\Untitled1.ps1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
What could be the reason for this behaviour for methods inside classes?
As an aside: Invoke-Expression (iex) should generally be avoided; definitely don't use it to invoke an external program - just invoke it directly, as shown below.
In PowerShell class methods:
Do not use Write-Error, as classes are not designed to emit non-terminating errors.
The only reason you're seeing any output at all is a bug as of PowerShell Core 7.0.0-rc.3 with methods whose return type happens to be [void] - see GitHub issue #5331.
Instead, communicate errors solely by throwing them with the Throw statement or by not catching terminating errors (which include exceptions from .NET methods and cmdlet calls with -ErrorAction Stop).
Note: Throw and -ErrorAction Stop (or $ErrorActionPreference = 'Stop') create script-terminating (thread-terminating) errors, whereas exceptions thrown by a .NET method (not caught and re-thrown in the class method) only create statement-terminating errors; that is, while the class-method body is terminated right away, execution continues in the caller by default; the latter also applies to the call operator (&) not finding an executable, errors in expressions such as 1 / 0, and cmdlet calls that emit statement-terminating errors (the most severe error type they can report) without their being promoted to script-terminating ones with -ErrorAction Stop; see this GitHub docs issue for a comprehensive overview of PowerShell's complex error handling.
See this answer for more information about error handling and stream-output behavior in class methods in particular.
Here's a corrected version of your code.
class Operator {
[void] oper1() {
Try {
# Try to invoke a non-existent executable.
& ".\some_exe_which_does_not_exist.exe"
}
Catch {
# Re-throw the error.
# Alternatively, don't use try / catch, but the error
# then only aborts the method call, not the entire script.
Throw
}
}
}
$operator = [Operator]::new()
$operator.oper1()
I also have this problem! But I really wanted to figure out how to output information and return the desired type of information from the function!
I solved the problem using Write-Warning
[bool] hidden AddUserToGroup([Microsoft.ActiveDirectory.Management.ADGroup]$group, [Microsoft.ActiveDirectory.Management.ADUser]$user)
{
try
{
Add-ADGroupMember -Server $this.server -Identity $group -Members $user;
return $true;
}
catch [System.SystemException]
{
Write-Warning $_.Exception.Message;
return $false;
}
}

Parsing a web page for text

I'm trying to search a webpage for a word "Green". It tells me things are fine but if it finds "Red" it tells me things are bad. What I've done below is very simple but I'm thinking its enough to ask the question.
$web = Invoke-WebRequest http://myip/vrsinfo/aghealth/DISTAGAR
$web.ToString() -split "[`r`n]" | Select-String "Green"
Here is what it returns
name="agSolarwindsHealth" value=Green readonly>
Here is what I've tried so far
if (name="agSolarwindsHealth" value=Green readonly>) {
'This number is 1'
} else {
'This number is not 1'
}
Error
name=agSolarwindsHealth : The term 'name=agSolarwindsHealth' is not recognized
as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct
and try again.
At line:3 char:5
+ if (name="agSolarwindsHealth" value=Green readonly>)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (name=agSolarwindsHealth:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Powershell scripting help needed

I am very new to powershell scripting. Trying to learn it from web. Now I am trying to do a script and facing some problem, so need some help ans suggestions from you people. I am giving description what I tried to do:
first of all I have declared 2 variables, then I used if statement to see if the variables are empty then it will show a warning message and it will ask for the inputs from the user and after that it will show the value of the variables. but it is giving some errors.
$workingdirectory = args[0]
$directoryname = args[1]
if ("$WorkingDirectory" -eq "")
{
Write-Warning "Parameter Required"
$WorkingDirectory = Read-Host "Enter the absolute path to working directory "
}
if ("$DirectoryName" -eq "")
{
Write-Warning "Paramater Required"
$DirectoryName = Read-Host "Enter a directory name to search for in $WorkingDirectory "
}
Write-Host "$WorkingDIrectory"
write-host "$DirectoryName"
When I run it, it is showing the following errors:
ARGS[0] : The term 'ARGS[0]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\LAB_5-submission\mmbillah1_Lab_testdir.ps1:24 char:21
+ $WorkingDirectory = ARGS[0]
+ ~~~~~~~
+ CategoryInfo : ObjectNotFound: (ARGS[0]:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
ARGS[1] : The term 'ARGS[1]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\LAB_5-submission\mmbillah1_Lab_testdir.ps1:25 char:18
+ $DirectoryName = ARGS[1]
+ ~~~~~~~
+ CategoryInfo : ObjectNotFound: (ARGS[1]:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I want to run like this: .\scriptname.ps1, if I use this then it will show the warning and ask for the two variables input.
and if I run this .\scriptname.ps1 C:\users\masum then it will ask for the second variable value only.
The root of your problem is simply syntax it should be $args[0] and $args[1] if you intend to use what you have now. What I would strongly suggest instead is to create parameters for your script, and then test if those parameters are valid, and if they aren't to prompt for them.
Parameters can be defined in a Param() block as such:
Param(
$workingdirectory,
$directoryname
)
That is very simple, but for your needs it works. You can add types to make sure the right kinds of things are passed as the parameter, and add tests to make sure the parameters are valid, but that goes beyond what we're doing here.
Then you would check to make sure that there is a value for each, and I would recommend making sure that the path is valid. Something like:
While([string]::IsNullOrEmpty($workingdirectory) -or !(Test-Path $workingdirectory)){
$workingdirectory = Read-Host "Enter a valid working directory"
}
That checks if the $workingdirectory variable is empty or just blank spaces, and if it actually has a value it will check to make sure it's a valid directory. If it is blank or the path isn't valid it prompts the user to enter a valid path. You would need to repeat that for the $directoryname variable.
So you would end up with something like:
Param(
$workingdirectory,
$directoryname
)
While([string]::IsNullOrEmpty($workingdirectory) -or !(Test-Path $workingdirectory)){
$workingdirectory = Read-Host "Enter a valid working directory"
}
While([string]::IsNullOrEmpty($directoryname) -or !(Test-Path $directoryname)){
$directoryname= Read-Host "Enter a valid target directory"
}
Write-Host $workingdirectory
Write-Host $directoryname

Powershell script with params *and* functions

I want to write a powershell script that takes in params and uses functions.
I tried this:
param
(
$arg
)
Func $arg;
function Func($arg)
{
Write-Output $arg;
}
but I got this:
The term 'Func' is not recognized as the name
of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At func.ps1:6 char:5
+ Func <<<< $arg;
+ CategoryInfo : ObjectNotFound: (Func:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Fine, I thought. I'll try this instead:
function Func($arg)
{
Write-Output $arg;
}
param
(
$arg
)
Func $arg;
But then, I got this:
The term 'param' is not recognized as the name
of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At C:\Users\akina\Documents\Work\ADDC\func.ps1:7 char:10
+ param <<<<
+ CategoryInfo : ObjectNotFound: (param:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Is what I'm asking for doable? Or am I being unreasonable in my request?
The param block in a script has to be the first non-comment code. After that, you need to define the function before you invoke it e.g.:
param
(
$arg
)
function Func($arg)
{
$arg
}
Func $arg
The Write-Output is unnecessary in your example since the default behavior is to output objects to the output stream.
All you need ius to make sure PARAM is first string of your script.
You can put the param tag inside the function..
Something like this:
function func($avg)
{
param
(
$avg
)
}

powershell: how to print the total call stacks when error happen?

suppose I have the following code, when the error happens, I'd like to see the error that the error first happened at function b, and then happened at function a. But in fact it only tells me the error happen at function a, since function a could be called many times, I don't know which outer function calling function a caused the problem
cls
function a{
Remove-Item "not-exist-item"
}
function b{
a
}
b
Remove-Item : Cannot find path 'C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\not-exis
t-item' because it does not exist.
At C:\Users\Daniel.Wu\AppData\Local\Temp\2\a.ps1:***3 char:14***
+ Remove-Item <<<< "not-exist-item"
+ CategoryInfo : ObjectNotFound: (C:\Program File...\not-exist-item:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
If you are on PowerShell v2.0, use Get-PSCallStack. If you're still on v1, use a function like this:
function Get-CallStack {
trap { continue }
1..100 | foreach {
$var = Get-Variable -scope $_ MyInvocation
$var.Value.PositionMessage -replace "`n"
}
}
One option is to set
$ErrorActionPreference = 'inquire'
and then invoke the problematic script. On error you are prompted for choices, choose Suspend to enter into the nested prompt mode. Then type
Get-PSCallStack
or even
Get-PSCallStack | fl
to get the current call stack information.
Does get-help about_debuggers provide any illumination?