Категория: Компьютеры

Заметки о программировании и на околокомпьютерные темы

Вложенные категории: Игры, Delphi

Скачивалка Викидот

На чистом прекрасном Питоне написал я штуку, которая позволяет скачать викидот как репозиторий Mercurial.

Никто не знал, что такая штука вообще нужна, а я её написал.

Вот.

Quantum Break

Через несколько дней выйдет Quantum Break, игра для Xbox от Remedy, авторов Макса Пэйна. По-моему, как-то скучно выглядит, никому не кажется? Первая их игра, которая заранее не впечатляет. Что сюжет избитый — ну учёные, ну время сломали, — что герой непримечательная кирпичная морда. Что в ней захватывающего?

Выглядит как “книга в нагрузку”, которые иногда заказывают у малоизвестных авторов для игровых франшиз. “Вот у нас есть такие расы и юниты, давайте напишите что-нибудь, чтобы там были Кэрриган, протоссы и зерги. Я не знаю, вы автор, сами придумывайте.” Вот у нас есть такой актёр для вас купленый, нужно что-то про время и перестрелки, давайте придумывайте, вы разработчики или кто?

Конечно, сценарист по прежнему Сэм Лэйк, у него хороший вкус… Может быть, он знает, что делает. Но пока дифирамбы в твиттере редкие и непонятные. “Это будет лучшая игра на XboxOne”. Да почему? Графика обычная, стиля не видно…

“Логические цепочки” в имперском Фениксе Райте!

Холмсовские “логические цепочки” в Дай-гякутэн сайбан это потрясающе! Так же здорово, как суды, когда они появились впервые. Почему Феникс Райт всем нравится — разумеется не за детектив, там на 30 страниц текста один вопрос с очевидным ответом, а за кинематографичность, за возможность почувствовать себя сыщиком в момент успеха. Крикнуть “Минутку!”, швырнуть в лицо доказательства…

“Логические цепочки” это то же самое. Ты превращаешься в гения, мысль которого летит от вывода к выводу. В книгах о Холмсе разрешалось лишь чуть-чуть прикоснуться к успехам сыщика, здесь встаёшь на его место. Как красочно они сделаны — щелчок пальцев, взмах руки, подсветка на персонаже, крупный план — как в кино! Успех, успех.

Да и Холмс смешной персонаж, хороший.

999

Прошёл 999 (9 дверей, 9 часов, 9 пленников), который вроде как от Котаро Утикоси, одного из сценаристов KID. Наркомания и бред, Эвер 17 версия для младшеклассников, профессор Лейтон и таинственный корабль. Игровой процесс это решение детсадовских паззлов: сложить пятнашки, воспроизвести морзе по бумажке, собрать шесть обрывков чего-нибудь, перемежаемое сюжетной болтовнёй. По сюжету герои заперты на огромном корабле (почти Титанике), и должны оттуда выбраться. Им преграждают путь детские логические задачки. Финальная битва была судоку! В конце, следите за руками, (окончательные спойлеры по Эвер17, да, Эвер17) выясняется, что этот эксперимент уже был 9 лет назад, и там погибла какая-то девочка, и короче, его повторяют затем, чтобы через какое-то морфологическое поле связаться с этой клушей 9 лет назад и объяснить ей, как решать судоку (!!!!), чтобы она там не сгорела *стена лицо*.

Злодеи все такие злодеи, что уже на 9-й минуте все их планы понятны, и большую часть игры сидишь и ёрзаешь “да, сейчас он вас понятно как обманет, ну давай, герой, обрати внимание, это что мне, ещё одну ветку проходить, чтобы до тебя дошло, что ли?”

В общем, одну ветку этого добра пройти может ещё и не плохо, а вот 4 или сколько там надо для тру энда, это уже совершенно лишнее.

Цианогенмод

Внезапно ударился в перепрошивку мобильника и неплохо в этом освоился. Выяснилось, для моего Galaxy S2 есть Цианоген аж Android 5, и он нормально работает – быстрее, чем стоковый 4.4!

  • Никаких лишних приложений. Система весит 300 мегабайт против стоковых 600.
  • Для Цианогена есть кастомные ядра, которые оптимизированы не тратить батарею попусту + быстрые. Итог: в полтора раза (!) выше производительность мобильника.
  • В стандартной прошивке выключен Trim, со временем флешка работает всё медленней и медленней, в Цианогене он включен!

А началось с того, что в Galaxy S2 системный раздел 2 гб и 12 гб встроенный флеш. И на эти 2 гб не влезают приложения. Я уже намучался с LinkToSD, это неудобно и не всё можно перенести. И тут выясняется, что эти 2 раздела это разделы на одной флешке.

ДА НА КОГО Ж ТЫ ТАКОЕ СДЕЛАЛ, САМСУНГ

Я решил их переразметить. И вот так слово за слово… Но я их переразметил, теперь у меня 6 гб программы и никаких LinkToSD, забыл как о страшном сне. Нужно будет – сделаю больше (данные у меня всё равно на внешней SD-карте).
Какой же комфорт я себе навёл этими действиями! Ах. Трудно поверить, что я жил в этом кошмаре 3 года.

Вкратце итоги для новичков:
– Можно переразметить разделы. Даже не очень сложно! Можно даже и на лету (я потом нашёл утилиту), но лучше с полной перепрошивкой.
– Можно сохранить все данные с прошлой системы. И все установленные программы! См. Online nandroid.
– Если у вас зашифрован мобильник, бэкапьте на расшифрованную флешку. Расшифрованную!

Вот. Потом обнаружилось, что в штатном драйвере exfat баги, и он падает на АнкиДроид, а куда я без АнкиДроид. Так что я собрал Цианогенмод сам (виртуальная машина + 150 Гб места + 6гб оперативки + 4 часа компиляции + несколько дней возни) и в общем довольно легко нашёл эту багу, её уже пофиксили, но фикс застрял в code review. Теперь у меня на мобильнике собранный своими руками драйвер ФС, и он не падает.

Posting to console from GUI app

In Windows, apps can be marked as either GUI or console. GUI apps have windows with controls, console apps run in a black box, receive text input and produce text output. Inputs and outputs can be redirected, allowing to chain applications and write results to file:

dir | find ".dll" > list_of_dlls.txt

For apps which do not output streams of data, console is usually a good way to print status messages. There’s a whole class of apps that could benefit from functioning both ways: if run as is, they display GUI, but with command-line switches they do the job silently and exit.

myapp.exe — runs graphical interface

myapp.exe /source dir1,dir2 /output dir3 — does the job silently and exits

Could these apps detect when they’re running from console and output status messages? And otherwise behave entirely like a console app?

This is an interesting and complicated topic and here are my findings.

(Read the article)

Background

Console and GUI subsystems

Each EXE file has a flag that marks it either as GUI or CONSOLE subsystem application (there are other subsystems but they are not important for this article). Apps marked as console or GUI behave differently.

Console apps:

  • When run as is, create a new console window for itself.
  • When run from another console app (such as cmd.exe), inherit its console window and do not return until they’re done.

GUI apps:

  • When run as is, are invisible (until they create some GUI windows manually).
  • When run from a console app (such as cmd.exe), return the control immediately and work in the background.

Nevertheless once started, they are identical. They can call the same functions, they have the same rights, and so far as Windows is concerned, each can be reconfigured to be another.

There’s no principal difference between Console and GUI app, once they’re running.

Consoles

Each process can have up to one attached console. Consoles are windows where you type the input and where the output is printed. They are created automatically by the system when a Console-marked application starts and has no inherited console.

Each console provides three standard handles, for input, output and error output. They are passed to the application as described below. When you write to an output/error handle, that data is displayed in the console. When you read from an input handle, the console lets the user type some characters and returns that.

Attaching a console means you can use those handles. Without a console attached even if you somehow get those handles, they will not work.

Attaching goes deeper than that: once the console window is closed, all attached processes will be terminated and there’s no way to stop that, though you can receive a notification and be allowed to finalize.

When a console-marked app starts another console-marked app, the latter inherits the console. No new window is created, and it receives the same input, output and error handles.

GUI-marked app never inherit the console, no matter how they are started. But they still inherit the handles, which will be broken (see below).

By default in modern systems console window is implemented by conhost.exe. But there are apps which replace it when installed.

Attaching to a console

Any application, including a GUI-marked one, can attach to a console with AttachConsole(), by passing the process ID of a process with a console (copying a console from it).

If two applications are attached to the same console, both can read and write to it. Unless they coordinate, they’ll produce a mess.

Any application can create a new console for itself with AllocConsole(). This will spawn a new console window, identical to the one Windows creates automatically for console-marked apps.

In fact, for console-marked apps Windows just calls it automatically, if no console is inherited.

Detaching from a console

Any application, including a console-marked one, can detach from a console with FreeConsole(). In that case standard handles stop working.

Yes, that means a console app can stop being a console app, if it wishes so.

Console windows are destroyed automatically once no one is attached to it. If you’re the only one attached (because you created the console with AllocConsole() or because it was created for your console-marked process automatically), once you FreeConsole() the window disappears and you continue running.

If you inherited the console from a parent process or attached to it manually, it’ll stay for that other process.

Standard handles

To input and output data in console apps Windows provides three read-write handles which can be obtained from GetStdHandle(): STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE.

These are standard Windows handles, same as returned by CreateFile().

For a console app, all of these point to an attached console. If the input is redirected, they will point to files or to pipes to another app. For a GUI app started from Explorer, all will be zero.

By default these handles are inherited from parent to child. If you start a process from console, it will have its standard handles set to that console.

There are two ways to override handles for another app:

  • Or you can SetStdHandle() for your own process temporarily and start a child process like that (since standard handles are inherited).

To redirect input/output, the usual approach is to create an inheritable pipe, pass one end to a child process as an input and write to another. That’s more or less what cmd.exe does when it chains applications. But you can pass any handles which support reading/writing, including network handles and file handles.

How console-marked apps are started

All processes under Windows are ultimately started with a variation of CreateProcess(). This function returns immediately once the process is started.

How is it, then, that when you run a console-marked app from a command line (cmd.exe) it does not return until it is finished?

The answer is that cmd.exe itself does that. It starts the process and if it notices that the process is a console-marked one, it waits for it to return, and sets ERRORLEVEL to its exit code.

Why does it do that? Because child command-line processes inherit the console and start writing to it, and if cmd.exe continued to use the console at the same time, the result would be a mess. So it waits until the console is free again.

In other words it’s not built into the OS. If your command-line app starts another command-line app, by default it’ll still return immediately, and that app will write to your console in parallel with you.

What if I don’t want to share my console?

You can pass a flag CREATE_NEW_CONSOLE or DETACHED_PROCESS to attach a new console to a console-marked app, or to start it without any (like a GUI app!)

Can I share my console with a GUI app?

By default, no. There’s no way to start a GUI-marked app with inherited console. There’s no way to attach a console to another application. Only the application itself can call AttachConsole to attach one.

Can I start a GUI app with an attached console?

Yes, but only with a new one (pass CREATE_NEW_CONSOLE).

Reading and writing to console from GUI app

Since standard handles are inherited, GUI apps run from console receive handles to that console. But those handles will not work, because the console itself is not attached.

To make them work, it’s enough to do AttachConsole(ATTACH_PARENT_PROCESS).

There’s a host of cases that needs to be covered:

  • Standard handles (from GetStdHandle()) may be 0, which indicates that either you were started from Explorer, or that whoever started you wanted you to throw away your output. In this case, you do not have to AttachConsole().
  • Standard handles may be redirected to a file, or a pipe, or elsewhere. In which case you still do not have to AttachConsole(). You should just write where pointed. How to check what those handles are? GetFileType() == FILE_TYPE_CHAR, but it wouldn’t work — see below.
  • Standard handles may look like a console handles, but come from your own console, attached to you automatically because someone started you with CREATE_NEW_CONSOLE. It would not be nice if you detached from it and attached to a parent one, so you must not call AttachConsole in this case. How to tell if you have your own console? GetConsoleWindow().
  • Standard handles may come from a console, but an entirely different one because someone screwed up. In which case there’s nothing you can do and the behavior is undefined, but it would probably be better to just write wherever pointed, and not AttachConsole (since parent is unrelated).

Summarizing, what do we do?

If we have a console (GetConsoleWindow() <> 0), do nothing! We have explicitly been told exactly where to write.

If all the handles are zero, and you cared to check, do nothing! Either we don’t have a console-enabled parent (nowhere to attach), or been explicitly told to be silent.

Otherwise we could check GetFileType() to see if any of our handles is FILE_TYPE_CHAR. But there are two troubles with that. First, FILE_TYPE_CHAR also means stuff like LPT printers and not only consoles. And second, while the console is not attached, console handles will return FILE_TYPE_UNKNOWN.

So there’s no clear way to tell. As an optimization, you could check whether all of the handles are FILE_TYPE_PIPE and FILE_TYPE_DISK and in this case skip the AttachConsole(), but there’s plenty of cases where you don’t need AttachConsole() and can’t tell it.

So just do it. AttachConsole() returns FALSE if there’s no console underneath, and has no other consequences; we’ve already determined we have no other console to lose, so even if we attach to a parent one for no reason, it won’t hurt. Or will it?

What are the consequences of attaching to a parent console?

There are two:

  • Your process will be terminated if a console closes (see the section on Consoles)
  • Parts of your code which write to console may write to the parent console unexpectedly for the parent process.

Remember that for GUI-marked apps, cmd.exe returns immediately and the user may be typing another command, as you steal the console from them and output your messages. Therefore attaching to a console must be accompanied by a parent application waiting until you finish (how to achieve that will be described in the sections below).

Since there’s no way to guarantee that you’re being run in that fashion, it may be sensible to not attach to a console by default. Only if you’re passed a flag (say, "/console") indicating that the user (or an intermediate app) wants to run you in a console mode, only then should you attach a parent console.

How to run a console-attaching program

By default, cmd.exe does not wait for your process to return. It returns the control to the user immediately. If you attach the console and start writing to it, you’ll be interfering with user’s actions.

Even if you do not attach the console, your error code will not be delivered to the cmd.exe, and will not be put into ERRORLEVEL, as expected by scripts.

There are two approaches:

  • start "" /WAIT will start the app and wait for it to return. It will also properly handle the error code. This is entirely sufficient if your app does AttachConsole() and it works (see below about problems with runtimes).
  • You can write your own console-marked wrapper to start the app, wait for it to finish, then query and return it’s error code. This is preferable if you want a neat console shortcut to your GUI app, and when more complicated handling is needed (see below).

Consoles, standard handles and runtimes

AttachConsole() is fully enough to make ReadFile() and WriteFile() on console handles work just like they would in a console app.

But in a real world, most people write to console through some kind of language abstraction (printf() in C++, writeln() in Pascal and so on).

These abstractions are wrappers around platform-dependent functions, and on Windows resolve to querying GetStdHandle(STD_OUTPUT_HANDLE) and doing WriteFile() to it. But they introduce problems.

There’s two kinds of problems I’ve encountered:

  • Buffering, and
  • Handle caching

Buffering

Most runtimes do not write to files immediately as you call the equivalent of printf("text"). Badly written code often outputs data char by char, and it would’ve been too many system calls. Instead, they collect the data locally and push it to the operating system only occasionally.

C/C++ for example has three modes of buffering available for CRT FILEs: no buffering (output immediately), line buffering (output on each CR/LF) and block buffering (output when something like 2048/4096 bytes are collected).

CRT tries to be smart about it and chooses different buffering schemes for different files. For stdout it chooses line buffering, as it assumes we want to see each line as soon as it’s printed, not ten minutes later when enough data has been collected.

But when it detects the output is redirected (i.e. standard handles point to something other than FILE_TYPE_CHAR), it switches stdout/stderr to block buffering.

For instance, if you run a C++ app with it’s output redirected to a pipe, and if you read from that pipe and put that on the screen, you will not see the output line by line as the program executes. You will instead receive it in blocks of several lines, which is not how we expect console apps to function.

Similar buffering exists in most runtimes, although sometimes it’s smaller and less noticeable.

In C Runtime it can be disabled by calling setvbuf(stdout, NULL, _IOLBF, BUFSIZ) to enable line mode, or setbuf(stdout, NULL) to disable buffering at all. It needs to be done manually even if you output to console to which you attach with AttachConsole, because the buffering is decided before entering main(), and at that time console is not yet attached, so GetFileType() returns FILETYPE_UNKNOWN.

In particular, in Visual C Runtime line buffering is not implemented at all, so setbuf(stdout, NULL) should be used instead.

Other runtimes have their own ways of disabling buffering. If there’s none, sometimes you’ll have to bear with it.

Handle caching

Some runtimes, notoriously Visual C Runtime, inspect standard handles once and then remember the results forever. If your application starts with one set of standard handles, and then you use SetStdHandle to redirect your own output, that redirect will not be applied to stdout because it has already decided where to write.

This is especially bad with ATTACH_PARENT_CONSOLE method. By the time you get to do AttachConsole, C Runtime has already inspected the standard handles, called GetFileType() on them, seen that they’re FILE_UNKNOWN_TYPE (because their console wasn’t attached) and marked to never write anything to stdout/stderr.

Is there anything you can do? No.

There’s no way to make C Runtime re-decide. You can open a new FILE for a standard handle with _open_osfhandle, but you cannot assign it to stdout for it is a constant. You can freopen stdout, but only to a file name, not to a handle already opened. Finally, some sources teach to freopen("CON"), but this will always return a handle to attached console (no matter if it’s not set as your output), what if your standard handle is actually redirected to a file? Or a pipe?

So in short, there’s no reliable, non-hackish way (which doesn’t involve patching internal CRT structures).

In this case ATTACH_PARENT_CONSOLE method is not going to work, and you’re restricted to a console-marked wrapper with pipes (see in Solutions).

Compiled solutions

Summarizing all the knowledge we’ve accumulated, we’ll list approaches to making a GUI application behave in a console-like way.

ATTACH_PARENT_CONSOLE

When our app detects its parent process has a console, and it doesn’t have a console of its own, and perhaps it’s started with a "/console" flag, it calls AttachConsole(ATTACH_PARENT_CONSOLE) and ignores the result.

If used with a "/console" flag, it then can adjust buffers and other settings as expected from a console app.

if ((GetConsoleWindowHandle() == NULL) && (haveArg("/console"))) {
 AttachConsole(ATTACH_PARENT_CONSOLE);
 setbuf(stdout, NULL);
 setbuf(stderr, NULL);

}

It can then be run with start "" /WAIT app.exe params.

Console wrapper

A small console application can be written which starts the target application, passes it’s entire command line unchanged, waits for it to return and returns the error code.

Usually there’s not even a need to change the GetCommandLine() before passing it as lpCommandLine to the CreateProcess(), as the first argument in it needs not to be equal to the actual executable name. It’s enough to pass a correct new executable into the lpApplicationName.

Such a wrapper may include any additional flags you wish, for instance it may pass "/console" flag to your app to make it adjust its behavior (see ATTACH_PARENT_CONSOLE).

You do not need to override any of the standard handles, as they’ll be automatically inherited.

Console wrapper with pipe redirection

When ATTACH_PARENT_CONSOLE method doesn’t work, you’ll have to write a wrapper with pipe redirection. Do the same as in the previous step, only create three pipes in addition.

These pipes must be created with "Inheritable" flag set.

SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CreatePipe(out, in, &sa, 0));

For each pipe, pass one side as a standard handle to the child process and close it after the CreateProcess() call, keep the other side and read or write to it (make sure to keep the side you need, one is for reading, the other for writing).

Start a process with inherit handles flag set to true, then wait for it to finish, meanwhile translating input to it and reading and posting output. You’ll probably need a separate thread for input (readln() and write to input pipe in cycle), and you can handle both output and error output pipes in the main thread, by looking with PeekNamedPipe() and reading if there’s something to read.

This way when the target app starts, it already has valid input/output redirected handles. You may need cooperation of the target app to configure buffers and such like in ATTACH_PARENT_CONSOLE method.

Controlling the lifetime of a child process

Since your wrapper is a console-marked application, it is attached to a parent console and will be terminated if you press Ctrl-C, or if a parent console is closed.

But your child process is a GUI app. If it does not do ATTACH_PARENT_CONSOLE, it will remain in the background even after you’re terminated.

To work around that, set your own SetConsoleCtrlHandler(). This function will receive notifications when Ctrl-C is pressed or the console you’re attached to is about to go down.

You will not be able to prevent that, but you’ll be able to terminate the child process with you.

tee

There’s a quick and dirty way to test redirection before writing a wrapper. Use tee, an utility from unix-utils, available from cygwin. It’s purpose is to redirect the output both to file and to the screen; if you omit the file, you’re just getting the redirection wrapper:

MyGUIapp.exe | tee

Console app + GUI wrapper

Another way of having a dual console/GUI app is to mark it as console and FreeConsole immediately after start if you’re running in a GUI mode. But that still produces flickering console window (ugly).

But why, you can make a thin wrapper. It’s only role is to start the console app with DETACHED_PROCESS flag. This flag instructs Windows to not create a console window. Your app can then detect that it has no attached console (with GetConsoleWindowHandle) and run in a GUI mode.

This is the simplest approach of all, and with the least amount of code.

FAQ / TLDR

Yes, you can have a chameleon console/GUI app, but reliably only through a secondary helper app.

Can I write to console from my GUI app, if it’s run from one?

Yes, so long as you AttachConsole(ATTACH_PARENT_CONSOLE) or AllocConsole() and use WinAPI functions. But you don’t want to do this.

Why don’t I want to do that?

Because the parent application does not expect this. You should only ATTACH_PARENT_CONSOLE if you’re run in a certain way.

How should I be run so that I can attach parent console normally?

By start "" /WAIT appname.exe or through a special wrapper app.

How do I know that I’m run like that?

You don’t. The usual way is to pass you a flag, something like "/console". But you may decide to be reckless and just always attach the console.

Will my default printfs/writelns work everywhere in a program?

Sometimes. Some runtimes permit this, others don’t. C Runtime doesn’t, Delphi does. If your runtime doesn’t, WriteFile will work, but printfs won’t.

Can’t I do something so that my normal printfs work?

You can make a console wrapper around your app which runs it with redirected handles. It’s more work, but it will be almost transparent to your GUI app.

Can my GUI app tell if it has a console?

Yes, by checking GetConsoleWindowHandle(). But most of the time, your GUI app will NOT have a console. It does not inherit the console by default, even if started from one. You have to connect to one manually.

Okay, can my GUI app tell if there’s a parent console to connect to?

It probably can, but it’s easier to just go ahead and try to connect. If it fails, it fails. But make sure you don’t have your own console beforehand.

Can I make some existing GUI app (pre-compiled) write to console? (I know it calls printfs, even though it has no console)

Yes you can, by writing a wrapper. But there may be inconveniences (buffered output). One simple way to test it is to use tee from unix-utils.

Further reading

Life is slow

Художественные герои часто страдают книжной медлительностью. Вот героиня обнаружила, что может отматывать время. А потом и отмотала время на 5 лет и спасла отца подруги, в результате чего спойлеры спойлерыбабочки бабочки подруга оказалась в инвалидном кресле. Поставьте себя на её место, что вы сделаете первым делом, увидев такие дела?
– Назови мне дату, когда это случилось, и расскажи подробности, правильно же?
Но у героини целая глава впереди, поэтому она ходит по дому, ужасается, всем сочувствует и привыкает жить в этой совершенно ненужной временной ветке.

Google Pay

А что, в гугл-плей действительно нельзя публиковать даже бесплатное ПО, если не заплатить 25 баксов? Я тут написал штуку для московских велопарковок

Обычное приложение грузится полчаса, потом надо тыкать “Без регистрации”, потом у него данные на карте вчерашние, потому, что оно обновить не смогло, и непонятно, как я должен был об этом узнать.

А тут выбираешь несколько любимых парковок, запускаешь программу и сразу видишь, что сервер про них сказал.

Как её выложить-то теперь?

И ещё может кто знает, почему APK получаются такие огромные? Классов с гулькин нос, а скомпилированный код (.dex) 6 мегабайт.

О борьбе за остановку и неостановку служб

Службы в Windows задумывались как возможности системы, которые можно выбирать и запускать по желанию. Хочешь расшаривать файлы – запусти службу “Сервер”, хочешь печатать документы – запусти “Диспетчер печати”.

Для этого добрые силы в Microsoft сделали им команды запуска и остановки, а также настройки (запускать автоматически, по желанию, запретить запуск). Но злые силы с каждым годом всё больше ломают эти правила:

1. Некоторые службы стало нельзя останавливать. Без них система принудительно перезапускается через минуту, а вскоре запретили и команду остановки. С каждым годом таких сервисов всё больше (в Windows 10 уже штук 8).

2. Некоторые можно останавливать, но нельзя изменить тип запуска – они запускаются автоматически. Таких ещё 3-4 штуки.

3. Многие службы можно останавливать и можно перевести в режим “вручную”, но их всё равно принудительно запускает Windows Explorer. Какой тогда смысл в настройке “вручную”?

4. Начиная с Windows 7 появился ещё один вид издевательства: службы, которые восстанавливают свой режим работы. Их можно установить во “вручную”, но через 20 минут они всё равно выставят себя в “автоматически” (например, служба BITS). Какого чёрта, а?

(ещё)

Список служб как будто специально составлен так, чтобы в нём никто не мог разобраться:

1. Нигде не сказано, что именно делает каждая служба, и для чего требуется.

2. В Windows XP было модно давать службам “описания” вроде “Служба оркестратора управления командами. Требуется для клиентов, использующих оркестрацию управления командами. Если отключить эту службу, все компоненты, зависящие от неё, не смогут запуститься”. В Windows 10 описания службам просто не дают.

3. Множатся службы, с виду делающие одно и то же. Например, netman, netprofm, NlaSvc, NcaSvc, nsi, WcmSvc все как будто занимаются поддержанием списка сетей на компьютере. У пяти нянек дитя без глазу: попробуйте угадать, какая из них нужна, чтобы иконка сетевых подключений в Windows 10 работала правильно? (Ответ: WcmSvc. А в Windows 7 и ранее что-то другое).

Наконец, правая рука у Microsoft не знает и не любит то, что делает левая. Кроме служб различное ПО запускает в фоновом режиме бесконечные COM-объекты, обработчики WMI и вспомогательные процессы (Explorer особенно грешит этим). Убить их окончательно тоже нельзя, как и отключить ненужный функционал. Кортана в русских версиях не работает, а если б и работала, мне не нужна – но обслуживающий её процесс будет запущен, сколько не убивай.

И Microsoft ещё говорит, что идёт какая-то борьба за производительность, скорость загрузки и экономию батарей!

Освойте системы контроля версий

Если у вас есть пара дней на то, чтобы освоить один какой-нибудь продвинутый инструмент из мира технарей, освойте системы контроля версий (Mercurial или Git – под Windows я точно советую Mercurial). О программистах я даже не говорю, но если вы пишете книги, переводите (тем более вместе с другими), храните какие-то заметки, короче говоря, работаете с текстом, регулярно обновляя его, вы ещё этого не знаете, но вы без Mercurial как без рук.

Что скрывается за страшными словами “система контроля версий”?

Вы ставите на компьютер специальную программу, TortoiseHg.

Щёлкаете правой клавишей по папке – “Создать репозиторий”.

Дальше вы кладёте в эту папку какие-то текстовые файлы – например, исходники программы или книгу, которую пишете. И каждый раз, когда вы что-то в них исправили, щёлкаете по папке правой клавишей и говорите “Commit”. И пишете пояснение: “Переписал драку героя с инопланетянами”.

Через некоторое время вам кажется, что прежняя драка с инопланетянами была лучше. Вы щёлкаете по папке правой клавишей и говорите: “История изменений”. Программа показывает вам, каким был ваш текст вчера, позавчера, в самом начале, и как он менялся. Как у страницы в Википедии. К любой версии можно вернуться.

(Но это не всё.)

Но это не всё. Пока вы переписывали драку с инопланетянами, ваш редактор у себя дома исправлял по всему тексту орфографические ошибки. Если вы пользуетесь чем-то вроде Dropbox, то у вас теперь два файла и нужно вручную копировать куски из одного в другой, и дай бог, ничего не забыть.

С Mercurial всё проще. Во-первых, он показывает вам, что поменялось в каждом варианте. Во-вторых, он сам умеет их объединять. Вы щёлкаете правой клавишей по папке, говорите “Отправить на сервер”. Редактор у себя дома щёлкает по своей папке, говорит “Получить с сервера”. И видит, что от последней версии на сервере растут два хвоста: ваш и его. Он щёлкает по вашему, выбирает “совместить” и Mercurial сам совмещает правки. На случай, если он сам не сможет, он предложит вам – подсветив каждое разногласие и дав выбрать.

Даже если что-то совместить не получилось, или редактор напортачил, всегда можно вернуться к любой из прошлых версий. Можно посмотреть, какие правки внёс редактор. Системы контроля версий снимают с души огромные камни:

  • Камень “а вдруг я изменю, а получится хуже”. Если получится хуже, вернётесь к старой версии.
  • Камень “а вдруг я не все чужие исправления заметил”. Mercurial показывает все исправления.
  • Камень “сейчас я поправлю, а он там какую-нибудь старую версию редактирует и всё затрётся”. Mercurial следит, объединяет, и главное – никогда не даст затереть. Однажды внесённая в него версия остаётся в нём навсегда.

Мало того!

Системы контроля версий дают работать сразу над разными вариантами развития. Вы написали так, товарищ по-другому, не обязательно сливать ваши варианты сразу же. Вы можете продолжать пилить свою главу, напарник – свою, каждый со своим редактором. Когда ваши главы будут готовы, только тогда вы сольёте их воедино и из двух веток образуется общее будущее.

В одной ветке может храниться TV-версия сериала, в другой – получившаяся из неё BD-версия. Пока BD-версию допиливают, в ТВ-версии исправляют опечатки, наконец, BD-версию пора выпускать, и тут вы берёте все наборы исправлений, которые наслоили на TV-версию со времени её отпочкования, и переносите их на ветку BD.

Вы можете скопировать всю папку с файлами как обычную папку. Можете создать четыре копии, в каждой исправить что-нибудь своё, каждую закоммитить, а потом всё слить. Можете положить папку на флешку, сходить с ней к другу, вернуться и влить в домашнюю версию правки. Можете в одной копии папки отмотать на ноябрьскую версию, а в другой текущую, приделать к ноябрьской хвост.

Чтобы освоить системы контроля версий нужно некоторое время, но это такой могущественный молоток, что когда вы им овладеете, гвозди будут торчать из каждого косяка, вы будете ходить по всему дому и заколачивать, и заколачивать. А благодаря TortoiseHg / TortoiseGit, работа с ними уже стала достаточно простой даже для обычного пользователя.

Скажу, что Git по функциям не сильно отличается от Mercurial, но я советую последний, поскольку у него удобнее интерфейс под Windows. Если вы работаете из консоли, то совершенно неважно – выбирайте любой (Git сейчас популярнее).