locked
Implement Powershell in C# code RRS feed

  • Question

  • Hey Guys!

    I have tryied to implement this Powershell Code to C#:
    $Root = "\";
    $Taskname = "L&T Integration"
    $Scheduler = New-Object -ComObject Schedule.Service
    $Scheduler.Connect()
    $RootFolder = $Scheduler.GetFolder($Root)
    $Task = $RootFolder.GetTask($Taskname)
    $task.LastRunTime
    $Task.NextRunTime.DateTime
    $task.Enabled
    Right now i have this in a seperated script that im reading in..
    I want to implement it to c# code so i can set parameters like $TaskName and $Root from C# code..
    Here is my C# Code:
    string skript = File.ReadAllText(@"C:\Cago\taskSchedulerPS.ps1");
                    PowerShell ps = PowerShell.Create();
                    ps.Commands.AddScript(skript);
    
    
                    var resultat = ps.Invoke();


    Any Ideas?
    Best Regards
    Sunday, August 16, 2020 8:49 PM

Answers

  • This seems to be a common request and I really don't understand why. Powershell is a scripting wrapper around .NET. Why would you write C# code to call a PS script that itself is just going to run under .NET (and probably C#) that you are already using? Why do you need this to be explicitly done via PS vs just writing the equivalent code in C#?

    Picking your PS script apart you are getting a particular scheduled task (ignoring the legacy At service). You then display some properties from it. This isn't the correct approach in modern versions of Windows. If you are running at least Windows Server 2012 then use the official cmdlets.

    $task = Get-ScheduledTask -TaskName $taskName -TaskPath $taskPath
    

    The equivalent C# code without PS involved.

    var taskPath = @"\";
    var taskName = "L&T Integration";
    
    var scheduler = new TaskScheduler.TaskScheduler();
    scheduler.Connect();
    var folder = scheduler.GetFolder(taskPath);
    var task = folder?.GetTask(taskName);
    if (task == null)
        throw new Exception("Task not found");            


    But, again, I don't know why you'd bother hosting PS when you can just write the same C# code instead.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Carlo Goretti Monday, August 17, 2020 4:32 PM
    Monday, August 17, 2020 2:31 PM

All replies

  • This seems to be a common request and I really don't understand why. Powershell is a scripting wrapper around .NET. Why would you write C# code to call a PS script that itself is just going to run under .NET (and probably C#) that you are already using? Why do you need this to be explicitly done via PS vs just writing the equivalent code in C#?

    Picking your PS script apart you are getting a particular scheduled task (ignoring the legacy At service). You then display some properties from it. This isn't the correct approach in modern versions of Windows. If you are running at least Windows Server 2012 then use the official cmdlets.

    $task = Get-ScheduledTask -TaskName $taskName -TaskPath $taskPath
    

    The equivalent C# code without PS involved.

    var taskPath = @"\";
    var taskName = "L&T Integration";
    
    var scheduler = new TaskScheduler.TaskScheduler();
    scheduler.Connect();
    var folder = scheduler.GetFolder(taskPath);
    var task = folder?.GetTask(taskName);
    if (task == null)
        throw new Exception("Task not found");            


    But, again, I don't know why you'd bother hosting PS when you can just write the same C# code instead.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Carlo Goretti Monday, August 17, 2020 4:32 PM
    Monday, August 17, 2020 2:31 PM
  • Michael,

    Can you please explain this line of code (sorry for a little diversion). I think I've seen this syntax before, but want to make sure I understand it

    var task = folder?.GetTask(taskName);

    Thanks in advance.


    Looking for new opportunities

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    • Proposed as answer by KHURRAM RAHIM Wednesday, November 25, 2020 4:16 PM
    Monday, August 17, 2020 3:36 PM
  • (Unless I typed it wrong) this is the null conditional operator added in C# 6+. It checks the object to determine if it is null or not. If it is not null then the member is executed otherwise it is skipped. The result of the expression is the normal type of the expression (if any) or null. It would be equivalent to this.

    var task = (folder != null) ? folder.GetTask(taskName) : null;


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, August 17, 2020 3:44 PM
  • Sorry I should have clarified. To get this type you need to add a reference to the COM type library 'Task Scheduler'. To add a COM reference go to the References node of your project in Solution Explorer. Select the option to add a reference. Then in the References dialog go to COM. Scroll all the way down to the `Task Scheduler` type library and check the box. The IDE will generate the necessary reference and the above code will then work equivalent to your original PS code.

    As for the "taking out" that code is simply retrieving the properties of the task object. In your case the last and next run times and enabled. That is available on the returned `Task` object in the C# code as well. In fact when you get the above code working then when you type `task.` Intellisense should pop up and show you these properties. You can then use them how you see fit. Just getting a property value doesn't do anything so writing that code wouldn't make sense but you can use the properties in other expressions as you see fit.

    var task = folder?.GetTask(taskName);
    
    //Do something with the properties
    if (task.Enabled)
    {
       Console.WriteLine($"Task last run: {task.LastRunTime}");
       Console.WriteLine($"Task will next run: {task.NextRunTime}");
    };
    

    If you just want to view the properties while you're testing your code then set a breakpoint on the line that gets the task. Once it hits the line press F10 to step one more time so it executes. You can then mouse over the `task` identifier and see all the properties. Alternatively view the properties in the `Locals` or `Autos` debugger windows in the IDE. These only work while paused in the debugger though.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, August 17, 2020 4:33 PM