2010-12-16 220 views
6

J'ai fait des recherches depuis un moment et je suis dans une impasse. Je fais de l'automatisation IE. En C# /. NET, comment puis-je rechercher et consommer une alerte javascript() ou confirmer() afin que je puisse faire des choses comme saisir son texte et cliquer sur les boutons OK \ Annuler?Sonde C# et capture Javascript Alert() et Confirmer()

Mise à jour:

Je dois réitérer: Je dois être en mesure de tirer et de vérifier le texte d'une alerte() ou confirmer(), ainsi que l'envoyer un OK ou Annuler clic. Un exemple d'un tel test serait de s'assurer que, lorsque je clique sur supprimer, la confirmation() ne dit pas "Es-tu sûr que tu aimerais aller au Mexique?" ou toute autre chose sauf le bon message. Permettez-moi de réitérer: Pour les besoins de ce test, j'ai zéro contrôle sur la source du site en question.

Enfin, j'utilise SHDocVw.InternetExplorer.

+0

Utilisez-vous IE ou créez-vous une application personnalisée avec un contrôle WebBrowser? – zsalzbank

+0

Par "sonde pour" manipulez-vous le pré-navigateur source ou seulement après son affichage? Êtes-vous au service de vous-même? Est-il possible d'avoir ces choses utiliser des boîtes de dialogue modales au lieu de boîtes d'alerte et le gérer en javascript? – jcolebrand

+0

Possible dupe de http://stackoverflow.com/questions/77659/blocking-dialogs-in-net-webbrowser-control – Zach

Répondre

1

FindWindow - vous permettra de vous rapprocher; vous voulez une poignée de fenêtre, mais vous ne saurez pas comment le trouver.

Mieux vaut utiliser EnumWindows.Voici un exemple d'une routine que vous pouvez exécuter toutes les secondes ou deux qui vous donnera une tonne d'informations sur chaque fenêtre sur le système, alors vous pouvez l'analyser. Vous pouvez vérifier le type de fenêtre, le texte qui s'y trouve, obtenir les boutons et envoyer un clic sur le bon. Cela vous permettra de faire tout ce que vous espérez pouvoir faire.

Pour obtenir le texte, vous envoyez un wm_gettext et pour le bouton, vous pouvez vous en sortir avec wm_click.

Désolé pour le C. le prochain meilleur exemple que j'ai pu trouver était dans LISP. Prenez le temps de lire le code, vous verrez quelle est l'idée. Les fonctions Correspondance permettent de déterminer si le texte est correct sans le savoir exactement.

Si vous parvenez à faire cela en C# je parie que vous aurez une solution beaucoup plus courte. (Vous pouvez utiliser LINQ sur la sortie de 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

Je pense que vous allez devoir utiliser FindWindow, SendMessage, etc. C'est ainsi que WatiN gère son dialogue.

2

Je pense que ce que vous cherchez est l'interface IDocHostshowUI COM. Si je lis la documentation correctement et mes hypothèses sont correctes ShowMessage la fonction sera appelée quand un alert() ou un confirm() est appelé en JavaScript.

Je ne l'ai pas fait moi-même alors je ne fais que deviner. Voici some examples de quelqu'un montrant un exemple d'utilisation de cette interface (et beaucoup d'autres) en C#. WebBrowserSample2 ressemble à ce que vous cherchez.