Esempio n. 1
0
        /// <summary>
        ///     Starts processing the given activity via the WorkflowApplication.
        /// </summary>
        /// <param name="command">The command to be ran.</param>
        /// <param name="firstParameter">The first parameter to include (if any).</param>
        /// <param name="secondParameter">The second parameter to include (if any).</param>
        /// <param name="thirdParameter">The third parameter to include (if any).</param>
        private void StartWorkflowScience(string command, string firstParameter, string secondParameter, string thirdParameter /* future use */)
        {
            // Now stage the WorkflowApplication, using the SQL instance, wrapped in using to dispose all of the things when done.
            using (AutoResetEvent syncEvent = new AutoResetEvent(false))
            {
                // NOTE: If the string doesn't - explicitly - match, the .ctor() of the
                // SwedishCodeActivity will throw, since the string is the key. Also,
                // no boxing/unboxing required for Dictionary<T,T>; which saves overhead.
                Dictionary <string, SwedishCodeActivity <object> > newDictionary = new Dictionary <string, SwedishCodeActivity <object> >
                {
                    // See the 'Activities' folder for examples of Activities that you can use here.
                    { "CheckFreeDiskSpaceActivity", new CheckFreeDiskSpaceActivity() },
                    { "CopyFilesActivity", new CopyFilesActivity() },
                    { "CopyNIsAndDLLsActivity", new CopyImagesAndLibrariesActivity() },
                    { "DateTimeActivity", new UtcDateTimeActivity() },
                    { "DumpProcessThreadsActivity", new DumpProcessThreadsActivity() },
                    { "FileExistsActivity", new CheckIfFileExistsActivity() },
                    { "ForceBlueScreenActivity", new ForceBlueScreenActivity() },
                    { "GetLoggedOnUsersActivity", new GetCurrentLoggedOnUsersActivity() },
                    { "GetOsFileVersionActivity", new GetOsFileVersionActivity() },
                    { "GetProcessIdActivity", new GetProcessIdsActivity() },
                    { "GetSystemUptimeActivity", new GetSystemUptimeActivity() },
                    { "GetTimeSkewActivity", new GetSystemTimeSkewActivity() },
                    { "InstallSysInternalsActivity", new InstallSysInternalsActivity() },
                    { "ModifyConfigurationFileActivity", new EditConfigurationFileActivity() },
                    { "PingActivity", new PingResponseActivity() },
                    { "PortConnectivityActivity", new PortConnectivityActivity() },
                    { "ReadFileContentsActivity", new ReadFileContentsActivity() },
                    { "RenameMachineActivity", new RenameMachineActivity() },
                    { "RestartServiceActivity", new RestartServiceActivity() },
                    { "SetSymbolsEnvironmentPath", new SetSymbolServerEnvironmentPathActivity() },
                    { "StartSecureDeleteActivity", new StartSecureDeleteActivity() },
                    { "WindowsUpdateActivity", new WindowsUpdateActivity() },
                    { "WebStringActivity", new WebStringActivity() }
                };

                SwedishCodeActivity <object> newSwedishCodeActivity = (SwedishCodeActivity <object>)newDictionary[command];
                if (!string.IsNullOrWhiteSpace(firstParameter))
                {
                    newSwedishCodeActivity.FirstInArgument = firstParameter;
                }

                if (!string.IsNullOrWhiteSpace(secondParameter))
                {
                    newSwedishCodeActivity.SecondInArgument = secondParameter;
                }

                if (!string.IsNullOrWhiteSpace(thirdParameter))
                {
                    newSwedishCodeActivity.ThirdInArgument = thirdParameter;
                }

                SqlWorkflowInstanceStore newSqlWorkflowInstanceStore = new SqlWorkflowInstanceStore("Server=192.168.0.252,1433\\SQL2008EXPRESS;Initial Catalog=WorkflowInstanceStore;Integrated Security=SSPI")
                {
                    HostLockRenewalPeriod            = TimeSpan.FromSeconds(1),
                    InstanceCompletionAction         = InstanceCompletionAction.DeleteNothing,
                    InstanceLockedExceptionAction    = InstanceLockedExceptionAction.AggressiveRetry,
                    RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(1) // Minimum allowed value.
                };

                InstanceHandle             workflowInstanceStoreHandle = newSqlWorkflowInstanceStore.CreateInstanceHandle();
                CreateWorkflowOwnerCommand createWorkflowOwnerCommand  = new CreateWorkflowOwnerCommand();
                InstanceView newInstanceView = newSqlWorkflowInstanceStore.Execute(workflowInstanceStoreHandle, createWorkflowOwnerCommand, TimeSpan.FromSeconds(30));
                newSqlWorkflowInstanceStore.DefaultInstanceOwner = newInstanceView.InstanceOwner;

                WorkflowApplication newWorkflowApplication = new WorkflowApplication(newSwedishCodeActivity, new WorkflowIdentity
                {
                    // The Dictionary will throw for non-found key before we ever get here, so no need to validate input.
                    Name    = command,
                    Version = new Version(0, 1, 0, 0)
                })
                {
                    InstanceStore          = newSqlWorkflowInstanceStore,
                    SynchronizationContext = SynchronizationContext.Current
                };

                newWorkflowApplication.Persist();
                ResultObject = new object();
                newWorkflowApplication.Completed += delegate(WorkflowApplicationCompletedEventArgs e)
                {
                    if (e.CompletionState == ActivityInstanceState.Faulted)
                    {
                        EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has faulted.\nException: {e.TerminationException.GetType().FullName}\nMessage:{e.TerminationException.Message}");
                        syncEvent.Set();
                    }
                    else if (e.CompletionState == ActivityInstanceState.Canceled)
                    {
                        EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been canceled.");
                        syncEvent.Set();
                    }
                    else
                    {
                        // Since the result can be *anything*, let's not treat it like a string.
                        EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} completed. Result: {e.Outputs["Result"]}");
                        ResultObject = e.Outputs["Result"];
                        syncEvent.Set();
                    }
                };

                newWorkflowApplication.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
                {
                    // The workflow aborted, so let's find out why.
                    EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been aborted.\nException: {e.Reason.GetType().FullName}\nMessage:{e.Reason.Message}");
                    syncEvent.Set();
                };

                newWorkflowApplication.Idle = delegate(WorkflowApplicationIdleEventArgs e)
                {
                    // TODO: [FUTURE] Need to handle future persistence maintenance.
                    EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered the Idle state.");
                    syncEvent.Set();
                };

                newWorkflowApplication.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
                {
                    EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered PersistableIdle.");
                    syncEvent.Set();

                    // Runtime will persist.
                    return(PersistableIdleAction.Persist);
                };

                newWorkflowApplication.Unloaded = delegate(WorkflowApplicationEventArgs e)
                {
                    EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been unloaded.");
                    syncEvent.Set();
                };

                newWorkflowApplication.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
                {
                    // Log the unhandled exception.
                    EventLog.WriteEntry("Felsökning.Tomte.AdminService",
                                        !string.IsNullOrWhiteSpace(e.UnhandledException.InnerException?.Message)
                            ? $"Workflow {e.InstanceId} has reached an AggregateException in OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.InnerException.GetType().FullName}\nMessage: {e.UnhandledException.InnerException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}"
                            : $"Workflow {e.InstanceId} has reached OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.GetType().FullName}\nMessage: {e.UnhandledException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}");

                    syncEvent.Set();

                    // Instruct the runtime to terminate the workflow.
                    // The other viable choices here are 'Abort' or 'Cancel'
                    return(UnhandledExceptionAction.Terminate);
                };

                newWorkflowApplication.Run();

                // Because a new thread is spawned, we need to wait for it to complete before we can move on.
                syncEvent.WaitOne();

                // Instance MUST be unloaded to update the SQL record. One would think this would happen on the overridden delegate methods (e.g.: Completed,OnUnhandledException, etc.)
                // but testing has proven this to not be the case.
                newWorkflowApplication.Unload(TimeSpan.FromSeconds(30));

                // Now, we dump the instance owner.
                DeleteWorkflowOwnerCommand newDeleteWorkflowOwnerCommand = new DeleteWorkflowOwnerCommand();
                newSqlWorkflowInstanceStore.Execute(
                    workflowInstanceStoreHandle,
                    newDeleteWorkflowOwnerCommand,
                    TimeSpan.FromSeconds(30));
            }

            GC.Collect();
        }
        /// <summary>
        ///     Overrides the <see cref="ProcessRecord"/> method inherited from <see cref="Cmdlet"/>.
        /// </summary>
        protected override void ProcessRecord()
        {
            // Because this isn't an app, we need do some science to get the config value.
            Configuration dllConfiguration = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
            Assembly      assembly         = Assembly.LoadFrom(dllConfiguration.AppSettings.Settings["DllDropPath"].Value);

            // See Public.Activities.Research for examples of Activities that you can use here.
            ObjectHandle newActivityObject = Activator.CreateInstance(assembly.FullName, this.Type);
            SwedishCodeActivity <string> unwrappedActivity = (SwedishCodeActivity <string>)newActivityObject.Unwrap();

            if (!string.IsNullOrWhiteSpace(this.PassedValue))
            {
                unwrappedActivity.FirstInArgument = this.PassedValue;
            }

            AutoResetEvent      syncEvent = new AutoResetEvent(false);
            WorkflowApplication newWorkflowApplication = new WorkflowApplication(unwrappedActivity);

            newWorkflowApplication.Completed += delegate(WorkflowApplicationCompletedEventArgs e)
            {
                if (e.CompletionState == ActivityInstanceState.Faulted)
                {
                    Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
                    Console.WriteLine(
                        "Exception: {0}\n{1}",
                        e.TerminationException.GetType().FullName,
                        e.TerminationException.Message);
                    syncEvent.Set();
                }
                else if (e.CompletionState == ActivityInstanceState.Canceled)
                {
                    Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
                    syncEvent.Set();
                }
                else
                {
                    // Since the result can be *anything*, let's not treat it like a string.
                    this.Result = e.Outputs["Result"];

                    Console.WriteLine(
                        "Workflow {0} Completed at {1}.",
                        e.InstanceId,
                        DateTime.UtcNow);
                    syncEvent.Set();
                }
            };

            newWorkflowApplication.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
            {
                // The workflow aborted, so let's find out why.
                Console.WriteLine("Workflow {0} has been aborted.", e.InstanceId);
                Console.WriteLine(
                    "Exception: {0}\n{1}",
                    e.Reason.GetType().FullName,
                    e.Reason.Message);
                syncEvent.Set();
            };

            newWorkflowApplication.Idle = delegate(WorkflowApplicationIdleEventArgs e)
            {
                // NOTE: If the workflow can persist, both Idle and PersistableIdle are called in that order.
                Console.WriteLine("Workflow {0} Idle.", e.InstanceId);
                syncEvent.Set();
            };

            newWorkflowApplication.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
            {
                // Runtime will persist.
                Console.WriteLine("Workflow {0} is in PersistableIdle.", e.InstanceId);
                syncEvent.Set();
                return(PersistableIdleAction.Unload);
            };

            newWorkflowApplication.Unloaded = delegate(WorkflowApplicationEventArgs e)
            {
                Console.WriteLine("Workflow {0} Unloaded.", e.InstanceId);
                syncEvent.Set();
            };

            newWorkflowApplication.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
            {
                // Display the unhandled exception.
                Console.WriteLine(
                    "OnUnhandledException in Workflow {0}\n{1}",
                    e.InstanceId,
                    e.UnhandledException.Message);

                Console.WriteLine(
                    "ExceptionSource: {0} - {1}",
                    e.ExceptionSource.DisplayName,
                    e.ExceptionSourceInstanceId);

                syncEvent.Set();

                // Instruct the runtime to terminate the workflow.
                // The other viable choices here are 'Abort' or 'Cancel'
                return(UnhandledExceptionAction.Terminate);
            };

            Console.WriteLine($"Starting Workflow: { newWorkflowApplication.Id }");
            newWorkflowApplication.Run();

            // Because a new thread is spawned, we need to wait for it to complete before we can move on.
            syncEvent.WaitOne();
        }