elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


  Mostrar Mensajes
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 835
1  Programación / .NET / Re: Evitar se congele el formulario al hacer un for en: 14 Mayo 2016, 22:40
Por favor, cuando especifiques un error, muestra el código que lo genera. No somos adivinos.

De todas formas el mensaje de la excepción creo que te está indicando que por algún motivo en "X" miembro debes habilitar la comunicación entre los threads que se quieran comunicar con ese miembro via COM, y para ello ese miembro debe ejecutarse en un entorno de único hilo (single threaded apartment a.k.a. STA). Dicho miembro puede ser el punto de entrada de tu aplicación, u otro método, según lo que hagas en tu código y como lo estés haciendo.

Debes añadirle este atributo a dicho método:

Si estás usando un objeto de tipo Thread, también prueba utilizando el método Thread.SetApartmentState antes de iniciarlo.

Saludos.
2  Programación / .NET / Re: Evitar se congele el formulario al hacer un for en: 14 Mayo 2016, 15:08

El compañero @KuBox ya te ha dado y explicado la solución, particionar la lógica del algoritmo en bloques de método individuales es irse por las ramas, ya que sigues sin evaluar la propiedad que se te mencionó.

Pero aparte del uso de la propiedad Control.Invoke, es muy recomendable que también utilices la propiedad Control.InvokeRequired para evitar intentar invocar el control de forma síncrona en caso de que haya sido creado desde el mismo hilo, ya que de lo contrario esto ocasionaría comportamientos indeseados y/o errores, como por ejemplo la recreación del handle del control;

También hay otros controles de errores adicionales que serían bastante imprescindibles como por ejemplo:
· Utilizar la declaración SyncLock para evitar que múltiples hilos intenten modificar el control, por ejemplo si instancias e inicias el mismo BackGroundWorker 2 veces al mismo tiempo.
· Comprobar si los recursos del control fueron liberados (Control.IsDisposed).
· Comprobar si el handle de la ventana se creó, y verificarlo antes de llamar a Control.InvokeRequired, ya que de lo contrario Control.InvokeRequired siempre devolverá False indiferentemente del hilo donde se creó el control.

...Pero por el momento podemos dejarlo con la medida de seguridad básica y principal, que sería, como ya he dicho, evaluar el valor devuelto por Control.InvokeRequired.

Este sería el código que puedes utilizar:
Código
  1. Imports System.Threading
  2.  
  3. Public NotInheritable Class Work : Implements IDisposable
  4.  
  5. #Region " Private Fields "
  6.  
  7.    <EditorBrowsable(EditorBrowsableState.Never)>
  8.    Friend WithEvents Bgw As BackgroundWorker
  9.  
  10.    Private ReadOnly mreSync As ManualResetEvent
  11.    Private ReadOnly mreAsync As ManualResetEvent
  12.  
  13.    Private isRunSync As Boolean = False
  14.    Private isCancelSyncRequested As Boolean = False
  15.    Private isPauseRequested As Boolean = False
  16.  
  17. #End Region
  18.  
  19. #Region " Properties "
  20.  
  21.    <EditorBrowsable(EditorBrowsableState.Always)>
  22.    Public ReadOnly Property IsRunning As Boolean
  23.        Get
  24.            Return (Me.Bgw IsNot Nothing) AndAlso Not (Me.isPausedB)
  25.        End Get
  26.    End Property
  27.  
  28.    <EditorBrowsable(EditorBrowsableState.Always)>
  29.    Public ReadOnly Property IsPaused As Boolean
  30.        Get
  31.            Return (Me.Bgw IsNot Nothing) AndAlso (Me.isPausedB)
  32.        End Get
  33.    End Property
  34.    Private isPausedB As Boolean = False
  35.  
  36.    Public ReadOnly Property IsDisposed As Boolean
  37.        <DebuggerStepThrough>
  38.        Get
  39.            Return (Me.Bgw Is Nothing)
  40.        End Get
  41.    End Property
  42.  
  43. #End Region
  44.  
  45. #Region " Constructors "
  46.  
  47.    <DebuggerNonUserCode>
  48.    Public Sub New()
  49.  
  50.        Me.Bgw = New BackgroundWorker()
  51.        Me.mreSync = New ManualResetEvent(initialState:=False)
  52.        Me.mreAsync = New ManualResetEvent(initialState:=True)
  53.  
  54.    End Sub
  55.  
  56. #End Region
  57.  
  58. #Region " Public Methods "
  59.  
  60.    <DebuggerStepThrough>
  61.    Public Sub Run()
  62.  
  63.        If Not (Me.IsDisposed) AndAlso Not (Me.Bgw.IsBusy) Then
  64.            Me.isRunSync = True
  65.            With Me.Bgw
  66.                .WorkerSupportsCancellation = False
  67.                .WorkerReportsProgress = False
  68.                .RunWorkerAsync()
  69.            End With
  70.            Me.mreSync.WaitOne()
  71.  
  72.        Else
  73.            Throw New InvalidOperationException("BackGroundWorker is already running.")
  74.  
  75.        End If
  76.  
  77.    End Sub
  78.  
  79.    <DebuggerStepThrough>
  80.    Public Sub RunAsync()
  81.  
  82.        If Not (Me.IsDisposed) AndAlso Not (Me.Bgw.IsBusy) Then
  83.            With Me.Bgw
  84.                .WorkerSupportsCancellation = True
  85.                .WorkerReportsProgress = True
  86.                .RunWorkerAsync()
  87.            End With
  88.  
  89.        Else
  90.            Throw New InvalidOperationException("BackGroundWorker is already running.")
  91.  
  92.        End If
  93.  
  94.    End Sub
  95.  
  96.    <DebuggerStepThrough>
  97.    Public Sub Pause()
  98.  
  99.        If Not (Me.IsDisposed) AndAlso Not (Me.isPausedB) Then
  100.            Me.isPauseRequested = True
  101.            Me.isPausedB = True
  102.            Me.mreAsync.Reset()
  103.  
  104.        Else
  105.            Throw New InvalidOperationException("BackGroundWorker is not running.")
  106.  
  107.        End If
  108.  
  109.    End Sub
  110.  
  111.    <DebuggerStepThrough>
  112.    Public Sub [Resume]()
  113.  
  114.        If Not (Me.IsDisposed) AndAlso (Me.isPausedB) Then
  115.            Me.isPausedB = False
  116.            Me.isPauseRequested = False
  117.            Me.mreAsync.Set()
  118.  
  119.        Else
  120.            Throw New InvalidOperationException("BackGroundWorker is not paused.")
  121.  
  122.        End If
  123.  
  124.    End Sub
  125.  
  126.    <DebuggerStepThrough>
  127.    Public Sub Cancel(Optional ByVal throwOnError As Boolean = False)
  128.  
  129.        Me.isCancelSyncRequested = True
  130.        Me.CancelAsync()
  131.        Me.mreSync.WaitOne()
  132.        Me.isCancelSyncRequested = False
  133.  
  134.    End Sub
  135.  
  136.    <DebuggerStepThrough>
  137.    Public Sub CancelAsync(Optional ByVal throwOnError As Boolean = False)
  138.  
  139.        If Not (Me.IsDisposed) AndAlso Not (Me.Bgw.CancellationPending) AndAlso (Me.Bgw.IsBusy) Then
  140.            Me.mreAsync.Set() ' Resume thread if it is paused.
  141.            Me.Bgw.CancelAsync()
  142.  
  143.        Else
  144.            Throw New InvalidOperationException("BackGroundWorker is not initialized.")
  145.  
  146.        End If
  147.  
  148.    End Sub
  149.  
  150. #End Region
  151.  
  152. #Region " Private Methods "
  153.  
  154.    <DebuggerStepThrough>
  155.    Private Function AddLvItem(ByVal src As ListView, ByVal dst As ListView, ByVal index As Integer) As ListViewItem
  156.  
  157.        Dim result As ListViewItem = Nothing
  158.  
  159.        If (dst.InvokeRequired) Then
  160.            dst.Invoke(
  161.                Sub()
  162.                    Try
  163.                        result = dst.Items.Add(src.Items(index).Text)
  164.                    Catch ex As Exception
  165.                        Debug.WriteLine(String.Format("Woker exception occured: {0}", ex.Message))
  166.                    End Try
  167.                End Sub)
  168.        Else
  169.            Try
  170.                result = dst.Items.Add(src.Items(index).Text)
  171.            Catch ex As Exception
  172.                Debug.WriteLine(String.Format("Woker exception occured: {0}", ex.Message))
  173.            End Try
  174.  
  175.        End If
  176.  
  177.        Return result
  178.  
  179.    End Function
  180.  
  181. #End Region
  182.  
  183. #Region " Event-Handlers "
  184.  
  185.    <DebuggerStepperBoundary>
  186.    Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
  187.    Handles Bgw.DoWork
  188.  
  189.        Dim lock As Object = ""
  190.        SyncLock lock
  191.  
  192.            Dim lv1 As ListView = WindowsApplication1.Form1.ListView1
  193.            Dim lv2 As ListView = WindowsApplication1.Form1.ListView2
  194.            Dim max As Integer = lv2.Items.Count
  195.            Dim itemIndex As Integer = -1
  196.  
  197.            For i As Integer = 0 To (max - 1)
  198.  
  199.                If (Me.Bgw.CancellationPending) Then
  200.                    e.Cancel = True
  201.                    Exit For
  202.  
  203.                Else
  204.                    If Me.isPauseRequested Then ' Pause this thread.
  205.                        Me.mreAsync.WaitOne(Timeout.Infinite)
  206.                    End If
  207.  
  208.                    Dim lvi As ListViewItem = Me.AddLvItem(src:=lv2, dst:=lv1, index:=Interlocked.Increment(itemIndex))
  209.                    If (lvi IsNot Nothing) Then
  210.                        Debug.WriteLine(String.Format("ListViewItem Text: {0}", lvi.Text))
  211.                    End If
  212.  
  213.                    If Me.Bgw.WorkerReportsProgress Then
  214.                        Me.Bgw.ReportProgress((i + 1) * (100 \ max))
  215.                    End If
  216.  
  217.                    Thread.Sleep(TimeSpan.FromSeconds(1))
  218.  
  219.                End If
  220.  
  221.            Next i
  222.  
  223.        End SyncLock
  224.  
  225.        If (Me.Bgw.WorkerReportsProgress) AndAlso Not (Me.Bgw.CancellationPending) Then
  226.            Me.Bgw.ReportProgress(100)
  227.        End If
  228.  
  229.        If (Me.isRunSync) OrElse (Me.isCancelSyncRequested) Then
  230.            Me.mreSync.Set()
  231.        End If
  232.  
  233.    End Sub
  234.  
  235.    <DebuggerStepperBoundary>
  236.    Private Sub Bgw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
  237.    Handles Bgw.ProgressChanged
  238.  
  239.        Debug.WriteLine(String.Format("Work Progress: {0:00.00}%", e.ProgressPercentage))
  240.  
  241.    End Sub
  242.  
  243.    <DebuggerStepperBoundary>
  244.    Private Sub Bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
  245.    Handles Bgw.RunWorkerCompleted
  246.  
  247.        If (e.Cancelled) Then
  248.            Debug.WriteLine("Work state: Cancelled")
  249.  
  250.        ElseIf (e.Error IsNot Nothing) Then
  251.            Debug.WriteLine("Work state: Error")
  252.  
  253.        Else
  254.            Debug.WriteLine("Work state: Success")
  255.  
  256.        End If
  257.  
  258.        Me.Dispose()
  259.  
  260.    End Sub
  261.  
  262. #End Region
  263.  
  264. #Region " IDisposable Implementation "
  265.  
  266.    Private isDisposedB As Boolean
  267.  
  268.    <DebuggerStepThrough>
  269.    Public Sub Dispose() Implements IDisposable.Dispose
  270.  
  271.        Me.Dispose(isDisposing:=True)
  272.        GC.SuppressFinalize(obj:=Me)
  273.  
  274.    End Sub
  275.  
  276.    <DebuggerStepThrough>
  277.    Private Sub Dispose(ByVal isDisposing As Boolean)
  278.  
  279.        If (Not Me.isDisposedB) AndAlso (isDisposing) Then
  280.            Me.Bgw.Dispose()
  281.            Me.Bgw = Nothing
  282.  
  283.            With Me.mreSync
  284.                .SafeWaitHandle.Close()
  285.                .SafeWaitHandle.Dispose()
  286.                .Close()
  287.                .Dispose()
  288.            End With
  289.  
  290.            With Me.mreAsync
  291.                .SafeWaitHandle.Close()
  292.                .SafeWaitHandle.Dispose()
  293.                .Close()
  294.                .Dispose()
  295.            End With
  296.  
  297.        End If
  298.  
  299.        Me.isDisposedB = True
  300.  
  301.    End Sub
  302.  
  303. #End Region
  304.  
  305. #Region " Hidden Methods "
  306.  
  307.    <EditorBrowsable(EditorBrowsableState.Never)>
  308.    <DebuggerNonUserCode>
  309.    Public Shadows Function GetHashCode() As Integer
  310.        Return MyBase.GetHashCode
  311.    End Function
  312.  
  313.    <EditorBrowsable(EditorBrowsableState.Never)>
  314.    <DebuggerNonUserCode>
  315.    Public Shadows Function [GetType]() As Type
  316.        Return MyBase.GetType
  317.    End Function
  318.  
  319.    <EditorBrowsable(EditorBrowsableState.Never)>
  320.    <DebuggerNonUserCode>
  321.    Public Shadows Function Equals(ByVal obj As Object) As Boolean
  322.        Return MyBase.Equals(obj)
  323.    End Function
  324.  
  325.    <EditorBrowsable(EditorBrowsableState.Never)>
  326.    <DebuggerNonUserCode>
  327.    Public Shadows Function ToString() As String
  328.        Return MyBase.ToString
  329.    End Function
  330.  
  331. #End Region
  332.  
  333. End Class

Ejemplo de uso:
Código
  1. Public NotInheritable Class Form1 : Inherits Form
  2.  
  3.    Friend MyWork As Work
  4.  
  5.    Private Sub Button1_Click() Handles Button1.Click
  6.  
  7.        If (Me.MyWork IsNot Nothing) Then
  8.            Me.MyWork.Cancel()
  9.        End If
  10.  
  11.        Me.MyWork = New Work
  12.        Me.MyWork.RunAsync()
  13.  
  14.    End Sub
  15.  
  16. End Class

Como se puede ver, la clase donde encapsulo el BackGroundWorker tiene varias funcionalidades añadidas para controlar operaciones sincrónicas y asincrónicas, si quieres ver la implementación completa y original, y con la documentación XML, aquí lo tienes:


Saludos.
3  Programación / Scripting / Re: Comunicar dos consolas de comandos (CMD) en: 14 Mayo 2016, 03:38
Bueno, gracias por la ayuda de todas maneras.
En realidad uso batch para hacer estas cosas complicadísimas sólo por eso, porque es limitado.

Igual, creo que tengo otra manera de hacer el proyecto. Esto de comunicar los mensajes sólo lo necesito para hacer más facil la parte de añadir expresiones a los "bots", de manera que las expresiones quedaran escritas en un archivo cmd aparte y no en el intérprete.

Si lo logro entender y terminar el proyecto lo subo!

Ahora que has mencionado el archivo de texto ...claro, una posible manera de comunicarse en Batch sería mediante el uso de un archivo local que haga de intermediario, ya que desde ambas instancias de la CMD puedes escribir en el mismo archivo, y desde ambas puedes leer lo que la otra instancia escribió (al final del archivo), y para saber con certeza si una de las dos instancias "intenta comunicarse" solo tendrías que comprobar si el tamaño del archivo es distinto al tamaño de la ultima vez que lo comprobaste (o comprobar la cantidad de lineas), en un búcle FOR con iteraciones indefinidas (por ejemplo).

Eso me parece una idea simple y efectiva, pero ahora también se me ocurre que tal vez podrías comunicarte mediante Telnet, aunque sin saber muy bien como es la "estructura" de ese script o esos scripts no se muy bien que decirte.

Saludos
4  Programación / .NET / Re: Obtener texto de label en aplicación externa WPF en: 14 Mayo 2016, 03:19
La persona que escribió la respuesta que has citado de StackOverflow, se refiere a que al final ha acabado trasladando el código de C# a un nuevo proyecto de VC++ (escrito en modo no administrado).

¿Qué cuales cambios necesitarías hacer?, pues exactamente lo mismo que hizo esa persona, si quieres usar la API de UI Automation cambia de lenguaje para desarrollarlo en C++ importando los headers que se especifican en la referencia de la API de UI Automation (aquí), por que la otra opción sería perder unas semanas, un mes, o varios meses de tu vida en definir una infinidad de P/Invokes y wrappers en C#/VB.NET (e investigar y testearlos), lo que aparte de acabar logrando ser un código con probable inestabilidad (lo insuficientemente controlado), no es muy viable perder el tiempo de esa manera que digamos.

Como esa persona dijo, la herramienta de Microsoft UI Inspect está desarrollada en VC++, sin embargo tu estás bajo VB.NET o C#, y por ese motivo, cuando puedes usar lo mismo en un lenguaje que ya conoces, me parece una tontería pensar en hacer lo contrario, pero de todas formas si quieres probar a hacerlo mediante código no administrado entonces ya tienes un enlace a la API de UI Automation indicando, como ya he dicho, los headers de C++ y toda la información necesaria respecto a las definiciones.

No puedo ofrecerte una solución por que ni tan siquiera conozco la estructura de la UI que estás analizando, ni tengo el programa para testearlo, ni tampoco he pasado por el mismo problema que mencionas, lo siento, pero ten por seguro que debe existir una solución mediante código administrado, dudo mucho que las classes de .Net con los wrappers de UI Automation omitan elementos de la UI que al usar su equivalente desde la implementación "nativa" éstos no se omitan, eso suena demasiado extraño, así que desde la ignorancia yo simplemente creo que falta algo que añadirle a la ecuación (ej. una condición de búsqueda más especializada), pero que por el momento desconoces que factor hay que añadirle.

Saludos!.
5  Programación / Scripting / Re: Comunicar dos consolas de comandos (CMD) en: 14 Mayo 2016, 03:08
Con lo que dijiste, Elektro, no tengo ni la menor idea de cómo hacer nada de lo que dijiste pero voy a investigar y hacer lo que pueda.

Batch es una herramienta muy limitada, no te molestes en seguir buscando, no se pueden aplicar las técnicas que mencioné. Puedes utilizar el parámetro SHARED del comando START para algo relacionado, pero su propósito de uso no tiene nada que ver con este propósito de comunicarse.



Las modificaciones en las variables de entorno solo tienen efecto para la instancia actual de la CMD y solo perduran durante el tiempo de vida de dicha instancia, sinceramen a mi no se me ocurre nada, lo siento.

Saludos!

6  Foros Generales / Foro Libre / Re: ¿Cuál es la verdadera razón por la cual dormimos? en: 14 Mayo 2016, 01:25
Nuestro cerebro literálmente hablando es un ordenador biológico, desde el primer instante en el que estamos despiertos empieza a procesar todo tipo de datos sensoriales, los visuales, los auditivos, y etc., consumiendo así los recursos diarios limitados de nuestro procesador y el resto de componentes como la gráfica y nuestra tarjeta de memoria cerebral.

Las horas de sueño son necesarias para poner en un estado de hibernación o stand-by nuestro ordenador y así reducir el consumo de recursos al máximo, y entonces, se inician unas tareas programadas para almacenar lo que nuestra máquina consciente haya procesado durante el día (experiencia), filtrar y excluir datos innecesarios (evolución), hacer un backup de lo que nos pueda servir (recuerdos), y evaluar todo tipo de condiciones futuras en posibles escenarios de supervivencia (sueños y pesadillas).

Por muy ridículo o inasimilable que resulte, no se puede negar que todos los seres vivos con cerebro compartimos muchísimos aspectos similares comparándonos con el funcionamiento y limitaciones de un dispositivo informático como sería un PC, un smarthpone o una cámara, cosa que no podemos decir por ejempo de una una silla, un armario, o una pelota.

El ser humano hace mucho tiempo que empezó a intentar crear un ser corporeo y con vida a partir de recursos informáticos, los primeros intentos fueron conocidos como videojuegos (ej. 'Los Sims'), y ahora lo conocemos como robots con inteligencia artificial, implantes humanos artificiales, e incluso el nacimiento de animales clonados vivitos y coleando (ej. La oveja Dolly).

Así lo veo yo, solo es necesario tiempo y avances tecnológicos para que un dia no muy lejano acabar creando algo que podamos llamar "ser", seguido de "humano", y entonces toda la humanidad se tendrá que plantear la siguiente cuestión:

'¿Qué fue primero, el hombre, o la máquina?.'

...para acabar concluyendo, descubriendo y aceptar que somos exactamente lo mismo, solo que nosotros desconocemos quien nos creó o nos "programó" (no tiene por que ser un Dios omnipotente e incorporeo que vive en los cielos, no, pudo haber sido otro ser vivo el que nos dió la vida, como una especie de científicos extraterrestres, por así decirlo).

PD: Si el hombre ha usado la tecnología para diseñar el PC/robot a su imagen y semejanza, ¿quien dice que con la suficiente paciencia el hombre no pueda ser capaz de crear a otro hombre?.

Saludos!
7  Programación / Scripting / Re: Comunicar dos consolas de comandos (CMD) en: 13 Mayo 2016, 20:21
¿No te estarás refiriendo más bien a comunicar dos aplicaciones command-line entre si? (por que si realmente hablamos de dos procesos 'cmd.exe' a los que no tienes ningún control...)

En ese caso puedes enviar y recibir cadenas de texto asignando un espacio de memoria compartida para ambos procesos, o también puedes hacerlo mediante un socket abierto, u otras técnicas de IPC.

Saludos
8  Programación / Programación General / Re: Se puede impedir que imacros se actualice? en: 12 Mayo 2016, 21:27
empezemos por que es "imacros"? no es esto una pregunta del foro de mac osx?

iMacros es una aplicación multi plataforma para la automatización de navegadores y el testing a nivel web (typo WATIR o Selenium, te serán nombres más conocidas).

Yo lo tengo para Windows, pero hace muchísimo que no lo uso para nada.



Se puede impedir que imacros se actualice?

Asumiendo que iMacros no tenga ninguna opción para desactivar las actualizaciones automáticas, en MAC OSX no se como se logrará, pero en Windows podrías añadir un mapeo al archivo HOSTS de windows para denegar las actualizaciones programáticas de la aplicación, claro está que para ello primero deberás hacer un pequeño monitoreo con cualquier herramienta de análisis de conexiones establecidas por la aplicación (cuando éste demande la actualización automática) para descubrir la IP, y entonces poder añadirla al archivo HOSTS.

Otra opción más directa sería utilizar el Firewall de Windows para añadir una regla que deniegue todas las conexiones salientes, pero denegar todas las conexiones tal vez podría traer consecuencias negativas en el funcionamiento de la aplicación, depende de como trabaje el programa, siempre puedes hacerlo así y si ves que el programa da error o no va bien entonces deshaces la regla del Firewall.

Saludos
9  Programación / Scripting / Re: Elimina archivos < 15 dias problema con rutas por espacios en: 12 Mayo 2016, 17:59
si tuvieras que recomendarme un lenguaje cual seria? aver si me pongo en ello

Para este tipo de tareas, algo sencillo a la vez que efectivo sería Visual Basic.NET (no confundir con VB6 ni VBS) o C#, en ambos lo harías de la misma manera pero utilizando una sintaxis distinta.

Con la función System.IO.Directory.GetFiles() puedes obtener los archivos, y de manera recursiva (o no).
Con las propiedades del type System.IO.FileInfo puedes obtener la fecha de creación, modificación o último acceso de un archivo.
Para la exclusión, una manera sencilla sería con una query de LINQ-to-objects (From fi As FileInfo In files Where Not (fi.CreationTime < DateTime.Today.AddDays(-15)), así de simple en una sola linea).

PD: Hasta para alguien que jamás haya tocado esos lenguajes creo que es muy sencillo si buscas ejemplos de los nombres que he mencionado en Google y lo intentas hacer, en serio.

Saludos!
10  Programación / .NET / Re: Obtener texto de label en aplicación externa WPF en: 12 Mayo 2016, 12:36
Hola.

1:
La herramienta Spy++, aparte de poder considerarla obsoleta por su descontinuación de desarrollo o desactualización, está diseñada y enfocada para la inspección de ventanas Win32, y aquí surge el problema, por que una aplicación WPF no trabaja con el modelo de la API Win32/Win64, es una tecnología completamente diferente, sin embargo, el elemento de ventana principal de una aplicación WPF sigue exponiendo un handle de ventana (HWND) accesible mediante la class HwndWrapper, que sirve como contenedor de la WinAPI y WPF.

Como herramientas más modernas, completas y en constante actualización para inspeccionar ventanas Win32 y WPF, estas son mis recomendaciones:

  • XAML Spy
    Solamente para aplicaciones WPF.
    Tiene una interfáz de usuario muy amigable y bonita.
     
  • Microsoft UI Inspect
    Para aplicaciones Win32 y WPF.
    Lo puedes encontrar en el SDK de Windows para tu versión de Windows actual.



2:
Para identificar un elemento de una UI en WPF, generálmente no es necesario recurrir a la metodología que estás aplicando con la WinAPI, puedes evitar toda la tediosidad que supone la implementación y el uso inseguro de código no administrado con las típicas definiciones de las funciones que has mencionado de la lib. user32.dll para identificar elementos en la UI y etc...

En su lugar, puedes usar código administrado aprovechando el potencial del framework de Microsoft UI Automation, con los ensamblados de WPF (puedes utilizarlos desde windowsForms también, e incluso puedes utilizarlos para ventanas Win32 también, aunque todo esto dependerá siempre de ciertas circunstancias).

El uso de UI Automation resulta bastante sencillo, se basa en crear condiciones de búsqueda para hallar el elemento deseado, deberiamos saber lo que andamos buscando tras haber inspeccionado la aplicación con UI Inspect o nuestra herramienta favorita, pero si desconocemos lo que tenemos que buscar entonces siempre podemos iterar las ventanas y los árboles de controles para ir descubriendo la información como hariamos con el callback de la función EnumChildwindows y etc. para ventanas Win32.

Si creamos un nuevo proyecto WPF y le añadimos un LabelControl a la ventana principal, quedando así el código XAML:
Código
  1. <Window x:Class="WpfApplication1.MainWindow"
  2.        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.        xmlns:local="clr-namespace:WpfApplication1"
  7.        mc:Ignorable="d"
  8.        Title="Mi Ventana" Height="350" Width="525">
  9.    <Grid>
  10.        <Label Content="This is a Label control." />
  11.    </Grid>
  12. </Window>

Esto sería un ejemplo básico para identificar el label y obtener su texto en la aplicación compilada:
Código
  1. Imports Windows
  2. Imports Windows.Automation
  3.  
  4. ...
  5.  
  6. Dim pid As Integer = Process.GetProcessesByName("WpfApplication1").Single().Id
  7.  
  8. Dim parentConditions As New OrCondition({
  9.    New PropertyCondition(AutomationElement.ProcessIdProperty, pid, PropertyConditionFlags.None),
  10.    New PropertyCondition(AutomationElement.NameProperty, "Mi Ventana", PropertyConditionFlags.IgnoreCase)
  11. })
  12.  
  13. Dim labelConditions As New AndCondition({
  14.    New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text, PropertyConditionFlags.None),
  15.    New PropertyCondition(AutomationElement.RuntimeIdProperty, {7, 5924, 9119245}, PropertyConditionFlags.None)
  16. })
  17.  
  18. Dim parentElement As AutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, parentConditions)
  19. Dim labelElement As AutomationElement = parentElement.FindFirst(TreeScope.Children, labelConditions)
  20.  
  21. If (labelElement IsNot Nothing) Then
  22.    Dim labelText As String = labelElement.Current.Name
  23.    Console.WriteLine(labelText)
  24. End If

Nótese que en el código de arriba la condición de RuntimeIdProperty está hardcodeada, el label de tu aplicación tendrá otra Id asignada (lo puedes averiguar facilmente con UI Inspect, o en tiempo de ejecución con la función AutomationElement.GetRuntimeId) ...igual que el nombre del executable y el título de la ventana,
y dependiendo de la estructura de la aplicación seguramente debas añadir condiciones adicionales para identificar el espacio de trabajo y/o ventana donde se encuentre ese label.

Saludos.
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 835
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines