I haven’t written for a while. I have been super busy.  Chet said he signed up for my RSS feed today so I thought I would write a quick post so he has something to read today.  Hehe.

I am writing a tool that publishes projects on a schedule.  I want to do a Project Pro publish versus a publish with the PSI.   This tool runs unattended on the server.  Doing server-side automation of a singleton like Project Pro has its pitfalls—one is that since it is a singleton, if it gets hung up you can’t do much about it unless you code to defend yourself against such a case.

Enter the TimedExecution class. 

The concept is simple.  I want to run an operation and if it takes longer than a specified amount of time, I want to signal back to the caller that the operation is still executing.  The caller is then responsible for figuring out how to react.

Here is the source:

using System;
using System.Threading;
using Mcs.Epm.ProjectPro.Properties;
 
namespace Mcs.Epm.ProjectPro
{
    internal class TimedExecution
    {
        private readonly Action<string> _Action;
        private readonly string _State;
        private readonly int _RunTimeInMilliseconds;
 
        public TimedExecution(Action<string> action, string state, int runTimeInMilliseconds)
        {
            _Action = action;
            _State = state;
            _RunTimeInMilliseconds = runTimeInMilliseconds;
        }
 
        public bool Execute()
        {
            Thread executeThread = new Thread(ExecuteThreadEntry);
            executeThread.Name = Resources.AppTitle;
 
            executeThread.Start();
 
            executeThread.Join(_RunTimeInMilliseconds);
 
            return !executeThread.IsAlive;
        }
 
        private void ExecuteThreadEntry()
        {
            _Action.Invoke(_State);
        }
    }
}

Pretty straightforward.  I use the Action delegate to pass TimedExecution the method in the caller that will be called, as well as state information (in this case, the name of the project to publish), and the max run time in milliseconds.   I create a new thread and invoke the action.  The primary thread joins on the new thread for the specified time.   Once Join returns, Execute returns true if the thread is no longer alive.

Here is its usage:

TimedExecution timedExecution = new TimedExecution(PublishProject, project.Name, _AutomationOptions.MaxPublishRunTime * 1000);
 
if (!timedExecution.Execute())
{
    _ProjectWrapper.Dispose();
    OpenProjectWrapper();
}

This is the brute force stuff you have to do when automating Project Pro on the server.   In order to be as friendly and as considerate as possible, I implemented a whole slew of options for controlling how Project Pro is automated:

image

Have a great weekend!