Auto Complete User Input PowerShell 2.0 - powershell

I have a large list of data (over 1000 different values) and I want the user to be able to select certain values from the list from a PowerShell console.
What is the easiest way from within the console to allow the user to quickly select values?
I would like to do something like tab completion or the ability to use the arrow keys to scroll through the values but I am not sure how to do either of these things.
Any advice would be greatly appreciated.

PowerShell tab completion can be extended to custom parameters and parameter values (in v3). However, this is a property of advanced functions. You can use the ValidateSetAttribute to do that.
Check the Technet help topic on advanced functions: http://technet.microsoft.com/en-us/library/hh847806.aspx
You can replace the tabexpansion (v2) and tabexpansion2 (v3) function in PowerShell to auto complete parameter values outside of advanced functions. You can get a basic definition of this in PowerShell v3 by running
Get-Content function:TabExpansion2
Here is an example of showing custom tab expansion function.
http://www.powershellmagazine.com/2012/11/29/using-custom-argument-completers-in-powershell-3-0/
But, if you want to the user to be able to auto complete values for a Read-Host kind of input, you need to write a proxy for Read-Host to achieve that.
You can, optionally, look at PowerTab module at http://powertab.codeplex.com/

For folks who are looking for a way to do this and are fortunate enough to be using PS v3 (and my apologies for all those required to stay with V2):
The easiest way to achieve this is using the "ValidateSet" option in your input parameters.
function Show-Hello {
param (
[ValidateSet("World", "Galaxy", "Universe")]
[String]$noun
)
$greetingString = "Hello, " + $noun + "!"
Write-Host "`t=>`t" $greetingString "`t<="
}
ValidateSet throws an error if a user attempts to use any other input:
Show-Hello "Solar System"
Show-Hello : Cannot validate argument on parameter 'noun'. The argument `
"Solar System" does not belong to the set "World,Galaxy,Universe" specified `
by the ValidateSet attribute. Supply an argument that is in the set and `
then try the command again.
It also adds tab-completion to your function for that parameter. And if it is the FIRST parameter for your function, you don't even have to type in "-noun" for the tab-complete to make suggestions for its value.

Related

Best way to pass parameters to SparkSubmitOperator

So far i have been providing all required variables in the "application" field in the file itself this however feels a bit hacky.
So for example:
spark_clean_store_data = SparkSubmitOperator(
task_id="my_task_id",
application="/path/to/my/dags/scripts/clean_store_data.py",
conn_id="spark_conn",
dag=dag,
)
So the question is what is the most airflowy/proper way to provide SparkSubmitOperator with parameters like input data and or output files?
As per documentation, you might consider using the following parameters of the SparkSubmitOperator
files : a comma-separated string that allows you to upload files in the working directory of each executor
application_args : a list of string that allows you to pass arguments to the application

How to set a cloudformation parameter to a powershell variable

Trying to simply run some powershell in my cloudformation based on a user inpute parameter in cloudformation.
This works
write-host ${CFParameter} >> C:\temp\log.txt
but this does not
$PSVariable = ${CFParameter}
write-host $PSVariable >> C:\temp\log.txt
the second one just returns a blank line but the first one returns the correct information
If your powershell is being used in userdata and you can use ref function to refer to the parameter. I would recommend using cloudkast which is an online cloudformation template generator. It makes it easy to generate cloudformation templates.

Powershell returns wrong result

I came across this weird issue in Powershell (not in other languages). Could anyone please explain to me why this happened?
I tried to return a specified number (number 8), but the function keeps throwing everything at me. Is that a bug or by design?
Function GetNum() {
Return 10
}
Function Main() {
$Number10 = GetNum
$number10 #1 WHY NO OUTPUT HERE ??????? I don't want to use write host
$result = 8 # I WANT THIS NUMBER ONLY
PAUSE
return $result
}
do {
$again = Main
Write-Host "RESULT IS "$again # Weird Result, I only want Number 8
} While ($again -eq 10) # As the result is wrong, it loops forever
Is that a bug or by design?
By design. In PowerShell, cmdlets can return a stream of objects, much like using yield return in C# to return an IEnumerable collection.
The return keyword is not required for output values to be returned, it simply exits (or returns from) the current scope.
From Get-Help about_Return (emphasis added):
The Return keyword exits a function, script, or script block. It can be
used to exit a scope at a specific point, to return a value, or to indicate
that the end of the scope has been reached.
Users who are familiar with languages like C or C# might want to use the
Return keyword to make the logic of leaving a scope explicit.
In Windows PowerShell, the results of each statement are returned as
output, even without a statement that contains the Return keyword.
Languages like C or C# return only the value or values that are specified
by the Return keyword.
Mathias is spot on as usual.
I want to address this comment in your code:
$number10 #1 WHY NO OUTPUT HERE ??????? I don't want to use write host
Why don't you want to use Write-Host? Is it because you may have come across this very popular post from PowerShell's creator with the provocative title Write-Host Considered Harmful?
If so, I encourage you to read what I think is a great follow-up/companion piece by tby, titled Is Write-Host Really Harmful?
With this information, it should be clear that as Mathias said, you are returning objects to the pipeline, but you should also be armed with the information needed to choose an alternative, whether it's Write-Verbose, Write-Debug, or even Write-Host.
If I were going to be opinionated about it, I would go with Write-Verbose, altering your function definition slightly in order to support it:
function Main {
[CmdletBinding()]
param()
$Number10 = GetNum
Write-Verbose -Message $number10
$result = 8 # I WANT THIS NUMBER ONLY
PAUSE
$result
}
When you invoke it by just calling $again = Main you'll see nothing on the screen, and $again will have a value of 8. However if you call it this way:
$again = Main -Verbose
then $again will still have the value of 8, but on the screen you'll see:
VERBOSE: 10
likely in differently colored text.
What that gives is not only a way to show the value, but a way for the caller to control whether they see the value or not, without changing the return value of the function.
To drive some of the points in the articles home further, consider that it's not necessarily necessary to invoke your function with -Verbose to get that.
For example, let's say you stored that whole script in a file called FeelingNum.ps1.
If, in addition to the changes I made above, you also add the following to the very top of your file:
[CmdletBinding()]
param()
Then, you still invoked your function "normally" as $again = Main, you could still get the verbose output by invoking your script with -Verbose:
powershell.exe -File FeelingNum.ps1 -Verbose
What happens there is that using the -Verbose parameter sets a variable called $VerbosePreference, and that gets inherited on each function called down the stack (unless it's overridden). You can also set $VerbosePreference manually.
So what you get by using these built-in features is a lot of flexibility, both for you as the author and for anyone who uses your code, which is a good thing even if the only person using it is you.

how to disable 2nd parameter we select 1st parameter in crystal reports

Please guide how to do this requirement.
I Have a report having 2 command level parameters a and b.
If they select any of the one parameter then other one should be disabled/should not ask any value to enter /should not take any value .
Please suggest how to do
Command don't support optional parameters. Moreover, you can't disable or hide a parameter based on another parameter's value.
Your best option is to create a parameter that has a default value that will be 'ignored' by the query.
For example, given this Access command:
SELECT *
FROM customer
WHERE region='{?Region}'
with this parameter:
you will note that the parameter's Optional Prompt setting is false (and not editable):
Instead, you will need to a default, something like 'ALL' (or -1, in the case of a numeric value):
Modify the command accordingly:
SELECT *
FROM customer
WHERE ( '{?Region}'='ALL' OR region='{?Region}' )
This should be a feature of the user interface. You can implement it if you write your own software. The only viewer , which MIGHT be able to do this is R-Tag (www.r-tag.com). But even it will need to do some workaround ( if can do it at all). This behavior is very unique. Why would you need to have it ?

Text input through SSRS parameter including a Field name

I have a SSRS "statement" type report that has general layout of text boxes and tables. For the main text box I want to let the user supply the value as a parameter so the text can be customized, i.e.
Parameters!MainText.Value = "Dear Mr.Doe, Here is your statement."
then I can set the text box value to be the value of the parameter:
=Parameters!MainText.Value
However, I need to be able to allow the incoming parameter value to include a dataset field, like so:
Parameters!MainText.Value = "Dear Mr.Doe, Here is your [Fields!RunDate.Value] statement"
so that my report output would look like:
"Dear Mr.Doe, Here is your November statement."
I know that you can define it to do this in the text box by supplying the static text and the field request, but I need SSRS to recognize that inside the parameter string there is a field request that needs to be escaped and bound.
Does anyone have any ideas for this? I am using SSRS 2008R2
Have you tried concatenating?
Parameters!MainText.Value = "Dear Mr.Doe, Here is your" & [Fields!RunDate.Value] & "statement"
There are a few dramatically different approaches. To know which is best for you will require more information:
Embedded code in the report. Probably the quickest to
implement would be embedded code in the report that returned the
parameter, but called String.Replace() appropriately to substitute
in dynamic values. You'll need to establish some code for the user for which strings will be replaced. Embedded code will get you access to many objects in the report. For example:
Public Function TestGlobals(ByVal s As String) As String
Return Report.Globals.ExecutionTime.ToString
End Function
will return the execution time. Other methods of accessing parameters for the report are shown here.
1.5 If this function is getting very large, look at using a custom assembly. Then you can have a better authoring experience with Visual Studio
Modify the XML. Depending on where you use
this, you could directly modify the .rdl/.rdlc XML.
Consider other tools, such as ReportBuilder. IF you need to give the user
more flexibility over report authoring, there are many tools built
specifically for this purpose, such as SSRS's Report Builder.
Here's another approach: Display the parameter string with the dataset value already filled in.
To do so: create a parameter named RunDate for example and set Default value to "get values from a query" and select the first dataset and value field (RunDate). Now the parameter will hold the RunDate field and you can use it elsewhere. Make this parameter hidden or internal and set the correct data type. e.g. Date/Time so you can format its value later.
Now create the second parameter which will hold the default text you want:
Parameters!MainText.Value = "Dear Mr.Doe, Here is your [Parameters!RunDate.Value] statement"
Not sure if this syntax works but you get the idea. You can also do formatting here e.g. only the month of a Datetime:
="Dear Mr.Doe, Here is your " & Format(Parameters!RunDate.Value, "MMMM") & " statement"
This approach uses only built-in methods and avoids the need for a parser so the user doesn't have to learn the syntax for it.
There is of course one drawback: the user has complete control over the parameter contents and can supply a value that doesn't match the report content - but that is also the case with the String Replace method.
And just for the sake of completeness there's also the simplistic option: append multiple parameters: create 2 parameters named MainTextBeforeRunDate and MainTextAfterRunDate.
The Textbox value expression becomes:
=Parameters!MainTextBeforeRunDate.Value & Fields!RunDate.Value & Parameters!MainTextAfterRunDate.Value.
This should explain itself. The simplest solution is often the best, but in this case I have my doubts. At least this makes sure your RunDate ends up in the final report text.