activities
latest
false
Importante :
A tradução automática foi aplicada parcialmente neste conteúdo. A localização de um conteúdo recém-publicado pode levar de 1 a 2 semanas para ficar disponível.
UiPath logo, featuring letters U and I in white

Atividades do UIAutomation

Última atualização 9 de mar de 2026

Inject .NET Code

UiPath.Core.Activities.InjectDotNetCode

Description

Injeta código .NET no thread principal da interface gráfica do aplicativo de destino. Destinado ao uso com aplicativos .NET UI que não expõem tecnologias de automação tradicionais ou não podem ser direcionados corretamente por meios tradicionais.

Propriedades

Comum
  • ContinueOnError - Specifies if the automation should continue even when the activity throws an error. This field only supports Boolean values (True, False). The default value is False. As a result, if the field is blank and an error is thrown, the execution of the project stops. If the value is set to True, the execution of the project continues regardless of any error.

    Observação:

    If this activity is included in Try Catch and the value of the ContinueOnError property is True, no error is caught when the project is executed.

  • DisplayName - O nome de exibição da atividade.

Entrada
  • Montagem - O caminho completo para a montagem de compilação .NET que você deseja injetar.Este campo é compatível apenas com strings e variáveis String.

  • Nome do Método - o nome do método que você deseja executar. Somente métodos estáticos públicos são suportados.

    Observação:

    Um tipo não pode conter vários métodos com o mesmo nome. Se for esse o caso, um erro é exibido em runtime.

  • Destino.RegiãoDeRecorte - Define o retângulo de clipagem, em pixels, em relação ao ElementoDaUi, conforme as seguintes direções: esquerda, superior, direita, inferior. Suporta números positivos e negativos.

  • Target.Element - Use a variável ElementoDaUI retornada por outra atividade. Essa propriedade não pode ser usada com a propriedade Seletor. Esse campo é compatível apenas com variáveis ElementoDaUI.

  • Destino.Seletor - Propriedade de texto usada para localizar um determinado elemento de interface gráfica quando a atividade é executada. Em realidade, é um fragmento XML especificando atributos do elemento GUI procurado e de alguns de seus pais.

  • Destino.TempoLimiteEmMs - Especifica o período (em milissegundos) que se deve aguardar para a execução da atividade antes de gerar o erro SelectorNotFoundException. O valor padrão é de 30.000 milissegundos (30 segundos).

  • Target.WaitForReady - Antes de executar as ações, aguarda o destino ficar pronto. As seguintes opções estão disponíveis:

    • Nenhum — não espera por nada, exceto o elemento de interface gráfica do alvo existir antes de executar a ação. Por exemplo, você pode usar essa opção se quiser recuperar apenas o texto de uma página web ou clicar em um botão específico, sem precisar esperar todos os elementos da interface gráfica carregarem. Observe que isso pode ter consequências indesejadas se o botão depender de elementos ainda não carregados, como scripts.
    • Interativo/Completo - Espera que todos os elementos da interface gráfica no aplicativo de destino existam antes de executar, de fato, a ação.Para avaliar se um aplicativo está no estado Interativo ou Concluído, as seguintes tags são verificadas:
    • Aplicativos de área de trabalho — uma mensagem wm_null é enviada para verificar a existência das tags,<wnd> ,<ctrl> ,<java> ou. <uia>Se existirem, a atividade é executada.
    • Aplicativos web:
    1. Internet Explorer - A tag <webctrl> é usada para verificar se o estado Pronto do documento HTML está definido como Concluído. Além disso, o estado Ocupado deve ser definido como “Falso”.
    2. Outros - A tag <webctrl> é usada para verificar se o estado Pronto do documento HTML está Concluído.
    • Aplicativos SAP — primeiro a presença da tag <wnd> é verificada e, depois disso, uma API específica do SAP é usada para detectar se a sessão está ocupada ou não.
  • TipoDeNome - O nome da classe pública que contém o método de execução. Este campo é compatível apenas com strings e variáveis String.

  • Usar elemento de interface gráfica como primeiro argumento de função — usa o elemento de interface gráfica como o primeiro argumento para a função invocada. Com suporte apenas para formulários do Windows e aplicativos WPF.

    Para aplicativos do Windows Forms, o primeiro argumento da função invocada deve ser do tipo System.Windows.Forms.Control.

    Para aplicativos WPF, o primeiro argumento da função invocada deve ser do tipo System.Windows.DependencyObject.

Diversos
  • Privado - Se selecionado, os valores de variáveis e argumentos não são mais registrados no nível Verbose.
Saída
  • Resultado - O resultado do método invocado, armazenado em um variável Object.Este campo é compatível apenas com variáveis Object.

Injetando código em AppDomains não padrão

A atividade Injetar Código .NET injeta código apenas no DomínioDoApp padrão.

Alguns aplicativos são estruturados de tal maneira que os elementos que você pode precisar acessar ou manipular não estejam localizados dentro do AppDomain padrão. Portanto, injetar código no AppDomain padrão não é suficiente. Portanto, se os elementos da interface gráfica que você deseja indicar estiverem localizados em outro AppDomain, eles não estarão disponíveis para o código injetado.

Para corrigir isso, você deve modificar o processo de injeção para direcionar o AppDomain preciso que contém os elementos da interface gráfica. Mais exatamente, você precisa injetar código da função que é executada no AppDomain padrão em todos os AppDomains não padrão ou no AppDomain não padrão específico que contém os elementos da interface gráfica que você deseja indicar.

Criar um executor cruzado do AppDomain

Para executar código em AppDomains não padrão, você precisa criar uma classe derivada de MarshalByRefObject, contendo a função que deseja executar em AppDomains não padrão:

public class CrossAppDomainRunner : MarshalByRefObject
{
  public void Execute(IntPtr controlHandle)
  {
    // Implementation of the method that will be executed in the target AppDomain
    Trace.WriteLine("Sunt in " + AppDomain.CurrentDomain.FriendlyName);

    Control foundControl = null;
    try
    {
      foundControl = Control.FromHandle(controlHandle);
    }
    catch (Exception controlException)
    {
      int lastWin32Error = Marshal.GetLastWin32Error();
      Trace.WriteLine($"+++++ An exception occurred while getting the control from handle {controlHandle}. The message is: {controlException.Message}, Win32 Error: {lastWin32Error}");
            
    }
    if (foundControl != null)
    {
      Trace.WriteLine($"+++++ Found control {foundControl.Name} from handle {controlHandle}");
            
    }
    else
    {
      int lastWin32Error = Marshal.GetLastWin32Error();
      Trace.WriteLine($"+++++ Control NOT found based on handle {controlHandle}, Win32 Error: {lastWin32Error}");
            
    }
  }
}
public class CrossAppDomainRunner : MarshalByRefObject
{
  public void Execute(IntPtr controlHandle)
  {
    // Implementation of the method that will be executed in the target AppDomain
    Trace.WriteLine("Sunt in " + AppDomain.CurrentDomain.FriendlyName);

    Control foundControl = null;
    try
    {
      foundControl = Control.FromHandle(controlHandle);
    }
    catch (Exception controlException)
    {
      int lastWin32Error = Marshal.GetLastWin32Error();
      Trace.WriteLine($"+++++ An exception occurred while getting the control from handle {controlHandle}. The message is: {controlException.Message}, Win32 Error: {lastWin32Error}");
            
    }
    if (foundControl != null)
    {
      Trace.WriteLine($"+++++ Found control {foundControl.Name} from handle {controlHandle}");
            
    }
    else
    {
      int lastWin32Error = Marshal.GetLastWin32Error();
      Trace.WriteLine($"+++++ Control NOT found based on handle {controlHandle}, Win32 Error: {lastWin32Error}");
            
    }
  }
}

Basicamente, você tem uma função Execute que recebe um parâmetro IntPtr . Esse parâmetro contém o valor do controle que você está tentando encontrar. Neste exemplo, você precisa passar apenas um parâmetro IntPtr , mas, em sua situação específica, você pode adicionar quantos parâmetros desejar.

Como enumerar e injetar código em AppDomains não padrão

Para enumerar os outros AppDomains, você precisa de um ponteiro para a interface ICorRuntimeHost de mscoree. Para fazê-lo, você precisa declarar essa interface:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;

namespace mscoree
{
    [CompilerGenerated]
    [Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [TypeIdentifier]
    [ComImport]
    [CLSCompliant(false)]
    public interface ICorRuntimeHost
    {
  void _VtblGap1_11();

  void EnumDomains(out IntPtr enumHandle);

  void NextDomain([In] IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] out object appDomain);

  void CloseEnum([In] IntPtr enumHandle);
    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;

namespace mscoree
{
    [CompilerGenerated]
    [Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [TypeIdentifier]
    [ComImport]
    [CLSCompliant(false)]
    public interface ICorRuntimeHost
    {
  void _VtblGap1_11();

  void EnumDomains(out IntPtr enumHandle);

  void NextDomain([In] IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] out object appDomain);

  void CloseEnum([In] IntPtr enumHandle);
    }
}

É preciso declarar uma classe que contenha métodos nativos para inicializar o Modelo de Objeto do Componente (COM):

public static class NativeMethods
{
  [DllImport("ole32.dll")]
  public static extern int CoInitializeEx(IntPtr pvReserved, COINIT dwCoInit);

  public enum COINIT : uint
  {
    /// Initializes the thread for multi-threaded object concurrency.
    COINIT_MULTITHREADED = 0x0,
    /// Initializes the thread for apartment-threaded object concurrency. 
    COINIT_APARTMENTTHREADED = 0x2,
    // ...
  }
}
public static class NativeMethods
{
  [DllImport("ole32.dll")]
  public static extern int CoInitializeEx(IntPtr pvReserved, COINIT dwCoInit);

  public enum COINIT : uint
  {
    /// Initializes the thread for multi-threaded object concurrency.
    COINIT_MULTITHREADED = 0x0,
    /// Initializes the thread for apartment-threaded object concurrency. 
    COINIT_APARTMENTTHREADED = 0x2,
    // ...
  }
}

Você precisa de um método para obter um objeto ICorRunttimeHost :

public static ICorRuntimeHost GetCorRuntimeHost()
{
  return (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}
public static ICorRuntimeHost GetCorRuntimeHost()
{
  return (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}

Agora, você tem tudo no lugar para enumerar os outros AppDomains e executar código neles. A função GetControlData é executada pela atividade Injetar Código .NET no AppDomain padrão:

public static void GetControlData(Int64 controlHandle, out string response)
{
  //initialising COM
  NativeMethods.CoInitializeEx(IntPtr.Zero, NativeMethods.COINIT.COINIT_MULTITHREADED);

  mscoree.ICorRuntimeHost host = null;
  try
  {
    host = (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
  }
  catch (COMException comEx)
  {
    Trace.WriteLine($"COMException: {comEx.Message}, HRESULT: {comEx.ErrorCode}");
  }
  catch (Exception ex)
  {
    // Handle other exceptions
    Trace.WriteLine($"Exception: {ex.Message}");
  }

  IntPtr enumHandle = IntPtr.Zero;

  try
  {
    //now that we have ICorRuntimeHost object we can use it to enumerate the other domains
    host.EnumDomains(out enumHandle);
    object domain = null;
    host.NextDomain(enumHandle, out domain);
    while (domain != null)
    {
      //for each appdomain obtained
      AppDomain appDomain = (AppDomain)domain;
      //appDomain.BaseDirectory; - you might want to copy your dll 
      //in the appDomain.BaseDirectory cause otherwise it might not find 
      //the assembly 

      ObjectHandle handle = appDomain.CreateInstance(
        typeof(CrossAppDomainRunner).Assembly.FullName,
        typeof(CrossAppDomainRunner).FullName);

      // Unwrap to get the actual object
      var runnerProxy = handle.Unwrap();

      // Use reflection to call the Execute method
      MethodInfo executeMethod = runnerProxy.GetType().GetMethod("Execute", new Type[] { typeof(IntPtr) });
      //pass parameters as new object[]
      executeMethod.Invoke(runnerProxy, new object[] { new IntPtr(controlHandle) });

      //go to next appdomain
      host.NextDomain(enumHandle, out domain);
      if (domain == null)
        break;
    }
  }
  finally
  {
    if (host != null)
    {
      if (enumHandle != IntPtr.Zero)
      {
        host.CloseEnum(enumHandle);
      }

      Marshal.ReleaseComObject(host);
    }
  }
  response = string.Empty;
}
public static void GetControlData(Int64 controlHandle, out string response)
{
  //initialising COM
  NativeMethods.CoInitializeEx(IntPtr.Zero, NativeMethods.COINIT.COINIT_MULTITHREADED);

  mscoree.ICorRuntimeHost host = null;
  try
  {
    host = (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
  }
  catch (COMException comEx)
  {
    Trace.WriteLine($"COMException: {comEx.Message}, HRESULT: {comEx.ErrorCode}");
  }
  catch (Exception ex)
  {
    // Handle other exceptions
    Trace.WriteLine($"Exception: {ex.Message}");
  }

  IntPtr enumHandle = IntPtr.Zero;

  try
  {
    //now that we have ICorRuntimeHost object we can use it to enumerate the other domains
    host.EnumDomains(out enumHandle);
    object domain = null;
    host.NextDomain(enumHandle, out domain);
    while (domain != null)
    {
      //for each appdomain obtained
      AppDomain appDomain = (AppDomain)domain;
      //appDomain.BaseDirectory; - you might want to copy your dll 
      //in the appDomain.BaseDirectory cause otherwise it might not find 
      //the assembly 

      ObjectHandle handle = appDomain.CreateInstance(
        typeof(CrossAppDomainRunner).Assembly.FullName,
        typeof(CrossAppDomainRunner).FullName);

      // Unwrap to get the actual object
      var runnerProxy = handle.Unwrap();

      // Use reflection to call the Execute method
      MethodInfo executeMethod = runnerProxy.GetType().GetMethod("Execute", new Type[] { typeof(IntPtr) });
      //pass parameters as new object[]
      executeMethod.Invoke(runnerProxy, new object[] { new IntPtr(controlHandle) });

      //go to next appdomain
      host.NextDomain(enumHandle, out domain);
      if (domain == null)
        break;
    }
  }
  finally
  {
    if (host != null)
    {
      if (enumHandle != IntPtr.Zero)
      {
        host.CloseEnum(enumHandle);
      }

      Marshal.ReleaseComObject(host);
    }
  }
  response = string.Empty;
}

O exemplo acima injeta o código em todos os AppDomains. Após descobrir o DomínioDoAplicativo onde os elementos de interface gráfica que deseja indicar estão localizados, você pode enumerar todos os DomíniosAplicativos, mas injetar código apenas no DomínioDoAplicativo necessário.

Esta página foi útil?

Conectar

Precisa de ajuda? Suporte

Quer aprender? Academia UiPath

Tem perguntas? Fórum do UiPath

Fique por dentro das novidades