I have below command and it returns me null object . When I run the command separately in PowerShell window I get the right result. Below is my PowerShell method which is calling the command and the also the PowerShell command which I have defined. I am basically looking to return a string value. Please let me know what wrong am I doing?
C# method:
public string RunScript( string contentScript, Dictionary<string, EntityProperty> parameters)
{
List<string> parameterList = new List<string>();
foreach( var item in parameters )
{
parameterList.Add( item.Value.ToString() );
}
using( PowerShell ps = PowerShell.Create() )
{
ps.AddScript( contentScript );
// in ContentScript I get "Get-RowAndPartitionKey" on debugging
ps.AddParameters( parameterList );//I get list of strings
IAsyncResult async = ps.BeginInvoke();
StringBuilder stringBuilder = new StringBuilder();
foreach( PSObject result in ps.EndInvoke( async ) )
// here i get result empty in ps.EndInvoke(async)
{
stringBuilder.AppendLine( result.ToString() );
}
return stringBuilder.ToString();
}
}
}
My Powershell GetRowAndPartitionKey
cmdlet definition, which the code above is trying to call:
public abstract class GetRowAndPartitionKey : PSCmdlet
{
[Parameter]
public List<string> Properties { get; set; } = new List<string>();
}
[Cmdlet( VerbsCommon.Get, "RowAndPartitionKey" )]
public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKey
{
protected override void ProcessRecord()
{
string rowKey = string.Join( "_", Properties );
string pKey = string.Empty;
WriteObject( new
{
RowKey = rowKey,
PartitionKey = pKey
} );
}
}
}
When using the PowerShell SDK, if you want to pass parameters to a single command with
.AddParameter()
/.AddParameters()
/AddArgument()
, use.AddCommand()
, not.AddScript()
.AddScript()
is for passing arbitrary pieces of PowerShell code that is executed as a script block to which the parameters added with.AddParameters()
are passed.That is, your invocation is equivalent to
& { Get-RowAndPartitionKey } <your-parameters>
, and as you can see, yourGet-RowAndPartitionKey
command therefore doesn't receive the parameter values.See this answer or more information.
Note: As a prerequisite for calling your custom
Get-RowAndPartitionKey
cmdlet, you may have to explicitly import the module (DLL) that contains it, which you can do:either: with a separate, synchronous
Import-Module
call executed beforehand (for simplicity, I'm using.AddArgument()
here, with passes an argument positionally, which binds to the-Name
parameter (which also accepts paths)):or: as part of a single (in this case asynchronous) invocation - note the required
.AddStatement()
call to separate the two commands:"<your-module-path-here>"
refers to the full file-system path of the module that contains theGet-RowAndPartitionKey
cmdlet; depending on how that module is implemented, it is either a path to the module's directory, its.psd1
module manifest, or to its.dll
, if it is a stand-alone assembly.Alternative import method, using the PowerShell SDK's dedicated
.ImportPSModule()
method:This method obviates the need for an in-session
Import-Module
call, but requires extra setup:.ImportPSModule()
on it to import the module.PowerShell.Create()
Caveat: A
PowerShell
instance reflects its initial session state in.Runspace.InitialSessionState
, but as a conceptually read-only property; the tricky part is that it is technically still modifiable, so that mistaken attempts to modify it are quietly ignored rather than resulting in exceptions.To troubleshoot these calls:
Check
ps.HadErrors
after.Invoke()
/.EndInvoke()
to see if the PowerShell commands reported any (non-terminating) errors.Enumerate
ps.Streams.Errors
to inspect the specific errors that occurred.See this answer to a follow-up question for self-contained sample code that demonstrates these techniques.