Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > PowerShell

Vista Tutorial - Hosting Powershell in App - Obtaining delegates to powershellfunctions

Reply
 
Old 01-31-2008   #1 (permalink)
thoward37
Guest


 
 

Hosting Powershell in App - Obtaining delegates to powershellfunctions

Hi all, this is a follow-up to an earlier post I made regarding
embedded Powershell:

http://groups.google.com/group/micro...b8489ea0411486


In short, I'm hosting Powershell in an app as part of a rules engine,
using it to repeatedly execute user defined scripts on data provided
from a database, as one kind of "rule".

The way I initially implemented it was to create a single runspace,
then create and execute a new pipeline eachtime I needed to execute
the Powershell rule.

An example rule looks like this:

$dataValue =
$dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
$checkValue = $dataProviders[""StaticData""].GetValue(""MaxValue"");
if ($dataValue -eq $checkValue) { exit 5 } else { exit 0 }

The variable $dataProviders is a dictionary containing various data
providers that allow the Powershell script to make some decisions
about some data. It is passed into the Powershell world using a
statement like ...
Runspace.SessionStateProxy.SetVariable("dataProviders",
dataProviders); ... and it's updated each time I execute a pipeline
with the currently available data.

The exit code of the pipeline is checked to get the result of the
rule, which is then evaluated by the rest of the rule engine.

So, my previous post I had asked about ways to re-use a single
pipeline, instead of instantiating a new one everytime, but found that
was not possible.

Currently, this implementation works, but it's very slow, and there
are other options available for them to script in via traditional .Net
languages. Also, this code isn't even in QA at the moment, much less
released, so it's still a good time to make changes in the design...


Since then, it occured to me that a better way to do this might be as
such:

1. Instantiate Runspace
2. Pre-load the scripts into the Runspace. Each script defines a
function for each Powershell rule I'll need to run. The function takes
the dataProviders variable as a parameter, and returns an integer.
3. Obtain delegates to the loaded functions from the Runspace.
4. When the rule needs to be executed, just invoke the delegate from
my C# code.



My intention for getting the delegate to the PS function was to use
the get-delegate function described here:

http://blogs.msdn.com/powershell/arc...25/678259.aspx


So the c# delegate defintion would look like:

public delegate int PsRuleDelegate(IDictionary<string,
IRuleDataProvider> dataProviders);


The user function delegate creation code would look like this (with
each script definition getting it's own delegate variable):

.. insert get-delegate code here ..

$MyRuleDelegate = get-delegate `
My.Namespace.PsRuleDelegate {
$dataValue =
$dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
$checkValue =
$dataProviders[""StaticData""].GetValue(""MaxValue"");
if ($dataValue -eq $checkValue) { return 5 } else { return 0 }
}


Getting the delegate back from the runspace would look like:

Runspace.SessionStateProxy.GetVariable("MyRuleDelegate");


So, before I go fiddling with it, and trying to make that happen...
I'd like to know, is this a viable solution? Will this work? I'll
probably try it anyway tomorrow, but I'd like to hear what more
experienced and knowledgable people have to say about this idea.

I'm guessing that I will need to assemble the delgate creation
function, and all the rule function definitions into a single script,
which is loaded when the runspace first starts up, then obtain the
named delegate variables after the runspace loads. Would I then not
need to run a pipeline? Could those delegates be called directly from
my C# code without an active pipeline (but with an active runspace?).

I think that would improve the performance considerably, without
changing too much of what the end user needs to write.

Thanks,
Troy

My System SpecsSystem Spec
Old 02-01-2008   #2 (permalink)
Karl Prosser[MVP]
Guest


 
 

Re: Hosting Powershell in App - Obtaining delegates to powershellfunctions

PowerShell isn't really the best choice for performance against 40
million rows, even if the solution is great semantically. its good you
are allowing other languages as scripting languages though it might be
hard for them without an integrated editor, checker. Another option
might be choosing preformant dynamic languages on the dotnet platform
like F# or ironpython.

-Karl
My System SpecsSystem Spec
Old 02-01-2008   #3 (permalink)
thoward37
Guest


 
 

Re: Hosting Powershell in App - Obtaining delegates to powershellfunctions

yes, i've considered including both of those as well. i've also
considered writing a dsl on top of f# using a custom ( and greatly
simplified) rule language.

the desire to use powershell comes from a desire to target existing
skills that our technical staff has. we already use powershell in-
house for a variety of admin tasks, so, there wouldn't be a learning
curve for the people who will support the rule engine. the goal behind
the scripting support in the rules engine is to allow advanced users
to create more complex rules than the builtins. as it is, using c#,
vb.net, javscript, f#, or ironpython would be a significant learning
investment for them, wheras powersell is already in thier skillset.
its also much easier to learn for someone with no existing programming
skills...



Karl Prosser[MVP] wrote:
Quote:

> PowerShell isn't really the best choice for performance against 40
> million rows, even if the solution is great semantically. its good you
> are allowing other languages as scripting languages though it might be
> hard for them without an integrated editor, checker. Another option
> might be choosing preformant dynamic languages on the dotnet platform
> like F# or ironpython.
>
> -Karl
My System SpecsSystem Spec
Old 02-01-2008   #4 (permalink)
Oisin (x0n) Grehan [MVP]
Guest


 
 

Re: Hosting Powershell in App - Obtaining delegates to powershellfunctions

On Jan 31, 11:39*pm, thoward37 <thowar...@xxxxxx> wrote:
Quote:

> Hi all, this is a follow-up to an earlier post I made regarding
> embedded Powershell:
>
> http://groups.google.com/group/micro....powershell/br...
>
> In short, I'm hosting Powershell in an app as part of a rules engine,
> using it to repeatedly execute user defined scripts on data provided
> from a database, as one kind of "rule".
>
> The way I initially implemented it was to create a single runspace,
> then create and execute a new pipeline eachtime I needed to execute
> the Powershell rule.
>
> An example rule looks like this:
>
> $dataValue =
> $dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
> $checkValue = $dataProviders[""StaticData""].GetValue(""MaxValue"");
> if ($dataValue -eq $checkValue) { exit 5 } else { exit 0 }
>
> The variable $dataProviders is a dictionary containing various data
> providers that allow the Powershell script to make some decisions
> about some data. It is passed into the Powershell world using a
> statement like ...
> Runspace.SessionStateProxy.SetVariable("dataProviders",
> dataProviders); ... and it's updated each time I execute a pipeline
> with the currently available data.
>
> The exit code of the pipeline is checked to get the result of the
> rule, which is then evaluated by the rest of the rule engine.
>
> So, my previous post I had asked about ways to re-use a single
> pipeline, instead of instantiating a new one everytime, but found that
> was not possible.
>
> Currently, this implementation works, but it's very slow, and there
> are other options available for them to script in via traditional .Net
> languages. Also, this code isn't even in QA at the moment, much less
> released, so it's still a good time to make changes in the design...
>
> Since then, it occured to me that a better way to do this might be as
> such:
>
> 1. Instantiate Runspace
> 2. Pre-load the scripts into the Runspace. Each script defines a
> function for each Powershell rule I'll need to run. The function takes
> the dataProviders variable as a parameter, and returns an integer.
> 3. Obtain delegates to the loaded functions from the Runspace.
> 4. When the rule needs to be executed, just invoke the delegate from
> my C# code.
>
> My intention for getting the delegate to the PS function was to use
> the get-delegate function described here:
>
> http://blogs.msdn.com/powershell/arc...25/678259.aspx
>
> So the c# delegate defintion would look like:
>
> * public delegate int PsRuleDelegate(IDictionary<string,
> IRuleDataProvider> dataProviders);
>
> The user function delegate creation code would look like this (with
> each script definition getting it's own delegate variable):
>
> * .. insert get-delegate code here ..
>
> * $MyRuleDelegate = get-delegate `
> * My.Namespace.PsRuleDelegate *{
> * * * $dataValue =
> $dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
> * * * $checkValue =
> $dataProviders[""StaticData""].GetValue(""MaxValue"");
> * * * if ($dataValue -eq $checkValue) { return 5 } else { return 0 }
> * }
>
> Getting the delegate back from the runspace would look like:
>
> * Runspace.SessionStateProxy.GetVariable("MyRuleDelegate");
>
> So, before I go fiddling with it, and trying to make that happen...
> I'd like to know, is this a viable solution? Will this work? I'll
> probably try it anyway tomorrow, but I'd like to hear what more
> experienced and knowledgable people have to say about this idea.
>
> I'm guessing that I will need to assemble the delgate creation
> function, and all the rule function definitions into a single script,
> which is loaded when the runspace first starts up, then obtain the
> named delegate variables after the runspace loads. Would I then not
> need to run a pipeline? Could those delegates be called directly from
> my C# code without an active pipeline (but with an active runspace?).
>
> I think that would improve the performance considerably, without
> changing too much of what the end user needs to write.
>
> Thanks,
> Troy
Hi Troy,

From my understanding of the powershell engine itself, it won't be
possible to get a delegate to a function as such. PowerShell's script
is interpreted and no matter how you invoke it, the creation of a
pipeline to execute it is implicit.

Don't get me wrong though, PowerShell is one of the greatest things
(imho) to come out of Microsoft in the last few years but it truely is
a prototype in the best sense of the word; a proof of concept that has
shown itself to be a resounding success in all the areas of
application it has found itself. We all expect great things from V2 -
an incremental improvement in fuctionality in tandem with a order of
magnitude increase in speed would be a great result I think. The
community has proven itself to be more than capable of filling in the
missing bits (thanks to the excellent extensibility of the product),
but as for core efficiency and speed, well, that's down to Jeffrey's
great team.

- Oisin
My System SpecsSystem Spec
Old 02-01-2008   #5 (permalink)
thoward37
Guest


 
 

Re: Hosting Powershell in App - Obtaining delegates to powershellfunctions

On Feb 1, 10:20*am, "Oisin (x0n) Grehan [MVP]" <ois...@xxxxxx>
wrote:
Quote:

> On Jan 31, 11:39*pm, thoward37 <thowar...@xxxxxx> wrote:
>
>
>
>
>
Quote:

> > Hi all, this is a follow-up to an earlier post I made regarding
> > embedded Powershell:
>>
Quote:

> > In short, I'm hosting Powershell in an app as part of a rules engine,
> > using it to repeatedly execute user defined scripts on data provided
> > from a database, as one kind of "rule".
>
Quote:

> > The way I initially implemented it was to create a single runspace,
> > then create and execute a new pipeline eachtime I needed to execute
> > the Powershell rule.
>
Quote:

> > An example rule looks like this:
>
Quote:

> > $dataValue =
> > $dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
> > $checkValue = $dataProviders[""StaticData""].GetValue(""MaxValue"");
> > if ($dataValue -eq $checkValue) { exit 5 } else { exit 0 }
>
Quote:

> > The variable $dataProviders is a dictionary containing various data
> > providers that allow the Powershell script to make some decisions
> > about some data. It is passed into the Powershell world using a
> > statement like ...
> > Runspace.SessionStateProxy.SetVariable("dataProviders",
> > dataProviders); ... and it's updated each time I execute a pipeline
> > with the currently available data.
>
Quote:

> > The exit code of the pipeline is checked to get the result of the
> > rule, which is then evaluated by the rest of the rule engine.
>
Quote:

> > So, my previous post I had asked about ways to re-use a single
> > pipeline, instead of instantiating a new one everytime, but found that
> > was not possible.
>
Quote:

> > Currently, this implementation works, but it's very slow, and there
> > are other options available for them to script in via traditional .Net
> > languages. Also, this code isn't even in QA at the moment, much less
> > released, so it's still a good time to make changes in the design...
>
Quote:

> > Since then, it occured to me that a better way to do this might be as
> > such:
>
Quote:

> > 1. Instantiate Runspace
> > 2. Pre-load the scripts into the Runspace. Each script defines a
> > function for each Powershell rule I'll need to run. The function takes
> > the dataProviders variable as a parameter, and returns an integer.
> > 3. Obtain delegates to the loaded functions from the Runspace.
> > 4. When the rule needs to be executed, just invoke the delegate from
> > my C# code.
>
Quote:

> > My intention for getting the delegate to the PS function was to use
> > the get-delegate function described here:
>>
Quote:

> > So the c# delegate defintion would look like:
>
Quote:

> > * public delegate int PsRuleDelegate(IDictionary<string,
> > IRuleDataProvider> dataProviders);
>
Quote:

> > The user function delegate creation code would look like this (with
> > each script definition getting it's own delegate variable):
>
Quote:

> > * .. insert get-delegate code here ..
>
Quote:

> > * $MyRuleDelegate = get-delegate `
> > * My.Namespace.PsRuleDelegate *{
> > * * * $dataValue =
> > $dataProviders[""SomeRandomSqlData""].GetValue(""SomeValue"");
> > * * * $checkValue =
> > $dataProviders[""StaticData""].GetValue(""MaxValue"");
> > * * * if ($dataValue -eq $checkValue) { return 5 } else { return 0}
> > * }
>
Quote:

> > Getting the delegate back from the runspace would look like:
>
Quote:

> > * Runspace.SessionStateProxy.GetVariable("MyRuleDelegate");
>
Quote:

> > So, before I go fiddling with it, and trying to make that happen...
> > I'd like to know, is this a viable solution? Will this work? I'll
> > probably try it anyway tomorrow, but I'd like to hear what more
> > experienced and knowledgable people have to say about this idea.
>
Quote:

> > I'm guessing that I will need to assemble the delgate creation
> > function, and all the rule function definitions into a single script,
> > which is loaded when the runspace first starts up, then obtain the
> > named delegate variables after the runspace loads. Would I then not
> > need to run a pipeline? Could those delegates be called directly from
> > my C# code without an active pipeline (but with an active runspace?).
>
Quote:

> > I think that would improve the performance considerably, without
> > changing too much of what the end user needs to write.
>
Quote:

> > Thanks,
> > Troy
>
> Hi Troy,
>
> From my understanding of the powershell engine itself, it won't be
> possible to get a delegate to a function as such. PowerShell's script
> is interpreted and no matter how you invoke it, the creation of a
> pipeline to execute it is implicit.
>
> Don't get me wrong though, PowerShell is one of the greatest things
> (imho) to come out of Microsoft in the last few years but it truely is
> a prototype in the best sense of the word; a proof of concept that has
> shown itself to be a resounding success in all the areas of
> application it has found itself. We all expect great things from V2 -
> an incremental improvement in fuctionality in tandem with a order of
> magnitude increase in speed would be a great result I think. The
> community has proven itself to be more than capable of filling in the
> missing bits (thanks to the excellent extensibility of the product),
> but as for core efficiency and speed, well, that's down to Jeffrey's
> great team.
>
> - Oisin- Hide quoted text -
>
> - Show quoted text -


Yes, you're right.

I took a tour through the Powershell source using Reflector. There is
no tangible advantage to doing it the way I described. I assumed that
under-the-hood, Powershell functions are compiled at some point, even
if only "on the fly"... But it looks like they are not, so by doing it
the way I described, it's just a more complicated way to achieve the
same results... I might be able to avoid some parsing over-head, but
that's about all. Not sure that's worth making the code more
complicated...

Ah well. So much for what seemed to be a good idea.

Thanks,
Troy
My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
top web hosting service hosting reviews rank Virtual Server
Hosting Powershell in app -- Question about Pipeline PowerShell
Hosting PowerShell & passing parameters to script PowerShell
PowerShell hosting on the Internet PowerShell


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46