2010-12-16 23 views
6

Así que he estado investigando por un tiempo y estoy en un callejón sin salida. Estoy haciendo algo de automatización de IE. En C#/.NET, ¿cómo indago y consumo una alerta de JavaScript() o confirmo() para que pueda hacer cosas como tomar su texto y hacer clic en los botones OK \ Cancelar?C# sonda y captura Javascript Alert() y Confirm()

actualización:

necesito reiterar: Tengo que ser capaz de tirar y verificar el texto de una alerta() o confirmar(), así como enviar un OK o Cancelar clic. Un ejemplo de una prueba de este tipo sería asegurarse de que, cuando hago clic en eliminar, la confirmación() no dice "¿Estás seguro de que te gustaría ir a México?" o cualquier otra cosa excepto el mensaje adecuado.

Por las dudas, permítanme reiterar: A los efectos de esta prueba, tengo cero control sobre la fuente del sitio web en cuestión.

Por último, estoy usando SHDocVw.InternetExplorer.

+0

¿Está utilizando IE o está creando una aplicación personalizada con un control WebBrowser? – zsalzbank

+0

¿Por "sonda para" está manejando el pre-navegador de origen o solo después de que se muestra? ¿Estás sirviendo a ti mismo? ¿Es posible tener estas cosas usar diálogos modales en lugar de cuadros de alerta y manejarlos en javascript? – jcolebrand

+0

Posible engaño de http://stackoverflow.com/questions/77659/blocking-dialogs-in-net-webbrowser-control – Zach

Respuesta

1

FindWindow - lo acercarán; usted quiere un identificador de ventana pero no sabrá con certeza cómo encontrarlo.

Mejor sería usar EnumWindows. Aquí hay un ejemplo de una rutina que puede ejecutar cada segundo o dos que le dará una tonelada de información sobre cada ventana del sistema, luego puede analizarla. Puede verificar el tipo de ventana, el texto en ella, obtener los botones y enviar un mensaje de clic a la derecha. Te permitirá hacer todo lo que esperas poder hacer.

Para obtener el texto que envía un wm_gettext y para el botón, puede salirse con la suya wm_click.

Perdón por la C. El siguiente mejor ejemplo que pude encontrar fue en LISP. Tómese el tiempo para leer el código, verá cuál es la idea. Las funciones de coincidencia ayudan a determinar si el texto es correcto sin saberlo exactamente.

Si puede lograr esto en C#, estoy apostando a que obtendrá una solución mucho más corta. (Se puede utilizar LINQ en la salida del EnumWindows? ;-)

#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <windows.h> 
#include "resource.h" 

#define ET_STARTUP 1 
#define ET_WINDOWOPEN 2 
#define ET_RUNEND 3 
#define ET_USEREVENT 4 
#define M_STAR 1 
#define M_QUESTION 2 

typedef struct WindowList_s 
{ 
int iScriptLine; 
HWND hwnd; 
    char *stName; 
char *stTitle; 
char *stClassName; 
char *stParentName; 
struct WindowList_s *wlParentPtr; 
char *stChildName; 
struct WindowList_s *wlChildPtr; 
int bWarned; 
struct WindowList_s *next; 
} WindowList_t; 


//////////////// 



extern long g_runids[]; 
extern WindowList_t *g_windowlist; 
extern EventList_t *g_eventlist; 
char stWTx[2000]; 
char stWCl[200]; 
char stPTx[2500]; 
char stPCl[200]; 
int bEventEntry=0; // means we're inside of processing an event. 
HWND LogWinParent; 

void FixIt(char *buf,unsigned int siz) 
{ 
int i,j,bump; 
int ir; 
char cr; 
char hex[10]; 
// keep special characters from screwing up script by 
// replacing w/ single-character wildcard 
    for (i=0;buf[i];i++) 
{ 
    cr='\0'; 
    ir=0; 
    bump=1; 
    switch(buf[i]) 
    { 
    case '\0':cr='0';break; 
    case '\\':cr='\\';break; 
    case '\n':cr='n';break; 
    case '\t':cr='t';break; 
    case '\a':cr='a';break; 
    case '\b':cr='b';break; 
    case '\f':cr='f';break; 
    case '\r':cr='r';break; 
    case M_STAR:cr='*';break; 
    case M_QUESTION:cr='*';break; 
    case '"':cr='"';break; 
    default: 
    if (buf[i]<32 || buf[i]>=127) 
    { 
    bump=2; 
    ir=buf[i]; 
    } 
    else 
    bump=0; 
    } 
    if (bump) 
    { 
    for (j=strlen(buf)+bump+1>=siz-1?siz-1:strlen(buf)+1; 
    j>i;j--) 
    buf[j+bump]=buf[j]; 
    buf[siz-1]='\0'; 
    if (cr) 
    { 
    buf[i++]='\\'; 
    buf[i]=cr; 
    } 
    if (ir) 
    { 
    sprintf(hex,"\\x%00H",ir); 
    memcpy(buf+i,hex,4); 
    i+=4; 
    } 
    } 
} 
} 
void LogWin(HWND hw) 
{ 
static long ParentNum=0,ChildNum=0; 

GetWindowText(hw,stWTx,sizeof(stWTx)-1); 
GetClassName(hw,stWCl,sizeof(stWCl)-1); 
FixIt(stWTx,sizeof(stWTx)); 
FixIt(stWCl,sizeof(stWCl)); 
if (GetParent(hw)==LogWinParent) 
{ 
    ChildNum++; 
    sprintf(stPTx,"  WindowObject %ld.%ld \"%s\" \"%s\" " 
    "Parent %ld",ParentNum,ChildNum,stWTx,stWCl,ParentNum); 
} 
else if (hw==LogWinParent) 
{ 
    ChildNum=0; 
    ParentNum++; 
    sprintf(stPTx," WindowObject %ld \"%s\" \"%s\"", 
    ParentNum,stWTx,stWCl); 
} 
else 
{ 
    ChildNum++; 
    sprintf(stPTx,"   WindowObject %ld.%ld \"%s\" \"%s\" GRANDCHILD", 
    ParentNum,ChildNum,stWTx,stWCl); 
} 
log_it(stPTx); 
} 

BOOL CALLBACK EnumChildProc4Logging( HWND hwnd,LPARAM lParam) 
{ 
    LogWin(hwnd); 
return 1; 
} 

void LogCurrentWindows(void) 
{ 
static int bEntry=0; 
static HWND hwCurrentFocus = 0; 

if (bEntry) 
    return; 
bEntry=1; 
    LogWinParent=GetForegroundWindow(); 
if (LogWinParent!=hwCurrentFocus) 
{ 
    hwCurrentFocus=LogWinParent; 
    LogWin(LogWinParent); 
    EnumChildWindows(LogWinParent,EnumChildProc4Logging,0); 
} 
bEntry=0; 
} 


/******************************************************************/ 
/* match() - parse wildcard strings .        */ 
/******************************************************************/ 
int match(char *pattern,char *str) 
{ 
    int patt,st; 

    patt=0; 
    st=0; 
    while(pattern[patt] || str[st]) /* go until both at '\0' */ 
    { 
     if ((!pattern[patt] || !str[st]) && pattern[patt]!=M_STAR) 
      return 0; /* fail if one at '\0' */ 
     if (pattern[patt]==M_STAR) 
     { 
      patt++; 
      while (str[st] && !match(pattern+patt,str+st)) 
      st++; 
     } 
     else if (pattern[patt]!=M_QUESTION && pattern[patt]!=str[st]) 
      return 0; /* Oh, No!! no match. */ 
     else 
     { 
      patt++; 
      st++; 
     } 
    } 
    return 1; /* successful match */ 
} 
void CheckWindowList(HWND hwnd) 
{ 
WindowList_t *wl; 
HWND hwndParent,hwndTarget; 
static char buf[600]; 
// Get the window's class and text 
GetWindowText(hwnd,stWTx,sizeof(stWTx)-1); 
GetClassName(hwnd,stWCl,sizeof(stWCl)-1); 
// Get the Parent Window's class and text 
hwndParent=GetParent(hwnd); 
GetWindowText(hwndParent,stPTx,sizeof(stPTx)-1); 
GetClassName(hwndParent,stPCl,sizeof(stPCl)-1); 

// search thru window objects, fill in 
// matching hwnds as appropriate 
for (wl=g_windowlist;wl;wl=wl->next) 
{ 
    hwndTarget=NULL; // separate variable enables 
       // warning on duplicate matches 
    if (wl->wlChildPtr==NULL && wl->wlParentPtr==NULL) 
    { // no parent/child requirements 
    if (match(wl->stClassName,stWCl) && 
    match(wl->stTitle,stWTx)) 
     hwndTarget=hwnd; 
    } 
    else if (wl->wlParentPtr) 
    { // parent requirement - if I (hwnd) match the 
    // wl's class/title and the parent (hwndParent) 
      // matches the wl's parentptr's class/title then 
    // set 'me' as the window that matches and has 
    // the proper parent requirement. 
    if (match(wl->stClassName,stWCl) && 
    match(wl->stTitle,stWTx) && 
    match(wl->wlParentPtr->stClassName,stPCl) && 
    match(wl->wlParentPtr->stTitle,stPTx)) 
     hwndTarget=hwnd; 
    } 
    else 
    { // child requirement - if I (hwnd) match the child 
    // requirement's stuff and the parent(hwndParent) 
    // matches the wl's stuff then set the parent 
    // as that wl's hwnd. 
    if (match(wl->stClassName,stPCl) && 
    match(wl->stTitle,stPTx) && 
    match(wl->wlChildPtr->stClassName,stWCl) && 
    match(wl->wlChildPtr->stTitle,stWTx)) 
     hwndTarget=hwndParent; 
    } 
    if (hwndTarget) 
    { 
    if (wl->hwnd && !wl->bWarned) // log a warning on dup windows 
    { 
    sprintf(buf,"267.EnumChildProc4Search.10 " 
    "Warning: more than one match for " 
    "windowobject %s exists",wl->stName); 
    log_it(buf); 
    wl->bWarned =1; 
    } 
    else 
    wl->hwnd=hwndTarget; 
    } 
} 
} 
BOOL CALLBACK EnumChildProc4Search( HWND hwnd,LPARAM lParam) 
{ 
    CheckWindowList(hwnd); 
    // return value of 1 means continue with rest of enumeration. 
return 1; 
} 

// to enumerate all... enumchild w/ NULL hwnd don't work???! 
BOOL CALLBACK EnumWindowProc4Search( HWND hwnd,LPARAM lParam) 
{ 
    CheckWindowList(hwnd); 
EnumChildWindows(hwnd,EnumChildProc4Search,0); 
return 1; 
} 

// Check thru all windows and runIDs to see if a run is done 
// or a window has opened. First emumerate the windows and running 
// programs and then see which events should be run. 
// this function must not run if blocked, 'once' countdown 
// has run out, or stopscript=1, or entry = 1 
void RunEvents(void) 
{ 
// Please keep in mind this program's error philosphoy when 
// extending it, namely, catch all possible script errors 
// when loading script, but do not display messageboxes for 
// even the most serious errors when doing events, because 
// the idea is to catch errors during development and avoid 
// errors at run time or in production!! 
static bEventEntry=0; 
WindowList_t *wl; 
EventList_t *el; 
ParmList_t *pl; 
char *st; 
int i; 
long lExitCode; 

// exit this routine if we shouldn't be here 
    if (g_iStopScript || bEventEntry) 
    return; 
bEventEntry=1; 
// clear all of the window handles in windowobject list 
for (wl=g_windowlist;wl;wl=wl->next) 
{ 
    wl->hwnd=NULL; 
    wl->bWarned = 0; 
} 

// enumerate all windows in the system; repopulate all of 
// the window handles in the windowobject list 
EnumWindows(EnumWindowProc4Search,0); 

// go thru event list, calling any events that must 
// be called; windows handles for any subsequent actions 
// will have been set by above code. Check for runs ending 
// to process runend events and search the windowobject list 
// to process windowopen events. 
for (el=g_eventlist;g_eventlist && el;el=el->next) 
{ 
    pl=MakeParms(el->stEventTypeSourceLine); 
    st=ParmValue(pl,2); // event name 
    // check for windowopen events 
    if (el->iEventType==ET_WINDOWOPEN) 
    { // search for their open windows!! 
    for (wl=g_windowlist;wl;wl=wl->next) 
    { 
    if (0==_stricmp(wl->stName,st) && wl->hwnd) 
    RunActions(el); 
    if (g_iStopScript) 
    return; // quit doing actions/events ASAP. } 
    } 
    } 
    if (el->iEventType==ET_RUNEND) 
    { 
    sscanf(st,"%ld",&i); 
    if (g_runids[i]!=-1 && g_runids[i]!=0) 
    { 
    GetExitCodeProcess((HANDLE)g_runids[i],&lExitCode); 
    if (lExitCode != STILL_ACTIVE) 
    { 
    RunActions(el); 
    g_runids[i]=0; 
    } 
    } 
    } 
    KillParms(pl); 
} 
bEventEntry=0; 
} 

void RunStartup(void) 
{ 
EventList_t *el; 

    if (bEventEntry) 
    return; 
bEventEntry=1; 
// check stopscript in case of endscript in startup event! 
for (el=g_eventlist;g_eventlist && el && !g_iStopScript;el=el->next) 
{ 
    if (el->iEventType==ET_STARTUP) 
    RunActions(el); 
} 
bEventEntry=0; 
} 
3

Creo que vas a tener que usar FindWindow, SendMessage, etc. Así es como WatiN maneja su cuadro de diálogo.

2

Creo que lo que busca es la interfaz COM IDocHostshowUI. Si leo la documentación correctamente y mis suposiciones son correctas, se llamará a la función ShowMessage cuando se invoque una alerta() o confirmación() en JavaScript.

No he hecho esto yo solo, así que solo estoy adivinando. Aquí están some examples de alguien que muestra un ejemplo de uso de esa interfaz (y muchas otras) en C#. WebBrowserSample2 suena como lo que estás buscando.