UiPath freezes for about 30 seconds when adding activity made in activity creator

I’m trying to develop an activity using the Activity Creator for Visual Studio, i’m using Visual Studio 17.3.7 which is the suggested version from the forums, and it works, but it freezes my studio for about 30-60 seconds whenever i load it and drag it into my workflow file, and then it works fine, and debug works fine. I’m developing these activities for SharePoint due to the standard UiPath 365 activities doesn’t seem to work in local sharepoint tenants with more than 200+ files/folders, even when setting the “first” to 9999 to ignore the 200 limit.

I have followed all the standard practices and created it as suggested, building/publishing it and it works fine but it just doesn’t really add a good experience for other people who might need to use it since it freezes the ui for the first 60 seconds since dragging the activities to the workflow file. I have since added icons, but it froze even when just using the standard setup. I suspect the Scope might be the culprit.

Scope code:

using System;
using System.Activities;
using System.Threading;
using System.Threading.Tasks;
using System.Security;
using System.Activities.Statements;
using System.ComponentModel;
using COMPANY.SharePointActivities.Activities.Properties;
using UiPath.Shared.Activities;
using UiPath.Shared.Activities.Localization;
using Azure.Core;
using Azure.Identity;
using Microsoft.Graph;
using System.Collections.Generic;

namespace COMPANY.SharePointActivities.Activities
{
    [LocalizedDisplayName(nameof(Resources.SharePointScope_DisplayName))]
    [LocalizedDescription(nameof(Resources.SharePointScope_Description))]
    public class SharePointScope : ContinuableAsyncNativeActivity
    {
        #region Properties

        [Browsable(false)]
        public ActivityAction<IObjectContainer​> Body { get; set; }

        /// <summary>
        /// If set, continue executing the remaining activities even if the current activity has failed.
        /// </summary>
        [LocalizedCategory(nameof(Resources.Common_Category))]
        [LocalizedDisplayName(nameof(Resources.ContinueOnError_DisplayName))]
        [LocalizedDescription(nameof(Resources.ContinueOnError_Description))]
        public override InArgument<bool> ContinueOnError { get; set; }

        [LocalizedDisplayName(nameof(Resources.SharePointScope_ClientId_DisplayName))]
        [LocalizedDescription(nameof(Resources.SharePointScope_ClientId_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<string> ClientId { get; set; }

        [LocalizedDisplayName(nameof(Resources.SharePointScope_TenantId_DisplayName))]
        [LocalizedDescription(nameof(Resources.SharePointScope_TenantId_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<string> TenantId { get; set; }

        [LocalizedDisplayName(nameof(Resources.SharePointScope_Username_DisplayName))]
        [LocalizedDescription(nameof(Resources.SharePointScope_Username_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<string> Username { get; set; }

        [LocalizedDisplayName(nameof(Resources.SharePointScope_SecurePassword_DisplayName))]
        [LocalizedDescription(nameof(Resources.SharePointScope_SecurePassword_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<SecureString> SecurePassword { get; set; }

        [LocalizedDisplayName(nameof(Resources.SharePointScope_SharePointUrl_DisplayName))]
        [LocalizedDescription(nameof(Resources.SharePointScope_SharePointUrl_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<string> SharePointUrl { get; set; }

        // A tag used to identify the scope in the activity context
        internal static string ParentContainerPropertyTag => "ScopeActivity";

        // Object Container: Add strongly-typed objects here and they will be available in the scope's child activities.
        private readonly IObjectContainer _objectContainer;

        #endregion


        #region Constructors

        public SharePointScope(IObjectContainer objectContainer)
        {
            _objectContainer = objectContainer;

            Body = new ActivityAction<IObjectContainer>
            {
                Argument = new DelegateInArgument<IObjectContainer> (ParentContainerPropertyTag),
                Handler = new Sequence { DisplayName = Resources.Do }
            };
        }

        public SharePointScope() : this(new ObjectContainer())
        {

        }

        #endregion


        #region Protected Methods

        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
            if (ClientId == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(ClientId)));
            if (TenantId == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(TenantId)));
            if (Username == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(Username)));
            if (SecurePassword == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(SecurePassword)));
            if (SharePointUrl == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(SharePointUrl)));

            base.CacheMetadata(metadata);
        }

        protected override async Task<Action<NativeActivityContext>> ExecuteAsync(NativeActivityContext  context, CancellationToken cancellationToken)
        {
            // Inputs
            var clientid = ClientId.Get(context);
            var tenantid = TenantId.Get(context);
            var username = Username.Get(context);
            var securepassword = SecurePassword.Get(context);
            var sharepointurl = SharePointUrl.Get(context);

            var scopes = new[] { "https://graph.microsoft.com/.default" };

            // using Azure.Identity;  
            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };
            string SiteURL = sharepointurl;

            // Check if the URL starts with "https://"
            if (SiteURL.StartsWith("https://"))
            {
                SiteURL = SiteURL.Substring(8); // Remove "https://"
            }

            // Replace ".sharepoint.com" with ".sharepoint.com:"
            SiteURL = SiteURL.Replace(".sharepoint.com", ".sharepoint.com:");

            var password = new System.Net.NetworkCredential(string.Empty, securepassword).Password;
            // https://learn.microsoft.com/dotnet/api/azure.identity.usernamepasswordcredential  
            var userNamePasswordCredential = new UsernamePasswordCredential(
                username, password, tenantid, clientid, options);


            var accessToken = await userNamePasswordCredential.GetTokenAsync(new TokenRequestContext(scopes) { });

            var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);

            var dictionaryContainer = new Dictionary<string, object>();
            dictionaryContainer["clientid"] = clientid;
            dictionaryContainer["tenantid"] = tenantid;
            dictionaryContainer["username"] = username;
            dictionaryContainer["securepassword"] = securepassword;
            dictionaryContainer["sharepointurl"] = SiteURL;
            dictionaryContainer["graphclient"] = graphClient;
            _objectContainer.Add<Dictionary<string, object>>(dictionaryContainer);

            return (ctx) => {
                // Schedule child activities
                if (Body != null)
				    ctx.ScheduleAction<IObjectContainer>(Body, _objectContainer, OnCompleted, OnFaulted);

                // Outputs
            };
        }

        #endregion


        #region Events

        private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
        {
            faultContext.CancelChildren();
            Cleanup();
        }

        private void OnCompleted(NativeActivityContext context, ActivityInstance completedInstance)
        {
            Cleanup();
        }

        #endregion


        #region Helpers
        
        private void Cleanup()
        {
            var disposableObjects = _objectContainer.Where(o => o is IDisposable);
            foreach (var obj in disposableObjects)
            {
                if (obj is IDisposable dispObject)
                    dispObject.Dispose();
            }
            _objectContainer.Clear();
        }

        #endregion
    }
}

Scope designer:

<sap:ActivityDesigner x:Class="COMPANY.SharePointActivities.Activities.Design.Designers.SharePointScopeDesigner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sa="http://schemas.microsoft.com/netfx/2009/xaml/activities"
    xmlns:p="clr-namespace:COMPANY.SharePointActivities.Activities.Design.Properties"
    xmlns:sharedres="clr-namespace:UiPath.Shared.Localization"
    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
    xmlns:converters="clr-namespace:UiPath.Shared.Activities.Design.Converters"
    xmlns:uip="clr-namespace:UiPath.Shared.Activities.Design.Controls" >

 
    <sap:ActivityDesigner.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="..\Themes\Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <converters:ActivityIconConverter x:Key="ActivityIconConverter" />
        </ResourceDictionary>
    </sap:ActivityDesigner.Resources>
 
    <sap:ActivityDesigner.Icon>
        <DrawingBrush Stretch="Uniform" Drawing="{Binding Path=ModelItem, Converter={StaticResource ActivityIconConverter}, ConverterParameter=pack://application:\,\,\,/COMMPANY.SharePointActivities.Activities.Design;component/themes/icons.xaml}" />
    </sap:ActivityDesigner.Icon>
 
    <uip:ActivityDecoratorControl Style="{StaticResource ActivityDecoratorStyle}">
        <DockPanel LastChildFill="True">
            <sap:WorkflowItemPresenter x:Uid="sad:WorkflowItemPresenter_1"
                                       AutomationProperties.AutomationId="Activity"
                                       DockPanel.Dock="Bottom"
                                       MinWidth="400"
                                       Margin="0,10,0,0"
                                       Item="{Binding Path=ModelItem.Body.Handler, Mode=TwoWay}"
                                       AllowedItemType="{x:Type sa:Activity}"
                                       HintText="{x:Static p:Resources.DropActivityHere}" />

        </DockPanel>
    </uip:ActivityDecoratorControl>
</sap:ActivityDesigner>

HI @farow31916 ,
Thanks for reaching out to UiPath Community.

You can try these steps to crosscheck.

  1. Optimize Your Custom Activity:
    -Review the code of your custom activity to ensure it is efficient and doesn’t contain any long-running or blocking operations.
    -Make sure that your activity is designed to handle large datasets efficiently, especially if it’s interacting with SharePoint with more than 200+ files/folders.
  2. Async/Await:
    -If your activity is performing any long-running or potentially blocking operations (such as network requests to SharePoint), consider using asynchronous programming with async and await to prevent freezing the UI.

Thanks,
@pratik.maskar

We would assume newer VS Studio Version as of now

We would assume newer VS Studio Version as of now

https://docs.uipath.com/activities/other/latest/developer/creating-activities-with-code

The activity creator doesn’t work with newer versions at the moment unfortunately: Activity Creator error - a problem was encountered creating the sub project - Visual Studio - Help / Activities - UiPath Community Forum

HI @farow31916 ,
Thanks for reaching out to UiPath Community.

You can try these steps to crosscheck.

  1. Optimize Your Custom Activity:
    -Review the code of your custom activity to ensure it is efficient and doesn’t contain any long-running or blocking operations.
    -Make sure that your activity is designed to handle large datasets efficiently, especially if it’s interacting with SharePoint with more than 200+ files/folders.
  2. Async/Await:
    -If your activity is performing any long-running or potentially blocking operations (such as network requests to SharePoint), consider using asynchronous programming with async and await to prevent freezing the UI.

Thanks,
@pratik.maskar

Hi, it isn’t when debugging, it’s just when i drag the activity into my workflow file, debug works fast and swift :slight_smile:

we also heard different, depending on the Activity Creator Version

Are you using the latest version of UiPath

Are you using the latest version of UiPath

Yes i’m using 2023.4.4

we also heard different, depending on the Activity Creator Version

Care to elaborate? Also you can only download the latest version of activity creator (4.0) using visual studio as far as i can tell.

You never responded, i’m interested in hearing more about this, could you elaborate?