:: MVP ::
|
|
:: RSS ::
|
|
|
rundll32.exe – утилита командной строки, которая позволяет запускать некоторые функции, заложенные в
DLL-файлах. Она входит в состав всех операционных систем Windows 32bit и 64bit.
Работать с ней из самой командной строки не самый удобный способ, гораздо удобнее создать *.bat файл или ярлык
(в последнем случае можно выполнять команду и по нажатию горячих клавиш). У обладателей клавиатур с настраиваемыми
клавишами есть еще одна, самая удобная, на мой взгляд, возможность - "посадить" команду на одну из таких клавиш.
В качестве примера работы с rundll32 рассмотрим следующую команду, которая прячет курсор мыши:
rundll32 user32,SetCursorPos
|
В интернете можно найти много других готовых команд, которые может выполнить с помощью rundll32.
А в этой статье мы научимся создавать свои.
Для начала разберемся поподробнее, что же такое rundll32. Программа rundll32 загружает и выполняет 32-разрядные
библиотеки. Эта программа позволяет вызывать функции только из тех библиотек, при разработке которых была
реализована подобная возможность. Если при запуске программы rundll32 указать в качестве аргумента библиотеку DLL
неподдерживаемого типа, программа завершит работу, при этом сообщение об ошибке не отображается.
При создании пользовательской библиотеки в нее необходимо поместить функцию <EntryPoint> со следующим прототипом
// ANSI
procedure EntryPoint( hWnd: Integer; hInstance: Integer; lpCmdLine: PAnsiChar; nCmdShow: Longint ); export; stdcall;
// UNICODE
procedure EntryPoint( hWnd: Integer; hInstance: Integer; lpCmdLine: PWideChar; nCmdShow: Longint ); export; stdcall;
|
Функции, являющейся точкой входа для программы rundll32, передаются следующие параметры:
- hWnd — идентификатор окна, который должен указываться в качестве родительского окна при
создании окон в функциях загружаемой библиотеки;
- hInstance — заголовок экземпляра выбранной библиотеки;
- lpCmdLine — командная строка, передаваемая библиотеке. Данная строка представляет
собой последовательность символов, завершающуюся символом с кодом 0 (ноль);
- nCmdShow — режим отображения окон выбранной библиотеки.
Посмотрим на пример команды, запускающей средство Rundll:
rundll32 SetupX.dll,InstallHinfSection 132 c:\Windows\Inf\Shell.inf
|
При выполнении данной команды средство rundll32 вызовет функцию InstallHinfSection(), находящуюся в
библиотеке Setupx.dll, и передаст ей следующие параметры:
- hWnd = (заголовок родительского окна);
- hInstance = параметр HINSTANCE библиотеки SetupX.dll;
- lpCmdLine = "132 c:\Windows\Inf\Shell.inf";
- nCmdShow = (данные, передаваемые функции CreateProcess).
Следует обратить внимание на то, что функция <EntryPoint> (в приведенном выше примере — функция
InstallHinfSection()) должна самостоятельно выполнять анализ командной строки и обрабатывать отдельные ее аргументы.
Использование rundll32.exe в операционных системах линейки Windows 9x несколько отличается от использования в операционных
системах линейки Windows NT. Это сделано для корректной обработки командных строк, содержащих символы в формате UNICODE.
Операционные системы линейки Windows NT пытаются получить значение GetProcAddress для функции <EntryPoint>W.
Если данная точка входа найдена, операционная система считает, что используется прототип с поддержкой UNICODE
(различие ANSI и UNICODE прототипа заключается в параметре lpszCmdLine). Если операционная система не находит
функцию <EntryPoint>W, то Windows NT пытается определить значение GetProcAddress для функций <EntryPoint>A
и <EntryPoint>. Если одна из этих функций существует, она будет рассматриваться как точка входа ANSI и будет
обрабатываться таким же образом, как в операционных системах линейки Windows 9x. Поэтому, если пользовательская разрабатываемая нами DLL
должна работать в Windows 9x со строками ANSI и в Windows NT со строками UNICODE, необходимо экспортировать функции EntryPointW и EntryPoint.
В операционных системах линейки Windows NT будет вызываться функция EntryPointW, которой будет передаваться строка в формате UNICODE, а в
Windows 9x будет вызываться функция EntryPoint, которой будет передаваться строка в формате ANSI.
Теперь перейдем к практике, напишем библиотеку, реализующую как ANSI, так и UNICODE вариант функции, и как следствие работающей как
под Windows 9x, так и под Windows NT. Суть этой библиотеки заключается в том, что она изменяет текст на контроле активного окна,
имеющего фокус.
library send32;
uses
Windows, Messages, SysUtils, Classes;
{$R *.res}
function GetFocusedWindow: HWND;
var
CurrThID, ThID: DWORD;
begin
Result := GetForegroundWindow;
if Result <> 0 then
begin
CurrThID := GetCurrentThreadId;
ThID := GetWindowThreadProcessId( Result, nil );
Result := 0;
if CurrThID = ThId then
Result := GetFocus
else
begin
if AttachThreadInput( CurrThID, ThID, True ) then
begin
Result := GetFocus;
AttachThreadInput( CurrThID, ThID, False );
end;
end;
end;
end;
procedure InsertText( hWnd: Integer; hInstance: Integer; lpCmdLine: PAnsiChar; nCmdShow: Longint ); export; stdcall;
var
Wnd: THandle;
begin
if ParamCount = 2 then
begin
Wnd := GetFocusedWindow;
if Wnd <> 0 then
SendMessageA( Wnd, WM_SETTEXT, 0, LParam( PAnsiChar( ParamStr( 2 ) ) ) );
end;
end;
procedure InsertTextW( hWnd: Integer; hInstance: Integer; lpCmdLine: PWideChar; nCmdShow: Longint ); export; stdcall;
var
Wnd: THandle;
begin
if ParamCount = 2 then
begin
Wnd := GetFocusedWindow;
if Wnd <> 0 then
SendMessageW( Wnd, WM_SETTEXT, 0, LParam( PWideChar( ParamStr( 2 ) ) ) );
end;
end;
exports
InsertText,
InsertTextW;
begin
end.
|
Библиотека экспортирует 2 функции - InsertText, которая будет вызываться в операционных системах семейства Windows 9x, и InsertTextW,
которая будет вызываться в операционных системах семейства Windows NT. Чтобы воспользоваться данной командой запрограммируем кнопку на
клавиатуре, не забыв скопировать скомпилированную библиотеку в "%WINDIR%\System32\".
А вот как выглядит результат ее работы:
Все же в настоящее время операционки семейства Windows 9x встречаются довольно редко, и добавлять их поддержку в библиотеку следует
в том случае, если вы планируете распространять свою библиотеку. Для себя же (или для внутреннего использования в рамках небольшого
предприятия), как мне кажется, можно обойтись поддержкой только систем линейки Windows NT. В качестве примера приведу исходный код
библиотеки, с помощью которой я открываю/закрываю лоток своего DVD привода (до кнопки на самом приводе мне лень тянуться :)).
library cd32;
uses
SysUtils, Classes, Types, MMSystem, ShellAPI, Math;
{$R *.res}
function Open_CD( Drive: Char; Open: Boolean ): boolean;
var
Res: MciError;
OpenParm: TMCI_Open_Parms;
Flags: DWord;
S: string;
DeviceID: Word;
begin
Result := False;
S := Drive + ':';
Flags := mci_Open_Type or mci_Open_Element;
with OpenParm do
begin
dwCallback := 0;
lpstrDeviceType := 'CDAudio';
lpstrElementName := PChar( S );
end;
Res := mciSendCommand( 0, mci_Open, Flags, Longint( @OpenParm ) );
if Res <> 0 then
Exit;
DeviceID := OpenParm.wDeviceID;
try
Res := mciSendCommand( DeviceID, MCI_SET, IfThen( Open, MCI_SET_DOOR_OPEN, MCI_SET_DOOR_CLOSED ), 0 );
if Res = 0 then
Exit;
Result := True;
finally
mciSendCommand( DeviceID, mci_Close, Flags, Longint( @OpenParm ) );
end;
end;
procedure OpenCDW( hWnd: Integer; hInstance: Integer; lpCmdLine: PChar; nCmdShow: Longint ); export; stdcall;
begin
if ParamCount = 3 then
Open_CD( ParamStr( 2 )[1], StrToBool( ParamStr( 3 ) ) );
end;
exports
OpenCDW;
begin
end.
|
Данная библиотека экспортирует 1 функцию для открытия/закрытия лотка привода, которая принимает 2 параметра
- букву этого самого привода, и команду (true - открыть, false - закрыть). Снова не забываем скопировать DLL
в "%WINDIR%\System32\" и запрограммировать пару кнопок на клавиатуре. Вот как это выглядит у меня:
На этом все, удачного вам программирования!
.: Пример к данной статье :.
|
При использовании материала - ссылка на сайт обязательна
|
|