Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Powershell script task #5

Open
patrickfarry opened this issue Dec 12, 2011 · 10 comments
Open

Powershell script task #5

patrickfarry opened this issue Dec 12, 2011 · 10 comments

Comments

@patrickfarry
Copy link

I wrote a small extension task that embeds a powershell script. We will be using it for complex build tasks. The script can access the Nant project object (get and set properties etc.). It also supports named powershell runspaces - so you can continue executing a script after setting up the parameters.

Anyone interested in this? I haven't contributed anything before - not sure if it is worthy or how to go about it.

Here is an example of the task in NAnt

The top level build file. $var = "this is the script" $myvar.Properties["tmpLog"] = "Hello" $myvar.Project.ProjectName $var = "running from a new runspace" $var $var
@patrickfarry
Copy link
Author

Sorry - that looks ugly - here is my test build file

<project name="My project" default="build" basedir=".">
  <description>The top level build file.</description>
  <property name="tmpLog" value="c:\tempSVNUpdate" />
  <property name="results" value="Unknown" />

<target name="build" >
    <powershell  property="results"  taskvar = "myvar" runspace="myrunspace">
        $var = "this is the script"
        $myvar.Properties["tmpLog"] = "Hello"
        $myvar.Project.ProjectName
    </powershell>
    <powershell  property="results">
        $var = "running from a new runspace"
        $var
    </powershell>
    <powershell  property="results" runspace="myrunspace">
        $var
    </powershell>

</target>
</project>

@patrickfarry
Copy link
Author

Here is the source - -

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace PowershellPlugin
{
[TaskName("powershell" )]
public class PowershellTask : Task
{

  private string _runspaceName = string.Empty;
  private string _taskVarName = "task";
  private bool _isNamedRunspace = false;
  private string _property = string.Empty;
  static private Dictionary<string, Runspace> _namedSession;


  [TaskAttribute("runspace", Required = false)]
  [StringValidator(AllowEmpty = false)]
  public string RunspaceName
  {
      get { return _runspaceName; }
      set { _isNamedRunspace = true; _runspaceName = value; }
  }

  [TaskAttribute("taskvar", Required = false)]
  [StringValidator(AllowEmpty = false)]
  public string TaskVar
  {
      get { return _taskVarName; }
      set { _taskVarName = value; }
  }

  [TaskAttribute("property", Required = false)]
  [StringValidator(AllowEmpty = false)]
  public string Property
  {
      get { return _property; }
      set { _property = value; }
  }


    public PowershellTask()
    {
        _runspaceName = String.Empty;
        if (_namedSession == null)
        {
            object l = new object();
            lock (l)
            {
                if (_namedSession == null)
                {
                    _namedSession = new Dictionary<string, Runspace>();
                }
            }
        }

    }




  protected override void ExecuteTask()
  {
      Runspace runspace = null;

      try
      {


          StringBuilder scriptText = new StringBuilder();
          scriptText.Append(XmlNode.InnerText);
            object l = new object();
            lock (l)
            {

                if (!_namedSession.TryGetValue(_runspaceName, out runspace))
                {
                    InitialSessionState iss = InitialSessionState.CreateDefault();
                    SessionStateVariableEntry thisTask = new SessionStateVariableEntry(_taskVarName, this, "The task being called in nant");
                    iss.Variables.Add(thisTask);
                    runspace = RunspaceFactory.CreateRunspace(iss);

                    if (_isNamedRunspace)
                    {
                        _namedSession.Add(_runspaceName, runspace);
                    }
                    runspace.Open();

                }
            }
          PowerShell ps = PowerShell.Create();
          ps.Runspace = runspace;
          ps.AddScript(scriptText.ToString());
          Collection<PSObject> results = ps.Invoke();
          StringBuilder resultString = new StringBuilder();
          if (_property != String.Empty)
          {
              foreach (PSObject po in results)
              {

                 resultString.AppendLine(po.ToString());

              }
              this.Properties[_property] = resultString.ToString();
          }
      }
      finally
      {
          if (!_isNamedRunspace && runspace != null)
          {
              runspace.Close();
              runspace.Dispose();
          }
      }

  }

}
}

@dguder dguder closed this as completed Dec 12, 2011
@dguder dguder reopened this Dec 12, 2011
@dguder
Copy link
Member

dguder commented Dec 12, 2011

Here is the source - -
(now using github markdown)

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace PowershellPlugin
{
    [TaskName("powershell" )]
    public class PowershellTask : Task
    {

      private string _runspaceName = string.Empty;
      private string _taskVarName = "task";
      private bool _isNamedRunspace = false;
      private string _property = string.Empty;
      static private Dictionary<string, Runspace> _namedSession;


      [TaskAttribute("runspace", Required = false)]
      [StringValidator(AllowEmpty = false)]
      public string RunspaceName
      {
          get { return _runspaceName; }
          set { _isNamedRunspace = true; _runspaceName = value; }
      }

      [TaskAttribute("taskvar", Required = false)]
      [StringValidator(AllowEmpty = false)]
      public string TaskVar
      {
          get { return _taskVarName; }
          set { _taskVarName = value; }
      }

      [TaskAttribute("property", Required = false)]
      [StringValidator(AllowEmpty = false)]
      public string Property
      {
          get { return _property; }
          set { _property = value; }
      }


        public PowershellTask()
        {
            _runspaceName = String.Empty;
            if (_namedSession == null)
            {
                object l = new object();
                lock (l)
                {
                    if (_namedSession == null)
                    {
                        _namedSession = new Dictionary<string, Runspace>();
                    }
                }
            }

        }




      protected override void ExecuteTask()
      {
          Runspace runspace = null;

          try
          {


              StringBuilder scriptText = new StringBuilder();
              scriptText.Append(XmlNode.InnerText);
                object l = new object();
                lock (l)
                {

                    if (!_namedSession.TryGetValue(_runspaceName, out runspace))
                    {
                        InitialSessionState iss = InitialSessionState.CreateDefault();
                        SessionStateVariableEntry thisTask = new SessionStateVariableEntry(_taskVarName, this, "The task being called in nant");
                        iss.Variables.Add(thisTask);
                        runspace = RunspaceFactory.CreateRunspace(iss);

                        if (_isNamedRunspace)
                        {
                            _namedSession.Add(_runspaceName, runspace);
                        }
                        runspace.Open();

                    }
                }
              PowerShell ps = PowerShell.Create();
              ps.Runspace = runspace;
              ps.AddScript(scriptText.ToString());
              Collection<PSObject> results = ps.Invoke();
              StringBuilder resultString = new StringBuilder();
              if (_property != String.Empty)
              {
                  foreach (PSObject po in results)
                  {

                     resultString.AppendLine(po.ToString());

                  }
                  this.Properties[_property] = resultString.ToString();
              }
          }
          finally
          {
              if (!_isNamedRunspace && runspace != null)
              {
                  runspace.Close();
                  runspace.Dispose();
              }
          }

      }

   }
}

@patrickfarry
Copy link
Author

Do you what the whole solution?

@dguder
Copy link
Member

dguder commented Dec 12, 2011

First of all I wanted to see the whole code. Do you have any tests?
Some review:

  • Your lock object should be defined at class level.
  • What happens if powershell could not be found? (e.g on WinXP or on mono on linux?)
  • Some comments for documentation are required (see other nantcontrib source files)

@rmboggs
Copy link
Member

rmboggs commented Dec 12, 2011

I like the idea. If you are wanting to submit this task to NAntContrib, I would ask if you could submit this via a pull request, details can be found here.

Documentation for this task would also be very helpful. :)

@patrickfarry
Copy link
Author

I don' t have anything else. Happy to spend some time bringing it up to
standard.

I will look at the other contrib projects and figure out what to do. Will
send an update when I get it done.

Cheers.

Connected by DROID on Verizon Wireless

-----Original message-----
From: Dominik Guder
<reply+i-2528372-b66055b90339b6ceec05f59b133e8fb0fc42c4db-1258583@reply.githu
b.com>
To: patrickfarry patrick.farry@endicia.com
Sent: Mon, Dec 12, 2011 23:01:25 GMT+00:00
Subject: Re: [nantcontrib] Powershell script task (#5)

First of all I wanted to see the whole code. Do you have any tests?
Some review:

  • Your lock object should be defined at class level.
  • What happens if powershell could not be found? (e.g on WinXP?)
  • Some comments for documentation is required (see other nantcontrib source
    files)

Reply to this email directly or view it on GitHub:
#5 (comment)

@patrickfarry
Copy link
Author

Will do. I got mail from Dominik. I will be upgrading what I did to fit the
project and will get back to you guys.

Connected by DROID on Verizon Wireless

-----Original message-----
From: Ryan Boggs
<reply+i-2528372-b66055b90339b6ceec05f59b133e8fb0fc42c4db-1258583@reply.githu
b.com>
To: patrickfarry patrick.farry@endicia.com
Sent: Mon, Dec 12, 2011 23:14:02 GMT+00:00
Subject: Re: [nantcontrib] Powershell script task (#5)

I like the idea. If you are wanting to submit this task to NAntContrib, I
would ask if you could submit this via a pull request, details can be found
here
.

Documentation for this task would also be very helpful. :)


Reply to this email directly or view it on GitHub:
#5 (comment)

@rmboggs
Copy link
Member

rmboggs commented Dec 13, 2011

Sounds great.

@andrewducker
Copy link

Did this ever get merged in?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants