![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| 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. |
| |||||||
![]() |
| |
| | #1 (permalink) |
| 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 Specs![]() |
| | #2 (permalink) |
| 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 Specs![]() |
| | #3 (permalink) |
| 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 Specs![]() |
| | #4 (permalink) |
| 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 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 Specs![]() |
| | #5 (permalink) |
| 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 Specs![]() |
![]() |
| 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 | |||