Solved

How to set the position and size for firefox using CreateProcess and MoveWindow (Visual Studio 2008, MFC)

Posted on 2009-04-04
11
983 Views
Last Modified: 2013-12-07
Hello,

I want to start firefox and set the size of the window to a specific value. Say 800x600 for tesing a homepage.

I wrote a small sample that works find with notepad.exe but not firefox.exe.

I used FindWindow the compare processID and it does not match.

Does anyone have an idea?

Stefan
HWND m_Window;
 

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

{

	DWORD		processID;

	::GetWindowThreadProcessId(hwnd, &processID);
 

	if (processID == lParam)

	{

		m_Window = hwnd;

		return FALSE;

	}
 

	return TRUE;

}
 

void CRunResDlg::OnBnClickedButtonfirefox()

{

	PROCESS_INFORMATION sProcessInfo;

	STARTUPINFO                  sStartupInfo;
 

	ZeroMemory(&sStartupInfo,sizeof(STARTUPINFO));

	ZeroMemory(&sProcessInfo,sizeof(PROCESS_INFORMATION));
 

	sStartupInfo.cb = sizeof( STARTUPINFO);
 

//	char szCommandLine[260] = {"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"};

	char szCommandLine[260] = {"C:\\windows\\notepad.exe"};
 

	CreateProcess(NULL, szCommandLine, 0, 0, 0, CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS, 0, 0, &sStartupInfo, &sProcessInfo);
 

	DWORD dw = WaitForInputIdle((HANDLE)sProcessInfo.hProcess, 10000);
 

	Sleep(2000);
 

	m_Window = 0;

	EnumWindows(EnumWindowsProc, sProcessInfo.dwProcessId);
 

	if (m_Window != 0)

	{

		::MoveWindow(m_Window, 100, 100, 800, 600, TRUE);

	}

}

Open in new window

0
Comment
Question by:StefanKittel
  • 8
  • 3
11 Comments
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24069830
Maybe here?

now
     m_Window = 0;
     EnumWindows(EnumWindowsProc, sProcessInfo.dwProcessId);

seems to be true
      m_Window = EnumWindows(EnumWindowsProc, sProcessInfo.dwProcessId);
 
;-)
0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24069845
Sorry. It's global variable.
But it must be NOT null before GetWindowThreadProcessId call!
Try this:
    m_Window = 1;
    EnumWindows(EnumWindowsProc, sProcessInfo.dwProcessId);

MSDN says:


Syntax
DWORD GetWindowThreadProcessId(      
    HWND hWnd,
    LPDWORD lpdwProcessId
);

Parameters

hWnd [in] Handle to the window.  
lpdwProcessId [out] Pointer to a variable that receives the process identifier. If this  parameter is not NULL, GetWindowThreadProcessId copies the identifier of  the process to the variable; otherwise, it does not.
0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24069854
Oops. Not m_Window, but processID  :-[
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

{

        DWORD           processID;
 

        processID = 1; //Here not null
 

        ::GetWindowThreadProcessId(hwnd, &processID);

 

        if (processID == lParam)

        {

                m_Window = hwnd;

                return FALSE;

        }

 

        return TRUE;

}

Open in new window

0
 
LVL 4

Author Comment

by:StefanKittel
ID: 24071116
Hello Mechanic_Kharkov,

my code is working fine the way it is.
What MS says means this "::GetWindowThreadProcessId(hwnd, NULL)"

My code works fine with notepad.exe but not with firefox.exe. It seems like the main process from ff is not connected to the window. So I need to find the other processes startet by the main process and then search for the window.

Stefan
0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24071200
I checked this version. You are wrong in this. FF really works with correct PID attached to it's main window. I used "Spy & Capture utility" to determine this condition is true.
And MS says that
lpdwProcessId [out] Pointer to a variable that receives the process identifier. If this  parameter is not NULL, GetWindowThreadProcessId copies the identifier of  the process to the variable; otherwise, it does not.
Are they wrong?
Look into Your code, and You will see that Your lpdwProcessId is NOT DEFINED before call to this function. And why it works with notepad - it's possible if data in this variable is not null. We can not guarantee anything, if we don't initialize variable. Just try to set it not null before call, and try again. Is it so hard to implement?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 4

Author Comment

by:StefanKittel
ID: 24071268
Hello,

I found out. During tesing a had a window with ff open to google.
When starting ff a second time, it attaches the new window to the first process. So I could not find it.
Thats the trick.

But I'm not sure how to deal with it.

Stefan
0
 
LVL 5

Accepted Solution

by:
Mechanic_Kharkov earned 500 total points
ID: 24071277
Found the same thing. Many windows, but the only process. :-)
I even port it to Delphi to test.

program SizeFFWindow1;

{$APPTYPE Console}
 

uses

	SysUtils,

	Windows;
 

var m_Window: HWND;
 

function EnumWindowsProc(Wnd:HWND; lParam:LPARAM): boolean;

var processID: DWORD;

begin

	Result := true;

	processID := 1;

	GetWindowThreadProcessId(Wnd, @processID);
 

	writeln('PID = '+Inttohex(processID,8)+'  Wnd = '+Inttohex(Wnd,8)+

	'   Look for '+Inttohex(lParam,8));
 

	if processId = lParam then

		begin

			m_Window := Wnd;

			Result := false;

			writeln('------ Matched -----');

		end;

end;
 

var

				sProcessInfo: PROCESS_INFORMATION;

				sStartupInfo: STARTUPINFO;

				szCommandLine: PChar;

				dw: DWORD;

begin

			//start ff

				ZeroMemory(@sStartupInfo,sizeof(STARTUPINFO));

				ZeroMemory(@sProcessInfo,sizeof(PROCESS_INFORMATION));
 

				sStartupInfo.cb := sizeof( STARTUPINFO);
 

				szCommandLine := PChar('"H:\Program Files\Mozilla Firefox\firefox.exe"');

				//char szCommandLine[260] = {"C:\\windows\\notepad.exe"};
 

				CreateProcess(nil, szCommandLine, nil, nil, false, {CREATE_NO_WINDOW or}

					NORMAL_PRIORITY_CLASS, 0, 0, sStartupInfo, sProcessInfo);
 

				dw := WaitForInputIdle(sProcessInfo.hProcess, 10000);
 

				Sleep(2000);
 

				m_Window := 0;

				EnumWindows(@EnumWindowsProc, sProcessInfo.dwProcessId);
 

				if (m_Window <> 0) then

					MoveWindow(m_Window, 100, 100, 800, 600, TRUE);
 

				writeln('Press Enter');

				Readln;
 

end.

Open in new window

0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24071283
If the bug located, it's just a time question to solve, nothing mysterious..
E.g. we can enumerate working processes and match executable name.
0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24071517
Ready to see some terrible solution? ;-)
It works, finding PID within filename of exe, and then looks for window not just with this PID, but also checks window class name. :-) But we still do not know that we find the last  opened window.. Here we can store existing windows list, or hook CreateWindowEx, or..
Too many ways to go. :-)  Interested problem, but I need to sleep right now. Sorry.

You can download working exe here.
ftp://mechanic.is-a-geek.com/pub/Garbage/!2kill/SizeFFWindow.zip



program SizeFFWindow1;

{$APPTYPE Console}
 

uses Windows, Classes, Sysutils, Psapi, tlhelp32;
 

const FF_WndClass = 'MozillaUIWindowClass';
 

var m_Window: HWND;

		lpclass: PChar;
 

function EnumWindowsProc(Wnd:HWND; lParam:LPARAM): boolean; stdcall;

var processID: DWORD;

begin

	Result := true;

	GetWindowThreadProcessId(Wnd, @processID);
 

	writeln('PID = '+Inttohex(processID,8)+'  Wnd = '+Inttohex(Wnd,8)+

	'   Look for PID '+Inttohex(lParam,8));
 

	if processId = lParam then

	begin

		GetClassName(Wnd,lpclass,Length(FF_WndClass)+1);

		writeln('Class *'+lpclass+'*');

		if lpclass = FF_WndClass then

		begin

			m_Window := Wnd;

			Result := false;

			writeln('------ Matched -----');

		end;

	end;

end;
 

procedure CreateWin9xProcessList(List: TstringList);

var

hSnapShot: THandle;

ProcInfo: TProcessEntry32;

begin

if List = nil then Exit;

hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hSnapShot <> THandle(-1)) then

begin

   ProcInfo.dwSize := SizeOf(ProcInfo);

   if (Process32First(hSnapshot, ProcInfo)) then

   begin

     //List.Add(ProcInfo.szExeFile);

     List.AddObject(ProcInfo.szExeFile,TObject(ProcInfo.th32ProcessID));

     while (Process32Next(hSnapShot, ProcInfo)) do

       //List.Add(ProcInfo.szExeFile);

       List.AddObject(ProcInfo.szExeFile,TObject(ProcInfo.th32ProcessID));

   end;

   CloseHandle(hSnapShot);

end;

end;
 
 
 

procedure CreateWinNTProcessList(List: TstringList);

var

PIDArray: array [0..MAX_PATH - 1] of DWORD;

cb: DWORD;

I: Integer;

ProcCount: Integer;

hMod: HMODULE;

hProcess: THandle;

ModuleName: array [0..300] of Char;

begin

if List = nil then Exit;

EnumProcesses(@PIDArray, SizeOf(PIDArray), cb);

ProcCount := cb div SizeOf(DWORD);

for I := 0 to ProcCount - 1 do

begin

   hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or

     PROCESS_VM_READ,

     False,

     PIDArray[I]);

   if (hProcess <> 0) then

   begin

     EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb);

     GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName));

     //List.Add(ModuleName);

     List.AddObject(ModuleName,TObject(PIDArray[I]));

     CloseHandle(hProcess);

   end;

end;

end;
 

procedure GetProcessList(var List: TstringList);

var

ovi: TOSVersionInfo;

begin

if List = nil then Exit;

ovi.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);

GetVersionEx(ovi);

case ovi.dwPlatformId of

   VER_PLATFORM_WIN32_WINDOWS: CreateWin9xProcessList(List);

   VER_PLATFORM_WIN32_NT: CreateWinNTProcessList(List);

end

end;
 
 

function EXE_Running(FileName: string; bFullpath: Boolean; var aPID: integer): Boolean;

var

i: Integer;

MyProcList: TstringList;

begin

MyProcList := TStringList.Create;

try

   GetProcessList(MyProcList);

   Result := False;

   if MyProcList = nil then Exit;

   for i := 0 to MyProcList.Count - 1 do

   begin

     if not bFullpath then

     begin

       if CompareText(ExtractFileName(MyProcList.Strings[i]), FileName) = 0 then

         begin Result := True; aPID := integer(MyProcList.Objects[i]); end

     end

     else if CompareText(MyProcList.strings[i], FileName) = 0 then

     		begin Result := True; aPID := integer(MyProcList.Objects[i]); end;

     if Result then Break;

   end;

finally

	 MyProcList.Free;

end;

end;
 

function GetExePID(const FileName: string): integer;

begin

	EXE_Running(FileName, FileName<>ExtractFileName(FileName), Result);

end;
 

var

				sProcessInfo: PROCESS_INFORMATION;

				sStartupInfo: STARTUPINFO;

				szCommandLine: PChar;

				dw: DWORD;

				sProcessId: DWORD;

begin

				//init structures

				lpclass := StrAlloc(Length(FF_WndClass)+1);

				ZeroMemory(@sStartupInfo,sizeof(STARTUPINFO));

				ZeroMemory(@sProcessInfo,sizeof(PROCESS_INFORMATION));
 

				sStartupInfo.cb := sizeof( STARTUPINFO);
 

				szCommandLine := PChar('H:\Program Files\Mozilla Firefox\firefox.exe');

				//char szCommandLine[260] = {"C:\\windows\\notepad.exe"};
 

				CreateProcess(nil, szCommandLine, nil, nil, false, CREATE_NO_WINDOW or

					NORMAL_PRIORITY_CLASS, 0, 0, sStartupInfo, sProcessInfo);
 

				dw := WaitForInputIdle(sProcessInfo.hProcess, 10000);
 

				Sleep(2000);
 

				m_Window := 0;

				sProcessId := 0;

				sProcessId := GetExePID(szCommandLine);
 

				if sProcessId <> 0 then

				begin

					EnumWindows(@EnumWindowsProc, sProcessId);

					if (m_Window <> 0) then

						MoveWindow(m_Window, 100, 100, 800, 600, TRUE);

				end;
 

				StrDispose(lpclass);
 

				writeln('Press Enter');

				Readln;
 

end.

Open in new window

0
 
LVL 4

Author Comment

by:StefanKittel
ID: 24081915
Hello,

because this is a special ff-feature/bug I close this question.
I let the use choose it select process-ID (which works for most programs safe) or current top window (for ff).

Thanks

Stefan
0
 
LVL 5

Expert Comment

by:Mechanic_Kharkov
ID: 24082027
Such interesting problem.. and such simple solution.. :-(

:-) But works. So, let it be!
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Web Browsers Start Page Hijacker 14 106
unix example issues 18 73
Render HTML in a desktop app, not using a browser 4 72
Resolve Dependency Issues 4 42
I spend far too much time on the web keeping up with the news: politics, the environment, computer stuff, the Experts Exchange. It's never-ending. But many of the most informative web pages are overwhelmed with noise: scrolling banners, flashing tex…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Google currently has a new report that is in beta and coming soon to Webmaster Tool accounts. This Micro Tutorial will highlight new features for Google Webmaster Tools.

919 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now