Developers Club geek daily blog

1 year, 5 months ago
My hobby, in addition to programming — development of modifications for the game S.T.A.L.K.E.R. We work in command where, as well as it is accepted, everyone is responsible for something special. I besides that I enter a circle of developers, also perform software development for command. Under a cat read how we automated unpacking of game archives what problems faced and as they were solved.

Resources of game are packed in archives. To evaluate how many at us archives in the current bild you can below:

As we automated unpacking of game

Developers have all these archives in the unpacked type, and for testers we release the cumulative updates extending uniform archive.

In addition, there are also different sets of changes of 4 lower archives. Sometimes there is a need to unpack them all. We have different tools for packaging and unpacking, I know, at least, 2 sets – console and GUI the version. At each of them the shortcomings:

Console:
1. On unpacking of archives more ~ 1.6 GB fall.

GUI:
1. The choice of the initial folder, archive, a final directory – is made by hands.
2. only unpacking of 1 archive for time is possible.

As we have archives and almost on 2 GB, it is necessary to use GUI. When bothered to do me on hundred times one and too, I decided to automate it.

Raspakovshchik has here such interface:

As we automated unpacking of game

As we automated unpacking of game

As we automated unpacking of game

All this dialog boxes. I was suggested an idea by a field in which the file name is displayed. If it can be entered hands there or to select, then same it is possible to repeat and programmatically.

We will arm with C ++ with WinAPI and SPY ++ and we will work on the first window so far. Let's start a raspakovshchik and SPY ++, we will find its process there:

As we automated unpacking of game

And yes, in order that it was more convenient to look for the necessary fields on the screen, I advise them to fill with information, I, for example, selected archive. Well, we see fields here. It is possible to start to write a code …

Even at the first considering of idea I had a thought to make a convenient configuration file. Its structure was thought up at once and did not change:

Raspakovshchik.Ekhe – let to GUI of a raspakovshchik
C:\S.T.A.L.K.E.R\ – let before game
D:\Stalker SHоC\1\ – let to the folder in which it is necessary to unpack
YES – to receive the list of archives recursively (NO) or from the list below
gamedata.db1 – the list with names of archives
/ gamedata.db2 – the commented-out line

I will not stop in detail on how the config is read out. I will tell only that we have a structure with similar fields. To click buttons in other window we need to receive its handle. Further we have to receive handly of controls necessary to us. And, to receive them in that sequence in which they are connected (how they are connected is visible according to the revealing lists at elements in SPY ++. Let's look:

As we automated unpacking of game

We will receive handly it the following code:

HWND hwnd = FindWindow(NULL, "Select file to unpack...");
HWND hbnd = FindWindowEx(hwnd, NULL, "Button", "&Открыть");
HWND hсnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", "");
hсnd = FindWindowEx(hсnd, NULL, "ComboBox", NULL);
hсnd = FindWindowEx(hсnd, NULL, "Edit", NULL);
#ifdef _DEBUG 
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Select file to unpack...') " << hwnd;
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Button', '&Открыть') " << hbnd;
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Edit', '') " << hсnd;
#endif

The FindWindow (Ex) function — returns handle on object name. The second parameter can accept value of object class, and the first can transfer that object in which to look for (for example, we give window handle for search of the button).

After we obtained data, we need to send the message to control. We will do it so:

if ((hwnd != NULL &&hbnd != NULL ) &&hсnd != NULL)
 {
  //устанавливаем текст
  SendMessage(hсnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR(path_to_db.c_str())));
  //кликаем
  SendMessage(hbnd, WM_LBUTTONDOWN, 0, 0);
  SendMessage(hbnd, WM_LBUTTONUP, 0, 0);
  #ifdef _DEBUG
  BOOST_LOG_TRIVIAL(info) << "Sended";
  #endif
}

Here I will dwell as there were difficulties when filling ComboBoxa. Initially the code was a little another, and I received only:

HWND hсnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", "");

Also tried to fill it using:

SendMessage(hсnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR(path_to_db.c_str())));

But nothing was impossible. Why – I do not know still. One more problem was that I was confused by the principle of work of this window. On a screenshot it is visible above that when we select archive that only its name gets to ComboBox. The way does not appear anywhere. Hoping for a miracle, I gave a full path to archive there and everything earned. Miracles are? I think, clicking the button is Ok obvious, and we will not consider it.

Now operating time with the second window of the choice of folders came. At once I will give a code and then I will comment.

//работа со 2м окном
Sleep(time);
hwnd = FindWindow(NULL, "Обзор папок");
hbnd = FindWindowEx(hwnd, NULL, "Button", "ОК");
hсnd = FindWindowEx(hwnd, NULL, "Edit", NULL);
if ((hwnd != NULL &&hbnd != NULL) &&hсnd != NULL)
{
//устанавливаем текст
SendMessage(hсnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR(config.path_to_output.c_str())));
//кликаем
SendMessage(hbnd, WM_LBUTTONDOWN, 0, 0);
SendMessage(hbnd, WM_LBUTTONUP, 0, 0);
#ifdef _DEBUG
BOOST_LOG_TRIVIAL(info) << "Sended";
#endif
}

With this window problems appeared too. On it there are no visible controls, except buttons. We open SPY ++ and we watch that at us inside:

As we automated unpacking of game

I began to select different folders, and the name of a directory was brought in Edit control, besides, only a name (there what, the processor of click of a mouse at line puts them?). And I absolutely despaired because I could not provide as there to transfer the way to me. The first thought was to start all this under a debugger and to find that memory address where the final way lies, to inzhektit the dll in process and to change value in memory (and DEP will give it to make?).

This idea failed because I am not able to work with a debugger and never did it, and to study it is necessary to begin with simpler. Again hoping for a miracle, I transferred a full path in Edit — and everything earned! The pleasure was not a side-altar. Further there was a routine dopisyvaniye of a code with which you can get acquainted here. We received a convenient and versatile tool for unpacking. I think that I my solution not the only thing and will be glad if in comments tell something useful. Thanks for attention.

This article is a translation of the original post at habrahabr.ru/post/273595/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus