0

I am hoping someone can help with this, I searched and can't seem to find an answer or even the exact same problem.

I am loading an assembly from file (even though I have v2 Powershell add-type has some strange behaviour in this instance).

[System.Reflection.Assembly]::LoadFrom("$env:userprogile\path\to\my\dll\mydll.dll")

$taskId = 1 $ts = New-Object mydll.myclass -ArgumentList @(,$taskId)

DLL loads fine and the constructor becomes available as expected but when trying to parse arguments into it, infact it takes just one in this case it throws this error

New-Object : Exception calling ".ctor" with "1" argument(s): "Index 1 is out of range." At line:1 char:7 + $ts = New-Object mydll.myclass + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

The unit test and test app for this works just fine when an integer of 1 is passed to it.

$taskId -is [int] gives true, I tried passing it these ways: -ArgumentList 1 -ArgumentList (1) -ArgumentList @(1) and I am sure there were some other more ludicrous ones Funnily enough all give the same error...

Constructor signature:

public sealed class myclass: IDisposable
{
    private readonly int _taskId = 0;
    private ScheduledTask scheduledTask = null;

    public myclass(int taskId)
    {
        if (taskId == 0)
            throw new ApplicationException("Task Id is not valid");

        _taskId = taskId;
        scheduledTask = TaskJobFactory.CreateScheduledTask(this._taskId);
    }

    public void RunTask()
    {

        DataTable dt = null;
        String csvString = String.Empty;

        try
        {
            dt = TaskJobFactory.CreateTableTask(scheduledTask.EnumTaskType, scheduledTask.campaignID.Value);
            csvString = Csv.DataTableToCsc(dt);

            if (csvString.Length > 0)
            {
                SmtpManager.SendEmailStatic(csvString, scheduledTask.Id, scheduledTask);
                TaskHistoryFactory.UpdateTaskHistory(this._taskId, (int)ScheduledTaskStatus.Success, "Success");
            }
            else
                TaskHistoryFactory.UpdateTaskHistory(this._taskId, (int)ScheduledTaskStatus.Unknown, String.Format("No Data for that Taks id {0}", _taskId));
        }
        catch (Exception ex)
        {
            TaskHistoryFactory.UpdateTaskHistory(this._taskId, (int)ScheduledTaskStatus.Failure, "Fail");
            ErorrLoggingFacede.LogError(ex, "TaskRunner", "RunTask");
            throw ex;
        }
        finally
        {
            dt = null;
        }
    }
}

sorry about the formatting...

Also, I tried having an empty constructor and passing the args directly to method, it worked in the test app (with a few errors since it wasn't built for that but actually completed)

Nitsch_D
  • 11
  • 1
  • 1
  • 4
  • post the signature of the constructor – dugas Aug 27 '15 at 17:33
  • Is your exception being thrown when calling CreateScheduledTask? – dugas Aug 27 '15 at 18:26
  • @dugas, I have no idea exactly where - when debugging in PS ISE it throws the exception as soon as the value is being passed in the constructor, but inside the constructor - I guess that would be the only place where it can error out, though not sure why since a test windows app works just fine... I will edit the constructor signature to show local _taskId and also pasted the first method into which it's passed. – Nitsch_D Aug 27 '15 at 18:44
  • just to add, I have called constructors from custom DLLs many times without a problem in exactly the same way- not sure why Powershell has decided to be problematic this time around – Nitsch_D Aug 27 '15 at 18:58

1 Answers1

1

After some debugging - it turns out that the Exception calling ".ctor" with "1" argument(s): "Index 1 is out of range." in the constructor was actually coming from a connection string error, or rather the mydll.dll.config was not being read even though it was in the same directory.

It should be enough for app.config or mydll.dll.config to be in the same directory as the DLL - Putting configuration information in a DLL according to these and many others.

Not so in this case, in first instance the DLL was actually using EF which was a bag of problems on its own, so changed to ADO, but still nothing.

The solution was to use var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location); string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;

As suggested in this post - C# DLL config file

This worked great once the path was explicitly named i.e. Assembly.GetExecutingAssembly(@"C:\mypath\to\dll\app.config") but posed an annoying problem of deploying to production where paths would have to be changed before deploying.

The final solution for us was to create our own XML configuration file and pass that to the constructor with other parameters. Works well and can be updated separately to the whole DLL - esp. if you are using third party APIs and store tokens/access keys/etc...

Community
  • 1
  • 1
Nitsch_D
  • 11
  • 1
  • 1
  • 4