C# script in script module

Hi! Is it possible to create a c# functions in Script Modules section of Library and include it to my project?

I tried to do it, but have no success

Hi,

Unfortunately no, the script modules are PowerShell only (they rely on some PowerShell features to work).

Hope this helps,

Paul

This is a very bad news :frowning:

Have you plans to make this feature?

Hi, it’s not something we have plans for at the moment - you could open a suggestion here:

https://octopusdeploy.uservoice.com/

Paul

we really need this feature. May be it will help to fix problems in http://help.octopusdeploy.com/discussions/problems/36271-parallel-deploy-problems

Hi,

Unfortunately, even if we supported ScriptCS scripts it would still try to run them all in parallel, so you’d end up with the same problems that you are currently having with PowerShell scripts.

Paul

You can write c# within powershell :slight_smile: http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/30/weekend-scripter-run-c-code-from-within-powershell.aspx

one more argument for c# in script modules - with powershell i have 2 variants - either i must make awful scripts with old comandlets for compatibility with windows 2008R2, or i must upgrade all computers to 2012R2 (and maybe to 2016 soon) - and all of this variants bad.

With c# modules this problems must be solved.

What is it that you are trying to do? You could just write a cmdlet in c# and call that from octopus - I’ve got an example I did for resetting a tentacle if its any help…

Hey @David, can you show me this example? I need to call a C# code as one of my steps during deployment.
Thanks,
Alex

I cant find the octopus one at the moment, but this is an example of a cmdlet I did for Vmware service manager…

Im not a dev, so Ignore any crude code :slight_smile:

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Management.Automation;


namespace VSM
{
    [Cmdlet(VerbsCommon.Get, "VsmRfc", SupportsShouldProcess = true)]
    public class Get_VsmRfc : PSCmdlet
    {
        #region Parameters


        [Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The workflow reference id"), ValidateNotNullOrEmpty]
        public string EntityRef { get; set; }

        // Common Params
        [Parameter(Mandatory = true, HelpMessage = "The database name."), ValidateNotNullOrEmpty]
        public string Database { get; set; }

        [Parameter(Mandatory = true, HelpMessage = "The service URL."), ValidateNotNullOrEmpty]
        public string ServiceUrl { get; set; }

        [Parameter(Mandatory = true)]
        public PSCredential Credential;


        #endregion

        protected override void ProcessRecord()
        {
            try
            {
                // convert pwd to plain text to use with the API
                var pwd = Marshal.PtrToStringBSTR(Marshal.SecureStringToBSTR(Credential.Password));

                WriteVerbose(string.Format("Attempting to establish connection with VMWare service manager located at: {0}", ServiceUrl));
                var client = new ServiceManagerClient(new BasicHttpBinding(), new EndpointAddress(ServiceUrl));

                string message;
                
                WriteVerbose(string.Format("Attempting to retrieve workflow with entity ref: {0}", EntityRef));

                var request = new WorkflowRetrieveRequest()
                {
                    sLoginUserID = Credential.UserName,
                    sLoginPassword = pwd,
                    sDatabase = Database,
                    lEntityRef = EntityRef
                };
                
                
                // Attempt to Retrieve RFC Info 
                DataSet ds;
                APIReturn apiReturn = client.WorkflowRetrieve(
                    request.sID,
                    request.sLoginUserID,
                    request.sLoginPassword,
                    request.sDatabase,
                    request.lEntityRef,
                    request.aCustomParameters,
                    out message,
                    out ds
                    );


                WriteVerbose("Checking API response");

                // check response from the API and return the data if we have it.
                if (apiReturn == APIReturn.API_SUCCESS)
                {
                    WriteVerbose("API success");

                    // Sort Results by column name before returning
                    var columnNames = (from DataColumn col in ds.Tables[0].Columns select col.ColumnName).ToList();
                    columnNames.Sort();

                    var newIndex = 0;
                    foreach (var name in columnNames)
                    {
                        ds.Tables[0].Columns[name].SetOrdinal(newIndex);
                        newIndex++;
                    }

                    // Return object containing dataset
                    WriteObject(ds.Tables[0]);
                }
                else
                {
                    WriteVerbose("API Error");
                    WriteError(new ErrorRecord(new Exception(message), "", ErrorCategory.NotSpecified, this));
                }         

            }
            catch (Exception ex)
            {
                WriteError(new ErrorRecord(ex, "", ErrorCategory.NotSpecified, this));
            }
        }


    }
}

Another thought is just compile the code as a console app and add to the deployment?

@David, you’ve gave me a better idea, i will update the setting using an api call and add it as a step during deployment probably as a console app.
Thanks you very much!!