![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запуск команды runas [D4, D6, WinXP]
olevacho © (2004-10-30 15:56:00)Есть в винде ХР команда runas. Она позволяет находясь в системе под одним пользователем выполнить другую команду или внешнюю программу от имени другого пользователя. Проблемма в том что нужно после запуска вводить пароль другого пользователя вручную. Можно ли сделать прогу на дельфе так чтоб пароль другого пользователя передавался из моей проге команде runas автоматически. А может в дельфе есть какой-нить аналог команды runas ?
GuAV (2004-10-31 13:35:00) [1]Игорь Шевченко © (31.10.04 13:05) [39]
Честно говоря, страдаю идиосинкразией к слову absolute, не знаю, почему, но факт :)
Ну можно ещё объявить как переменную и установить в initialization или сделать функцией :)
Или вообще так
type
WIN_BOOL = type DWORD;
const
WIN_FALSE = 0;
WIN_TRUE = 1;
GuAV (2004-10-31 13:15:00) [2]VMcL © (31.10.04 10:35) [38]
Относительно безопасно передачи в качестве параметра, но совершенно не допустимо сравнение или другие операции с константой TRUE. Гарантирована только константа FALSE и правильная работа с ней во всех случаях. В других случаях если требуется работа с TRUE оно должно заменяться на arg <> FALSE
В принципе, сравнивать в С я смысла вообще не вижу.
В Delphi есть смысл сравнивать, например хэндлы или указатели, чтобы избежать необходимости приведения типов. Ptr <> nil почему-то лучше чем BOOL(Ptr).
Но сравнивают действительно не Handle = 1, а Handle <> 0, иначе просто не работает.
Что интересно, в отличии от С, в Delphi есть защита от этих граблей
см. код в [18].
В С различается логическое и побитное and or not. Почему же нет такого xor и сравения ?
Игорь Шевченко (2004-10-31 13:05:00) [3]GuAV © (31.10.04 02:10) [30]
> Работает так:
>
> const
> WIN_TRUE_VALUE: LongWord = 1;
> var
> WIN_TRUE: BOOL absolute WIN_TRUE_VALUE;
Честно говоря, страдаю идиосинкразией к слову absolute, не знаю, почему, но факт :)
VMcL (2004-10-31 10:35:00) [4]>> Defunct © (31.10.04 02:23) [32]
> хотя в общем с вами согласен, проверка с 1 это клиника.
>> GuAV © (31.10.04 02:33) [33]
> Вы представляете, с этим и я согласен.
Вот и я пытался объяснить alena.svt © здесь:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1099061998&n=0
Только как горохом об стенку. Дело вкуса, дело вкуса, блин. За такие вкусы надо к стенке и расстреливать... из водяного пистолета :-)
Anatoly Podgoretsky (2004-10-31 09:57:00) [5]VMcL © (31.10.04 02:07) [29]
Вот на подобных методах работы пострадало много программистов, когда сменилось определение контстанты TRUE в языке или возвращаемое значение из ОС.
Это пример опасного программирования, который выявляется не в момент написания, а иногда только несколько лет спустя.
Относительно безопасно передачи в качестве параметра, но совершенно не допустимо сравнение или другие операции с константой TRUE. Гарантирована только константа FALSE и правильная работа с ней во всех случаях. В других случаях если требуется работа с TRUE оно должно заменяться на arg <> FALSE
GuAV (2004-10-31 02:49:00) [6]Defunct © (31.10.04 2:36) [35]
мда.. не зря некоторые говорили масдай..
Ну я же перезапустил. Поэтому Хэндлы другие и сами окна другие. А значение ISWindow видимо больше чем просто BOOL, имеет физический смысл :-))
Defunct (2004-10-31 02:36:00) [7]> Позакрывал немонго окон. Ещё раз результат.
мда.. не зря некоторые говорили масдай..
GuAV (2004-10-31 02:34:00) [8]GuAV © (31.10.04 2:33) [33]
Позакрывал немонго окон. Ещё раз результат.
Забыл сказать, что перезапустил - иначе хэндлы бы не поменялись, конечно.
GuAV (2004-10-31 02:33:00) [9]
> скорее там будет 255 не так ли?
Не так.
function IsWindowInt(hWnd: HWND): Integer; stdcall; external
user32 name 'IsWindow';
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Add(Format('%.8X %.8X', [Handle, IsWindowInt(Handle)]));
with Application do
Memo1.Lines.Add(Format('%.8X %.8X', [Handle, IsWindowInt(Handle)]));
end;
Результат.
00000A48 82198090
00000A20 82198EF8
Позакрывал немонго окон. Ещё раз результат.
0000046C 821999A4
00000770 82199C7C
И где-то так же для других функций.
> хотя в общем с вами согласен, проверка с 1 это клиника.
Вы представляете, с этим и я согласен.
Defunct (2004-10-31 02:23:00) [10]GuAV © (31.10.04 02:13) [31]
> Такое значение может вернуть BOOL-функция в 9х.
Я очень в этом сомневаюсь.
скорее там будет 255 не так ли?
У вас w98 скажите често, что возвращает функция?
VMcL © (31.10.04 02:07) [29]
чаще видел:
if a != 0 {...}
if a == 0 {...}
реже видел:
if a != 1 {...}
хотя в общем с вами согласен, проверка с 1 это клиника.
GuAV (2004-10-31 02:13:00) [11]VMcL © (31.10.04 2:07) [29]
Неудачный пример. Byte(256) = 0.
Именно об этом речь. Такое значение может вернуть BOOL-функция в 9х. DWord не равен 0, а байт - равен.
> С точностью до наоборот: 4, 2 и 1.
угу.
> Кхм. Обычно пишут что-то типа "этот оператор не
> выполнится". А то как-то непонятно, кто выпадет,
> откуда и куда
ок. "этот оператор не выполнится".
GuAV (2004-10-31 02:10:00) [12]
>const WIN_TRUE=BOOL(1);
Идея хорошая но не работает !
Работает так:
const
WIN_TRUE_VALUE: LongWord = 1;
var
WIN_TRUE: BOOL absolute WIN_TRUE_VALUE;
VMcL (2004-10-31 02:07:00) [13]>> GuAV © (31.10.04 01:39) [28]
> Для совместимости с другими языками введены ещё три логических типа - LongBool, WordBool и ByteBool. Размер их соответственно 1, 2 и 4 байта.
С точностью до наоборот: 4, 2 и 1.
> function b3: boolean;
Неудачный пример. Byte(256) = 0.
> // выпадет
Кхм. Обычно пишут что-то типа "этот оператор не выполнится". А то как-то непонятно, кто выпадет, откуда и куда.
>> Игорь Шевченко © (30.10.04 23:24) [20]
> Причем, внутри этих функций (Enumxxxx) стоит сравнение с именно с единицей, а не с неким "ненулевым значением".
Вот яркий пример людей, который вместо
if (a) {...}
и
if (!a) {...}
пишут
if (a == TRUE) {...}
и
if (a == FALSE) {...}
соотвественно.
Повбывав бы :-)
GuAV (2004-10-31 01:39:00) [14]Какая разница между Boolean и BOOL ?
Как использовать внешние функции, работающие с логическими значениями ?
В Borland Delphi основным логическим типом является boolean. Длина его 1 байт. Если этот байт равен единице, то значение логического типа - истина, если нулю, то ложь. Другие значения являются недопустимыми, и их использование может привести к неожиданным результатам. Пример неожиданных результатов:
function b1: boolean;
asm
mov eax, 4 //недопустимое значение
end;
function b2: boolean;
asm
mov eax, 1
end;
function b3: boolean;
asm
mov eax, 256 //недопустимое значение
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if b1 = b2 then showmessage('b1 = b2'); // не выпадет
if b3 then showmessage('b3'); // не выпадет
end;
Для совместимости с другими языками введены ещё три логических типа - LongBool, WordBool и ByteBool. Размер их соответственно 1, 2 и 4 байта. LongBool значение - истинна если LongWord не равен 0 и ложь если равен 0. Для WordBool и ByteBool соответсвенно Word и Byte.
Для типа LongBool приведенный выше пример работает, т.к. значения 4 (не допустимые для Boolean) и 256 (не соответсвующее разрядности Boolean) будут истиной для LongBool
function b1: LongBool;
asm
mov eax, 4
end;
function b2: LongBool;
asm
mov eax, 1
end;
function b3: LongBool;
asm
mov eax, 256
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if b1 = b2 then showmessage('b1 = b2'); // выпадет
if b3 then showmessage('b3'); // выпадет
end;
Константам True типов LongBool, WordBool и ByteBool соответствуют значения $FFFFFFFF, $FFFF и $FF.
Логические операции над Boolean эффективнее, чем над XxxxBool, т.к. сводятся к соответствующим побитным операциям. Кроме того Boolean упорядочен, ord(False)=0 ord(True)=1. Поэтому предпочтительно использовать Boolean.
В 32-разрядной Windows принят 32-разрядный логический тип, с ненулевым значением в качестве истины. Причём в win9x это ненулевое значение произвольно, однако, начиная с Windows 2000, оно строго равно единице.
В Delphi этот тип объявлен какtype BOOL = LongBool;
Так, следующее объявление было бы не корректно в 9х:
function IsWindow(hWnd: HWND): Boolean; stdcall; external
user32 name 'IsWindow';
Однако, оно корректно в 2000, поскольку при приведении LongWord к Byte отсекаются страшие байты, и следовательно если LongWord был равен 1, то и Byte будет равен 1, аналогично c 0.
Для всех ОС подойдёт такое объявление:
function IsWindow(hWnd: HWND): BOOL; stdcall; external
user32 name 'IsWindow';
Для функций появившихся в Windows 2000 оба объявления корректны. Поэтому, исходя из того, что Boolean предпочтительнее в Delphi их лучше объявлять с результатом Boolean.
Теперь о передаче параметров. Как сообщалось ранее, в Windows принят 32-разрядный логический тип, с ненулевым значением в качестве истины. Т.е. вроде бы любое значение не равное нулю должно сойти за истину. Однако есть функции, которые требуют, чтобы в качестве "любого значение не равное нулю" передавалась единица. Т. е. константа True = $FFFFFFFF не подойдёт. Использовать Boolean тоже не следует, т.к. старшие 3 байта будут не определены и при попытке передать False может передаваться значение отличное от 0, что тоже может иметь негативные последствия. Решение - или объявлять этот параметр как DWORD или использовать константу
const WIN_TRUE=BOOL(1);
GuAV (2004-10-31 00:17:00) [15]
> function BoolToWin(B: ByteBool): BOOL; overload;
> function BoolToWin(B: WordBool): BOOL; overload;
С этими точнее как я написал не получится - надо так:
function BoolToWin(B: ByteBool): BOOL; overload;
asm
TEST AL, AL
SETNZ AL
AND EAX, 00000001h
end;
function BoolToWin(B: WordBool): BOOL; overload;
asm
TEST AX, AX
SETNZ AL
AND EAX, 00000001h
end;
GuAV (2004-10-31 00:09:00) [16]или не, во как:
function BoolToWin(B: Boolean): BOOL; overload;
asm
AND EAX, 00000001h
end;
function BoolToWin(B: ByteBool): BOOL; overload;
asm
TEST AL, AL
JZ @@Exit
MOV EAX, 00000001h
@@Exit:
end;
function BoolToWin(B: WordBool): BOOL; overload;
asm
TEST AX, AX
JZ @@Exit
MOV EAX, 00000001h
@@Exit:
end;
function BoolToWin(B: LongBool): BOOL; overload;
asm
TEST EAX, EAX
JZ @@Exit
MOV EAX, 00000001h
@@Exit:
end;
GuAV (2004-10-31 00:04:00) [17]Игорь Шевченко © (30.10.04 23:50) [22]
WinBOOL
const
WIN_NT_FALSE = BOOL(0);
WIN_NT_TRUE = BOOL(1);
function BoolToWin(B: Boolean): BOOL; overload;
asm
AND EAX, 00000001h
end;
{
function BoolToWin(B: BOOL): BOOL; overload;
asm
TEST EAX, EAX
SETNZ AL
AND EAX, 00000001h
end;
}
function BoolToWin(B: BOOL): BOOL; overload;
asm
TEST EAX, EAX
JZ @@Exit
MOV EAX, 00000001h
@@Exit:
end;
Игорь Шевченко (2004-10-31 00:00:00) [18]GuAV © (30.10.04 23:55) [23]
Есть функции, которые честно сравнивают результат с нулем, и все от него отличное, интерпретируют как True, для примера, EnumWindows, EnumWindowStations и т.п.
GuAV (2004-10-30 23:55:00) [19]Игорь Шевченко © (30.10.04 23:24) [20]
Интересно, а есть ли вообще функции winapi, принимающие BOOL(-1) ?
И смотрите как пишут:
как результат - zero или nonzero
как пеарметр - TRUE или FALSE.
Игорь Шевченко (2004-10-30 23:50:00) [20]GuAV © (30.10.04 23:34) [21]
> Опять же рекомендую не Boolean, а
> const BOOL_TRUE = BOOL(1);
Я нашел альтернативный выход, но идея хорошая. Только я бы назвал не BOOL_TRUE, а MsBOOL или WinBOOL :)
> И может выводы из этой ветки поместить например в FAQ ?
Да, поддерживаю.