Question

I'm writing Cmdlets that interface with Google Apps API and require Oauth2 authentication. If a user tries to run a Cmdlet without being authenticated and it's more than just refreshing a token, I need them to enter in an access code provided from a browser. (That's all taken care of.) I'd like to pause the cmdlet when this is necessary, wait for their input and then only continue once verified.

However, I right now can only do this by throwing an error to quit the current Cmdlet and then instruct the user to pass the Access Code as an argument to another Cmdlet (clunky).

I've been looking for a way to call something like C#'s Console.Readline (this just gets skipped over when executing the cmdlet) or trying to invoke the Read-Host cmdlet; once I get the access code from the user the code could continue to execute as normal. I know it's not necessarily the 'Powershell Way' but for the sake of these tools, I feel it's the best option for the user.

If I try this method:

ReadHostCommand read = new ReadHostCommand();
read.prompt = "Access Code";
foreach (string s in read.Invoke<string>()) {
    WriteObject(s);
}

I get an error: Cmdlets derived from PSCmdlet cannot be invoked directly.

Search that error lead my to try creating a new Host object as follows I get another error (also following):

PowerShell ps = PowerShell.Create();
ps.AddCommand("Read-Host");
foreach (PSObject result in ps.Invoke()) {
    WriteObject(result);
}

Read-Host : A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.

Is there a way to pause the cmdlet to get a string from the user?

Edit: To clarify, I'm writing Cmdlets to be run from within Powershell Console or ISE or similar, and need to get input from the user mid-cmdlet-execution.

Was it helpful?

Solution

If your cmdlet derives from PSCmdlet then use the this.InvokeCommand.InvokeScript() to invoke the Read-Host cmdlet. Or you could use the this.Host.UI.Prompt*/Read*() methods.

OTHER TIPS

Sounds like you actually need to implement the PSHost (along with the PSHostUserInterface and PSHostRawUserInterface classes). In doing so, you will implement the functionality to interact with the user with read-host and write-host (probably using console.readline).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top