0

I am using flashwindowex winapi in my c# application to flash the IE window in icon tray. The code is running fine when I am adding a breakpoint in the code and running in debug. But the same code is not working when the breakpoint is removed.

It's a console application and I am using few windows api to find the handle of created IE process by its name. The handle of process is further passed to FlashWindowEX WINAPI for flashing the process.

public static System.IntPtr hnd = IntPtr.Zero;
public delegate bool CallBackPtr(IntPtr hwnd, int lParam);
public static CallBackPtr callBackPtr;
public const UInt32 FLASH_T = 3;
public const UInt32 FLASH_S = 12;

static void Main(string[] args)
{
    try
    {
        OrigCode();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    Console.ReadLine();
}

public static void OrigCode()
{
    string strPzszPath = string.Empty;
    string strCommandLine = string.Empty;
    string strpath1 = "http://localhost/Till/Default.aspx";

    strPzszPath = string.Concat(strPzszPath, strpath1);
    strPzszPath = string.Concat(strPzszPath, "?TSCashierID=JILL&TSBalPeriod=2&TSBalDate=2015-06-02");
    strCommandLine = strPzszPath;
    Process procRequested = new Process();

    ////Create the process in minimised mode by default
    procRequested.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
    procRequested.StartInfo.UseShellExecute = false;

    ////Get the file name in which process is required to be started
    procRequested.StartInfo.FileName = @"C:\Program Files\Internet Explorer\IExplore.exe";

    procRequested.StartInfo.Arguments = strCommandLine;

    ////Start the process, process should be created in minimised mode
    procRequested.Start();

    callBackPtr = new CallBackPtr(SetFocusEnum);
    int intResult = EnumWindows(callBackPtr, 0);

    FLASHWINFO fi = new FLASHWINFO();
    fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi));
    fi.hwnd = hnd;
    fi.dwFlags = FLASH_T | FLASH_S;
    fi.ucount = UInt32.MaxValue;
    fi.dwTimeout = 0;
    FlashWindowEx(ref fi);
}

private static bool SetFocusEnum(IntPtr hWnd, int intLParam)
{
    int intSize = GetWindowTextLength(hWnd);
    try
    {

        if (intLParam == 0) //Process created so check by name
        {
            if (intSize++ > 0)
            {

                //Capture the running window name
                StringBuilder sbWindowName = new StringBuilder(intSize);
                GetWindowText(hWnd, sbWindowName, intSize);
                //Capture the running process with the window name
                if (sbWindowName.ToString().Contains("My Web Application Title"))
                {
                //Capture the handle which will be used to set the focus
                hnd = hWnd;
                }
            }
        }
    }
    catch (Exception ex)
    {
    }
    finally
    {
    }
    return true;
}

Below are the winapi functions I used:

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int EnumWindows(CallBackPtr callPtr, int intProc);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetWindowTextLength(IntPtr intptrHwnd);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetWindowText(IntPtr intptrHwnd, StringBuilder strText, int intMaxCount);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FlashWindowEx(ref FLASHWINFO pwfi);

[StructLayout(LayoutKind.Sequential)]
private struct FLASHWINFO
{
    public UInt32 cbSize;
    public IntPtr hwnd;
    public UInt32 dwFlags;
    public UInt32 ucount;
    public UInt32 dwTimeout;
}
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • Please show your code, we cannot help you if we have don't have anything to go on. A description of what is, and what is not happening doesn't help much without code. – Visual Vincent Aug 07 '16 at 22:00
  • Hi I am posting the query through my cell phone and code I can share tomorrow but if I talk about the approach ,I am using the flashwindoex in the same way as shown in this link http://stackoverflow.com/questions/4889181/get-user-attention-without-stealing-focus . To get the value of handle that window I am using enumwindows winapi and that value I am passing to flashwindowex method. – bhupesh joshi Aug 07 '16 at 22:07
  • I'm currently on my phone too, so I cannot do much without your particular code (I would have hoped to verify that you'd used everything correctly). I will make a test when I get access to a computer. – Visual Vincent Aug 07 '16 at 22:12
  • Thanx in advance. I am posting the code block connecting my system to network. :) – bhupesh joshi Aug 07 '16 at 22:13
  • Oh there's no rush (unless you feel there is). Take your time. – Visual Vincent Aug 07 '16 at 22:16
  • Hi I have just posted code as a guest.. Please have a look if you can help – bhupesh joshi Aug 07 '16 at 22:56
  • You should just have edited your question instead and included it there instead. You posted an answer but it doesn't count as an answer. – Visual Vincent Aug 07 '16 at 22:59
  • I will look at it in a bit, but I cannot test it until tomorrow. – Visual Vincent Aug 07 '16 at 23:06
  • Ok thanx it's really important for me to resolve this issue by tomorrow. I will also try again – bhupesh joshi Aug 07 '16 at 23:08
  • It works when you place a breakpoint because when you resume your application the page has finished loading and the title is displayed as the window's text. You simply have to take the page's load time into account, which will be tricky, but I'll see if I can come up with something tomorrow. – Visual Vincent Aug 07 '16 at 23:17
  • May be you are right but always the page gets loaded before the call of enumwindows winapi. Even the code is finding its handle successfully (used console. Writeline for this ). The issue is really strange. – bhupesh joshi Aug 07 '16 at 23:20
  • Hmmh, does seem strange. I'll test the code more thoroughly tomorrow. Until then... – Visual Vincent Aug 07 '16 at 23:21
  • Ok thanx dude..!! I will also try again tomorrow.. – bhupesh joshi Aug 07 '16 at 23:24

1 Answers1

0

Like I stated in my comment, the issue here is that it takes too long to load the page for the window's text to be changed by the time you execute the EnumWindows() function. The code you use is executed almost immediatelly, whilst opening the process and loading the page takes a few hundred milliseconds to a few seconds. Adding a delay is the simplest workaround that will solve your problem.

Here's what I did:

procRequested.Start();
procRequested.WaitForInputIdle();

System.Threading.Thread.Sleep(750); //Wait for approximately 750 ms.

It is normally adviced against using Thread.Sleep(), but since you're in a Console Application it doesn't make much difference other than blocking user input the little time that it runs.

You may also have noticed that I added a call to Process.WaitForInputIdle(), this is to let your application wait until the process has finished its startup procedure (for example loading resources, or whatever Windows does with a process before the application actually starts) so that we know when we can expect the window to actually show.

If you feel or experience that the 750 ms delay is not enough sometimes, try raising it to 1250 or something like that.


EDIT:

Since (as you say) a focused window won't flash, you can store a window handle to the previously focused window, and use that to focus the window again right before you let the FlashWindowEx code execute.

For this you will need two WinAPI calls:

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

Then you just use those two functions here:

IntPtr focusedhWnd = GetForegroundWindow(); //Get the window handle to the currently focused window.

procRequested.Start();
procRequested.WaitForInputIdle();

System.Threading.Thread.Sleep(750); //Wait for approximately 750 ms.

callBackPtr = new CallBackPtr(SetFocusEnum);
int intResult = EnumWindows(callBackPtr, 0);

SetForegroundWindow(focusedhWnd); //Focus the previously focused window again.

FLASHWINFO fi = new FLASHWINFO();
fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi));
fi.hwnd = hnd;
fi.dwFlags = FLASH_T | FLASH_S;
fi.ucount = UInt32.MaxValue;
fi.dwTimeout = 0;
FlashWindowEx(ref fi);
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • Thanx the issue was same what you said but it is with few cases only when the process is taking time. But the point which I was mentioning earlier regarding running of code while break point insertion. It was due to the fact that while debug mode the focus stays on visual studio so when application calls the flash window ex , the launched application blinks. But while running straight away through exe the focus goes to the minimised application in tray so it doesn't blink. Now the new issue is I need to create a process with no focus on that in window tray so that when this flash window gets c – bhupesh joshi Aug 08 '16 at 12:58
  • Thanx @visual Vincent I am trying as well. – bhupesh joshi Aug 08 '16 at 13:27
  • @bhupeshjoshi : Got it, see my update. And if it solved your problem, please mark my post as the accepted answer by pressing the check mark on its left. – Visual Vincent Aug 08 '16 at 13:56
  • this is just the poc I am doing with console window. In the real scenario the same code has to be implemented in a DLL file. This DLL will then be consumed by a wcf callback service at server through a slnet channel. Will that getconsolewindow method work in that case ? – bhupesh joshi Aug 08 '16 at 14:00
  • @bhupeshjoshi : No, give me a few more minutes then. :) – Visual Vincent Aug 08 '16 at 14:03
  • @bhupeshjoshi : Fixed! – Visual Vincent Aug 08 '16 at 14:12
  • No sir you told me to wait for some other testing. Should I go for this solution only ? – bhupesh joshi Aug 08 '16 at 14:16
  • I am testing the code block.. Gimme few minutes will notify you once done – bhupesh joshi Aug 08 '16 at 14:18
  • @bhupeshjoshi : Take your time, I'm in no rush. But what I meant with "Fixed!" was that I fixed my answer, not that you should mark my post as the accepted answer (if that's what you thought). -- You mark a post as accepted once you find that it solved your problem. – Visual Vincent Aug 08 '16 at 14:20
  • That "other testing" that I mentioned was the testing I was going to do today, which I already have done now and shared with you as an answer. – Visual Vincent Aug 08 '16 at 14:22
  • Thanx visual Vincent it is working fine but the issue is coming intermittently. If I will explain you entire scenario then this problem is just a part of it. There is this approach I was trying but I don't think I can move it further as it is not stable. The issue was to create a application process in minimised mode and the application aspx start page has window.open code written which is not allowing it to open in minimised no active mode. This is the main issue. So just to test I used window.blur in web app only but I just came to know I can't change web app code. I need to open it in min – bhupesh joshi Aug 09 '16 at 09:12
  • I need to open the web app with window.open in minimize mode through my DLL code only. Then based on certain conditions from server caller component I need to bring it in focus and foreground. Please if you can help on this elaborating the same code above as I have used same process.start method in DLL code. – bhupesh joshi Aug 09 '16 at 09:16
  • @bhupeshjoshi : I find it hard to understand what you mean you want to achieve, and I'm also not very good at ASP.NET (my area of expertise is primarily WinForms). I don't know if it's possible to open a window in a specific way using `Window.Open()` (Javascript?), I think it just tells the web browser that it wants a new window and then the browser does the rest. – Visual Vincent Aug 09 '16 at 10:24
  • Hi @visual Vincent thanx for your last answer it really helped and code is running fine but there are two machine where the code is only running once I set the value of dwtimeout flag (flashwinfo) as greater than 0. But on other it is running fine with 0 value. If you can help me on this. – bhupesh joshi Aug 17 '16 at 09:29
  • @bhupesjoshi : Don't know, seems like a hard problem to diagnose. What OS does these machines run? – Visual Vincent Aug 17 '16 at 09:36
  • Windows 7 enterprise service pack 1 is dere on them with XP theme – bhupesh joshi Aug 17 '16 at 09:49
  • @bhupeshjoshi : If it works every time with the `dwTimeout` field set, then you should always do so to avoid it not working. The documentation says that if it's `0` it will be set to the default caret blink rate. If you reference `System.Windows.Forms.dll` then you can use [**`SystemInformation.CaretBlinkTime`**](https://msdn.microsoft.com/en-us/library/system.windows.forms.systeminformation.caretblinktime(v=vs.110).aspx) to get the blink rate. – Visual Vincent Aug 20 '16 at 09:09