Respondido C# and Windows 7 conflict

  • sexta-feira, 2 de março de 2012 15:05
     
      Contém Código

    Hi,

    I am not sure if this must be in a Windows forum or here, as it cuts both ways..

    I have been using the following code with XP SP3 - 32Bit with no problems

    IEnumerable<dynamic> FindAllIE()
            {
                var t = Type.GetTypeFromProgID("Shell.Application");
                dynamic o = Activator.CreateInstance(t);
                try
                {
                    var ws = o.Windows();
                    for (int i = 0; i < ws.Count; i++)
                    {
                        var ie = ws.Item(i);
                        if (ie != null && System.IO.Path.GetFileName((string)ie.FullName) == "IEXPLORE.EXE")
                            yield return ie;
                    }
                }
                finally
                {
                    Marshal.FinalReleaseComObject(o);
                }
            }

    And it could find the IE window with no problems, BUT now after we took the next step to Windows 7 64Bit , The code above is not working....
    Could this be abstract windows problem or a code problem??? AND What shall I do to fix the problem???
    And this is the first problem...

    The second one is as follows ..

    I have used the following line of code to get the text inside a web page :

    IE_Window_Text = (string)ie.Document.body.innerText + Environment.NewLine;

    Now as the web page layout changed , and it is now using Frames inside the webpage, the line above is not able to catch the text which we need as it is now placed in a Frame, and it instead catches the text of the webpage without the contents of the Frames,,,

    How can I get the contents inside the frame to get my App up and running again??

    Thanks in advance for any help,, and sorry for bothering you all with such an old outdated problems...

Todas as Respostas

  • sexta-feira, 2 de março de 2012 15:51
    Moderador
     
     

    For the first problem I don't understand why you have all that code.  You're getting access to the shell and then enumerating through looking for open IE windows.  Why don't you just use Process.GetProcesses() to get all the running processes?  Once you find an instance of IE (note that each tab runs as a subprocess) then you can get the associated window. 

    I suspect your crash is caused by the fact that security permissions do not allow you to view information about processes (or windows) that you don't own.  Hence during your enumeration the call will fail.  Ironically I believe you can view the process name but not the full name.  Irrelevant you'll need to wrap a try-catch around each call to the process data and handle/ignore the security exception.

    The second question is unrelated so I can't help you there.

    Michael Taylor - 3/2/2012
    http://msmvps.com/blogs/p3net

  • sexta-feira, 2 de março de 2012 15:52
     
     

    For the first problem, put your code into debug and tell us what you see in var ie...

    For the second problem you are correct you have to first get the proper frame which is in a collection.  Question how are you getting the Document, show that code.  Reason: If you are doing it natively you will have to use MSHTML to get the frame collection, if you application is hosting the System.Window.Forms.Webbrowser then that's done a bit differently.


    JP Cowboy Coders Unite!

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:23
    • Não Sugerido como Resposta Martin Rasch segunda-feira, 12 de março de 2012 02:42
    •  
  • sexta-feira, 2 de março de 2012 16:11
     
      Contém Código

    Hi,
    So many thanks for you both for replies.

    As for the first problem , the var 'ie' gets null in each iteration ,, odd enough for me..
    And as for the second question I have my program runnig an an IE window open that has the webpage with FRAMEs in it.
    My code may be simple in a "stupid" way I think, as I am using the following line of code o get the text of the webpage that I found on the IE ::

    =======================================================
    Here I am supposed to get the IE Window
    =======================================================

    IEnumerable<dynamic> FindAllIE()
            {
                var t = Type.GetTypeFromProgID("Shell.Application");
                dynamic o = Activator.CreateInstance(t);
                try
                {
                    var ws = o.Windows();
                    for (int i = 0; i < ws.Count; i++)
                    {
                        var ie = ws.Item(i);
                        if (ie != null && System.IO.Path.GetFileName((string)ie.FullName) == "IEXPLORE.EXE")
                            yield return ie;
                    }
                }
                finally
                {
                    Marshal.FinalReleaseComObject(o);
                }
    }
    ===========================================================

    *****************************************************************
    and here I am getting the text in the webpage::
    *****************************************************************
    private void FindIEWindows()
            {
                foreach (var ie in FindAllIE())
                {
                   IE_Window_Text = (string)ie.Document.body.innerText + Environment.NewLine;
                }
            }
    *****************************************************************

    So, if we simply want to get the text inside One of the Frames inside the webpage,,, how can this be done??

    By the way,,

    In my Application I have tried to use the System.Window.Forms.Webbrowser and it failed due to security measures that made the

    server refuse the connection to it.

    Hope I am clear enough and so many thanks for replies...


    • Editado Not_An_Expert sexta-feira, 2 de março de 2012 16:31
    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:24
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:18
    • Sugerido como Resposta Martin Rasch segunda-feira, 12 de março de 2012 02:42
    • Não Sugerido como Resposta MarcDModerator segunda-feira, 12 de março de 2012 02:44
    •  
  • sexta-feira, 2 de março de 2012 21:36
     
     

    So I think I am not clear enough as I thought,.. Sorrrrry.

    Please let me know what portion of code exactly should I show??

    And bare with me as I re-ask the same question >>

    How can we get the contents of a SPECIFIC FRAME inside a webpage opened using IE ,,, using a c# application??

    Thanks again for any help... and again sorry for bothering you all.

    • Editado Not_An_Expert sexta-feira, 2 de março de 2012 21:45
    •  
  • sábado, 3 de março de 2012 03:16
     
     
    You can't do anything if you don't have addressibility to the webbrowser.  I am unfamilair with your approach but did see it out there on the internet.  If you host a browser in your own application that's a different story.

    JP Cowboy Coders Unite!

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:24
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:18
    •  
  • sábado, 3 de março de 2012 03:21
     
     Respondido
    namespace IELibrary
    {
      using System;
      using System.Linq;

      public static class ShellWindowWrapper
      {
        public static mshtml.HTMLDocument GetHTMLDocumentFromHwnd(IntPtr hwnd)
        {
          if (hwnd == IntPtr.Zero)
            return null;

          var wbSearched = new SHDocVw.ShellWindowsClass()
            .Cast<SHDocVw.WebBrowser>()
            .Where(wb => wb.HWND == hwnd.ToInt32())
            .SingleOrDefault();

          if (null == wbSearched)
            return null;

          if (!(wbSearched.Document is mshtml.HTMLDocument))
            return null;

          return (mshtml.HTMLDocument)wbSearched.Document;
        }
      }
    }

    JP Cowboy Coders Unite!

  • sábado, 3 de março de 2012 03:23
     
     
    The code above takes a HWND point to instanciate an IE based Webbrowser.  It returns an HTML document that will allow you to get to the proper frame. But before you can do that you have to get all PROCESSes on the system, and find the HWND to IE instances.  Do that first and then I'll show you how to traverse the HTMLDOCUMENT to find the frame.

    JP Cowboy Coders Unite!

  • sábado, 3 de março de 2012 09:11
     
      Contém Código

    Thanks Mr. Javaman II,,, and sorry for being late,,, had a long power cut.

    As for getting all PROCESSes on the system I think it may be something like this:: correct me if not, please::

    foreach(Process p in Process.GetProcesses()) 
    { 
          Console.WriteLine(p.ProcessName); 
    } 
    Console.ReadKey();

    Or maybe store them in an array :: 

    Process[] theProcesses = Process.GetProcesses();

    ------------

    As for the second section , I think I must admitt it again, as I am Not_An_Expert,,, it is hard for me to figure it out,, The only thing I know is something like the following:    "Shame on me!!!!"

    int myHandle = this.Handle.ToInt32();

    BUT I have came on some articles that may be related, but I got lost in between , below are the links:

    http://stackoverflow.com/questions/3924812/how-can-i-select-a-ie-tab-from-its-handle

    http://www.codeproject.com/Articles/2052/Capturing-the-Running-IE-Instances-in-C

    http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/16bf995d-6bab-40b5-a7ae-c844b7f0d51f

    http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/59b7c865-ccbe-463c-a0b8-e8e55b9bed2e/

    http://stackoverflow.com/questions/4768689/c-sharp-get-path-filename-by-handle-hwnd-32-and-64bit

    http://stackoverflow.com/questions/1982699/get-hwnd-of-containing-ie-window-from-toolbar

    http://msdn.microsoft.com/en-us/library/aa752126(VS.85).aspx

    Please point me to right direction and so many thanks, you have been so helpfull so far

  • sábado, 3 de março de 2012 20:32
     
      Contém Código

    The following code is used to get path/filename by handle, is it what we are talking about and how should we make use of it in our problem,,, if it is what we need ?

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowThreadProcessId(IntPtr handle, out uint processId);
        public static string GetProcessPath(IntPtr hwnd)
        {
            uint pid = 0;
            GetWindowThreadProcessId(hwnd, out pid);
            Process proc = Process.GetProcessById((int)pid);
            return proc.MainModule.FileName.ToString();
        }

    Thanks for help...
  • sábado, 3 de março de 2012 21:30
    Moderador
     
     Respondido

    Why do you need the process given a handle.  The Process.GetProcesses() method gives you all the running processes.  From there you have access to the filename and the main window (if any) - barring any security issues which you'll have to handle anyway.  I don't understand why you're trying to make this soo much harder than it needs to be.  You don't need to P/Invoke to get the process filename.

    Michael Taylor - 3/3/2012
    http://msmvps.com/blogs/p3net

  • sábado, 3 de março de 2012 21:38
     
     

    I got lost in between articles untill I lost track totally.

    All I need is a way to copy the text inside a FRAME in a webpage... but i seems to be so much harder than I thought.

    I have tried every thing I knew already but obviously it failed, I can't retrive the actual contents of the FRAME..

    Any help??

    Thanks for response,

  • domingo, 4 de março de 2012 14:57
     
     
    So, it is really that hard. I figured it would be so ..
    Should I look for another way to copy the contents of a FRAME in the webpage, or this is not do-able at all??!!
    Thanks for all the help..
  • domingo, 4 de março de 2012 21:26
     
     

    .

  • domingo, 4 de março de 2012 21:46
     
      Contém Código

    hi Not_An_Expert,

    I think the problem is it is somehow casesensitive just make it in lower case this row of code (the string: iexplore.exe):

    IEnumerable<dynamic> FindAllIE()
            {
                var t = Type.GetTypeFromProgID("Shell.Application");
                dynamic o = Activator.CreateInstance(t);
    try
                {
                    var ws = o.Windows();
    for (int i = 0; i < ws.Count; i++)
                    {
                        var ie = ws.Item(i);
    if (ie != null && System.IO.Path.GetFileName((string)ie.FullName) == "iexplore.exe") //write iexplore.exe in lower case

    yieldreturn ie;
                    }
                }
    finally
                {
                    Marshal.FinalReleaseComObject(o);
                }
    }

                                                                                         

    this works to me...

    to get the frame element that's more an Html & JavaScript question... reference to those links:

    http://roneiv.wordpress.com/2008/01/18/get-the-content-of-an-iframe-in-javascript-crossbrowser-solution-for-both-ie-and-firefox/

    http://stackoverflow.com/questions/2026743/accessing-frames-rendered-in-webbrowser-control-in-c-net

    Hope it helps , if not reply :)


    If some code doesn't work, don't worry help is on the way.. don't forget to mark your thread as solved when done...

  • domingo, 4 de março de 2012 21:49
    Moderador
     
     Respondido

    Filenames are not case sensitive in Windows.  To properly compare filenames use String.Compare(file1, file2, StringComparison.OrdinalIgnoreCase) == 0  Technically you could use case insensitive but ordinal is preferable.

    Michael Taylor - 3/4/2012
    http://msmvps.com/blogs/p3net

  • domingo, 4 de março de 2012 21:59
     
     

    Hi.

    Thanks for reply Muli, But I have tried every thing you might imagine including upper and lower case with no success.

    Any way thanks for the suggestion.

    As for the links I will look them up now.

    Thanks again.

  • domingo, 4 de março de 2012 22:02
     
     

    Hi, CoolDadTx,

    I just wanted to say it is so Coooool and a great honor to see your name in my thread 3 times .

    This is enough for me to walk tall in the crouds.

    Thanks for your help so far.

  • terça-feira, 6 de março de 2012 14:23
     
     Respondido Contém Código

    This code works and shows you how to get to the frames collection...

    public void FindAllIE(){
        var t = Type.GetTypeFromProgID("Shell.Application");  
        dynamic o = Activator.CreateInstance(t);
        try {   
            var ws = o.Windows();
            for (int i = 0; i < ws.Count; i++){  
                var ie = ws.Item(i);
                if (ie != null && System.IO.Path.GetFileName((string)ie.FullName) == "iexplore.exe");
                var doc2 = (mshtml.IHTMLDocument2)ie.document;
                mshtml.IHTMLFramesCollection2 frames2 = doc2.frames;
                for (int j = 0; j < frames2.length;j++ )
                {
                    var thing = frames2.item(i);                      
    
                }
                }
            }catch(Exception iox){
                        
            }           
            finally{                
                Marshal.FinalReleaseComObject(o);            
            }
    }


    JP Cowboy Coders Unite!

  • terça-feira, 6 de março de 2012 14:25
     
     Respondido

    Note you will have to add a reference to MSHTML via the COM classes to your project.   I like your solution becuase it totally bypasses having to work with hwnd pointers.   The only thing I don't care for in this style of programming above is that everything that comes back is a COM_OBJECT... Therefore you have to infer what the type is just to grab a method or property or two...  I did this first by attempting to do a GetType().UnderlyingSystemType.Name  which told me it was a COM_OBJECT.  I then was able to luckily guess that the object type of IE had a Document property which based on past experience was a MSHTML.IHTMLDOCUMENT type which could be case into MSHTML.ITHTMLDOCUMENT2 object.

    From there it is Welcome to MSHTML world!

    Good Luck!

    JP Cowboy Coders Unite!



  • quarta-feira, 7 de março de 2012 15:33
     
     

    Hi Mr. GREAT JavaMan II

    Huge Thanks for the reply and sorry for being late to respond..

    I am now going to try the way you coded and I have a feeling it is gonna be a huge WOW it works.

    I am not really so familiar with this type of programming (COM and MSHTML ) but I will do some readings over these topics and then try to use the code you provided.

    I will get back to this post and mark as an answer as soon as I become able to copy the contents of the frame (even though I can't see how right now   :)    )

    Thanks very much again and I will be back soon.

  • quarta-feira, 7 de março de 2012 16:39
     
     
    Np dude glad to help, vote me some points ok?

    JP Cowboy Coders Unite!

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:25
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:19
    •  
  • quarta-feira, 7 de março de 2012 20:14
     
     

    OK,, of course OK...

    Hope I can work it out ... please wish me luck !! and some smartness toooooo !!!! :)

  • quarta-feira, 7 de março de 2012 21:33
     
      Contém Código

    I have used the following line of code to get the text inside a web page :


    IE_Window_Text = (string)ie.Document.body.innerText + Environment.NewLine;

    Now as the web page layout changed , and it is now using Frames inside the webpage, the line above is not able to catch the text which we need as it is now placed in a Frame, and it instead catches the text of the webpage without the contents of the Frames,,,

    How can I get the contents inside the frame to get my App up and running again??

    Your "IE_Window_Text" variable leads me to believe you are just wanting to get the window title for each IE window? Am I correct?

    Aaron Chapman

  • quarta-feira, 7 de março de 2012 22:37
     
     

    Hi Mr Aaron Chapman,

    Thanks for the reply.

    Indeed the name "IE_Window_Text" is just a "maybe not the best" name for a variable, but it does the job, right :)

    What I want really is getting the text ((ALL THE TEXTs )) that are shown on the webpage opened in the current IE window... even the text in the FRAMEs shown on that page.

    I have been trying to get this done for a while with no luck , until Mr.Javaman showed up with some usefull suggestions that might help,, even though I am not able to use them successfully until the moment.

    Anyways, thanks for the reply again and any help is welcome.... :)

  • quarta-feira, 7 de março de 2012 22:46
     
     

    Windows 7 intel 64-Bit is the currently running OS with VS2010 on it....

    XP SP3 with VS2008 was the platform used to develop the old school app before we upgraded to W7

    Now, to be precise, in the web page shown there are 3 FRAMES where on of them (the one in the center of the page) shows some textual data,,,,and those TEXTs are the goal... I need to copy them,,, apply the REGEX I have previously used on them,,, EXTRACT some details and print them finally...

    Hope this makes things clear enough, and sorry for any confusion caused

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:23
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:17
    •  
  • quarta-feira, 7 de março de 2012 22:46
     
     Resposta Proposta Contém Código

    So what you have to do is go through each of the frames and pull out each frame's MSHTML.Document2.  Contained within that is a HTMLELEMENT collection or as Aaron mentioned the entire body which is the same thing as the HTML tag Body...  You can get all of the HTML markup via the Body element.  However, if you know an element name or ID you can get the value of the HTMLELEMENT directly  like this:

    var o = document.getElementById("msdn");
    var sContentAttr = o.getAttribute("href");
    

    Which would get the element named MSDN which is a link or some other element that has an HREF attribute.  (Like and IFRAME or even a FRAME).  sContentAttr would then hold the string of the HREF like http://www.msdn.com

    JP Cowboy Coders Unite!

    • Sugerido como Resposta Mr. Javaman II segunda-feira, 12 de março de 2012 03:16
    •  
  • quarta-feira, 7 de março de 2012 22:51
     
     

    WOOOOW Mr.Javaman II

    A real expert you are...

    I am going to try it right away, I will be right back As Soon As I Do it Right..

    Thanks for all the help man

    Appreciat it...   :)

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:26
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:19
    •  
  • quinta-feira, 8 de março de 2012 00:04
     
     

    Pretty tuff stuff for a new guy diving into MSHTML and IE web browser internals but you're doing a good job.


    JP Cowboy Coders Unite!

    • Sugerido como Resposta Martin Rasch sexta-feira, 9 de março de 2012 22:23
    • Não Sugerido como Resposta MarcDModerator sábado, 10 de março de 2012 18:17
    •  
  • sexta-feira, 9 de março de 2012 22:29
     
     

    Windows 7 intel 64-Bit is the currently running OS with VS2010 on it....

    XP SP3 with VS2008 was the platform used to develop the old school app before we upgraded to W7

    Now, to be precise, in the web page shown there are 3 FRAMES where on of them (the one in the center of the page) shows some textual data,,,,and those TEXTs are the goal... I need to copy them,,, apply the REGEX I have previously used on them,,, EXTRACT some details and print them finally...

    Hope this makes things clear enough, and sorry for any confusion caused


    Yes it works for me :)

    Martin Rasch

  • segunda-feira, 12 de março de 2012 01:41
    Moderador
     
     

    Hi,

    Any update of this problem?   Not_An_Expert, if the replies can solve your questions here, please help to mark them as the answers to benefit more community members.

    Good day, all!

    Thanks


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us

    • Sugerido como Resposta Martin Rasch segunda-feira, 12 de março de 2012 02:49
    • Não Sugerido como Resposta MarcDModerator segunda-feira, 12 de março de 2012 16:43
    •  
  • sábado, 14 de abril de 2012 17:07
     
     

    Hi,

    So Late Yeah,, So Sorrrrry

    Mr. Great Javaman II has been so helpful and the solutions he came up with are a HUGE success... WOOOW.

    So many thanks Mr. Javaman II..

    By the way::

    I voted you some point dude... :)