llerik Хранить пароли в базе совершенно неправильно. Более правильно получить хэш пароля ( MD5 или SHA1), и уже его хранить в базе. А в программе при проверке логина тоже вычислять хэш, и сравнивать его с тем, что хранится в базе.
» Программирование в среде .NET (ASP.NET,ADO.NET) на C#/VB.NET
dneprcomp
"Сверить" - это сравнить пароль введенный ползователем с паролем для выбранного логина, который хранится в базе.
vlary
Спасибо за совет, учту на будущее. А в данной базе, я думаю, это применять излишне, сама авторизация создается фактически как защита от дурака - не больше (как в анекдоте - "а че тут брать-то?" )
Mextrom
Флаг login.admin - это указатель на то, является ли пользователь администратором или простым смертным.
И так, на форме авторизации есть ComboBox1 для выбора имени пользователя и TextBox1 для ввода пароля, а так же кнопка. В кнопке, в методе Click должен быть примерно такой код:
Код: select password, admin
from login
where user = ComboBox1.Text
If password = TextBox1.Text Then
If admin = 1 Then
<некоторый набор действий для входа с правами админа>
Else
<некоторый набор действий для входа с правами юзера>
End If
Else
<какое-то сообщение об ошибке, думаю найду подходящую функцию>
End If
"Сверить" - это сравнить пароль введенный ползователем с паролем для выбранного логина, который хранится в базе.
vlary
Спасибо за совет, учту на будущее. А в данной базе, я думаю, это применять излишне, сама авторизация создается фактически как защита от дурака - не больше (как в анекдоте - "а че тут брать-то?" )
Mextrom
Флаг login.admin - это указатель на то, является ли пользователь администратором или простым смертным.
И так, на форме авторизации есть ComboBox1 для выбора имени пользователя и TextBox1 для ввода пароля, а так же кнопка. В кнопке, в методе Click должен быть примерно такой код:
Код: select password, admin
from login
where user = ComboBox1.Text
If password = TextBox1.Text Then
If admin = 1 Then
<некоторый набор действий для входа с правами админа>
Else
<некоторый набор действий для входа с правами юзера>
End If
Else
<какое-то сообщение об ошибке, думаю найду подходящую функцию>
End If
llerik
Невозможно получить что-либо из базы не залогинившсь. Если логин прошел, то все уже давно "сверено".
Уже ведь известно, что user admin успешно прошел авторизацию. Значит и права подтверждены. Ничего более из базы запрашивать не надо.
В том же login вместо пасс я бы сделал поле usergroup и проверял бы только его. Тогда настраивать права для <некоторых наборов действий> можно более гибко и проще. И наборов таких можно иметь большее количество.
Невозможно получить что-либо из базы не залогинившсь. Если логин прошел, то все уже давно "сверено".
Уже ведь известно, что user admin успешно прошел авторизацию. Значит и права подтверждены. Ничего более из базы запрашивать не надо.
В том же login вместо пасс я бы сделал поле usergroup и проверял бы только его. Тогда настраивать права для <некоторых наборов действий> можно более гибко и проще. И наборов таких можно иметь большее количество.
llerik
Уточните задачу (и проблему). dneprcomp говорит о строке подключения к БД и о доступе к БД вообще, я так понял, что ваша таблица login (создана вами?) в базе служит для хранания данных для авторизации в вашем приложении, в котором после аутентификации вы хотите определить, является ли пользователь приложения админом или нет. У меня просто такое чувство, что мы о разных вещах говорим. Или я что-то не так понял.
Уточните задачу (и проблему). dneprcomp говорит о строке подключения к БД и о доступе к БД вообще, я так понял, что ваша таблица login (создана вами?) в базе служит для хранания данных для авторизации в вашем приложении, в котором после аутентификации вы хотите определить, является ли пользователь приложения админом или нет. У меня просто такое чувство, что мы о разных вещах говорим. Или я что-то не так понял.
Mextrom llerik
Цитата:
Я так понял, что в FoxPro было необходимо именно таким образом проверять авторизацию по каким-то присущим FoxPro свойствам.
Используя SQL Server, можно бы и отойти от устаревшей логики.
Цитата:
Дали задание перевести БД с FoxPro на SQL-server
Я так понял, что в FoxPro было необходимо именно таким образом проверять авторизацию по каким-то присущим FoxPro свойствам.
Используя SQL Server, можно бы и отойти от устаревшей логики.
Mextrom
Вы верно поняли, это аутентификация именно в приложении. Откровенно говоря как-то не задумывался о защите подключения к самой базе.
Опишу ситуацию.
База данных была изначально сделана с целью учета дипломных проектов, т.е. кто пишет, кто руководит и т.п.
Защищать саму БД вне приложения, с помощью которого будет происходить работа с базой я не вижу большого смысла, да и само приложение, откровенно говоря, тоже, но авторизация в оригинале была, а моя задача перенести с фокса на скуль... Вотъ.
З.Ы. Базу на фоксе делал студент в качестве дипломного проекта, но делал, судя по качеству, в последний момент, так что почему авторизация такая - это риторический вопрос.
dneprcomp
Если БД будет работать на удаленном сервере и доступ к ней будет осуществляться через общественную локальную сеть (компьютерный класс в институте), то аутентификация будет осуществляется на этапе подключения к БД, т.е. пользователи и их пароли настраиваются на этапе установки и настройки sql-server. Верно?
Тогда получается, что какая-либо авторизация в приложении не имеет смысла вообще?
В связи с тем, что, чую, не придется делать авторизацию, а вопрос о запуске sql-запроса при нажатии на кнопку останется без ответа, задам его отдельно.
Запрос может быть написан непосредственно в процедуре Click или там должен быть только запуск запроса по его имени, а сам запрос должен быть уже в БД?
И, если можно, небольшой пример, чтобы синтаксис понять.
Вы верно поняли, это аутентификация именно в приложении. Откровенно говоря как-то не задумывался о защите подключения к самой базе.
Опишу ситуацию.
База данных была изначально сделана с целью учета дипломных проектов, т.е. кто пишет, кто руководит и т.п.
Защищать саму БД вне приложения, с помощью которого будет происходить работа с базой я не вижу большого смысла, да и само приложение, откровенно говоря, тоже, но авторизация в оригинале была, а моя задача перенести с фокса на скуль... Вотъ.
З.Ы. Базу на фоксе делал студент в качестве дипломного проекта, но делал, судя по качеству, в последний момент, так что почему авторизация такая - это риторический вопрос.
dneprcomp
Если БД будет работать на удаленном сервере и доступ к ней будет осуществляться через общественную локальную сеть (компьютерный класс в институте), то аутентификация будет осуществляется на этапе подключения к БД, т.е. пользователи и их пароли настраиваются на этапе установки и настройки sql-server. Верно?
Тогда получается, что какая-либо авторизация в приложении не имеет смысла вообще?
В связи с тем, что, чую, не придется делать авторизацию, а вопрос о запуске sql-запроса при нажатии на кнопку останется без ответа, задам его отдельно.
Запрос может быть написан непосредственно в процедуре Click или там должен быть только запуск запроса по его имени, а сам запрос должен быть уже в БД?
И, если можно, небольшой пример, чтобы синтаксис понять.
llerik
Раз я понял правильно, тогда запрос в базу можно сделать так (пишу на шарпе, в vb должно быть аналогично, пуcть кто-нибудь переведет/подправит):
Код: string connectionString = "Server=[адрес_сервера]; Database=[имя_базы]; User=[имя_пользователя_БД]; Password=[пароль];"; // строка для подключения к БД
string query = "select password, admin from login where user = [имя_юзверя]"; // текст запроса
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.CommandType = CommandType.Text;
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
string pass = (string)reader["password"];
bool isAdmin = ((int)reader["admin"] == 1);
}
}
}
}
Раз я понял правильно, тогда запрос в базу можно сделать так (пишу на шарпе, в vb должно быть аналогично, пуcть кто-нибудь переведет/подправит):
Код: string connectionString = "Server=[адрес_сервера]; Database=[имя_базы]; User=[имя_пользователя_БД]; Password=[пароль];"; // строка для подключения к БД
string query = "select password, admin from login where user = [имя_юзверя]"; // текст запроса
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.CommandType = CommandType.Text;
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
string pass = (string)reader["password"];
bool isAdmin = ((int)reader["admin"] == 1);
}
}
}
}
Mextrom
Чего-то я видимо просто не понимаю. Зачем нужна вообще повторная проверка, если мы все равно обращаемся к базе?
llerik
?
Цитата:
В том же table login вместо полей login/пасс я бы сделал одно поле usergroup и получал бы по запросу только его. Хранил бы значение usergroup на все время работы програмы и сверял бы по возникновению необходимости.
Добавлено:
llerik
В принципе, при желании можно наверное сделать connection к базе без логина вообще или с единственным hard coded логином. Потом действительно передавать user log/pass
Но запросом
"select count(1) from login where password = [password] and admin = [admin]
Если вернуло 1, значит админ. Но все это как-то через то самое место
Чего-то я видимо просто не понимаю. Зачем нужна вообще повторная проверка, если мы все равно обращаемся к базе?
llerik
?
Цитата:
пользователи и их пароли настраиваются на этапе установки и настройки sql-server. Верно?По моему, именно так. Юзеров все равно в базе создавать придется. Авторизация в приложении имеет смысел если это самое приложение не работает с базой. Двойная авторизация в данном случае близка к паранойе
Тогда получается, что какая-либо авторизация в приложении не имеет смысла вообще?
В том же table login вместо полей login/пасс я бы сделал одно поле usergroup и получал бы по запросу только его. Хранил бы значение usergroup на все время работы програмы и сверял бы по возникновению необходимости.
Добавлено:
llerik
В принципе, при желании можно наверное сделать connection к базе без логина вообще или с единственным hard coded логином. Потом действительно передавать user log/pass
Но запросом
"select count(1) from login where password = [password] and admin = [admin]
Если вернуло 1, значит админ. Но все это как-то через то самое место
dneprcomp
Цитата:
Допустим, я хочу сделать сайт. На сайте у меня есть авторизация. Данные об зарегистрироваашихся пользователях (логин, хэш пароля, права, какие-то настроки и т.д.) я храню в базе. Соответственно, чтобы авторизовать пользователя на моем сайте, я должен запросить из базы его данные (например, его роль - админ/не админ и т.д.). Для подключения к базе мне нужна строка подключения, в которой я должен указать настройки подключения.
Цитата:
Для доступа к базе нужен всего один пользователь на все приложение или можно вообще использовать виндовую авторизацию (IntegratedSecurity=true). А в приложении пользователей может быть много. Что касается ролей пользователей в приложении, то все определяется логикой этого приложения (в данном случае видимо хватает админа и обычного пользователя).
Цитата:
Почему? Пользователь, созданный в базе, наделяется правами для работы с самой БД, т.е. чтение, изменения данных, создание таблиц и т.д. Пользователю приложения нужны совсем другие права, например, он должен иметь право заходить только на определенные страницы.
Цитата:
Чего-то я видимо просто не понимаю. Зачем нужна вообще повторная проверка, если мы все равно обращаемся к базе?
Допустим, я хочу сделать сайт. На сайте у меня есть авторизация. Данные об зарегистрироваашихся пользователях (логин, хэш пароля, права, какие-то настроки и т.д.) я храню в базе. Соответственно, чтобы авторизовать пользователя на моем сайте, я должен запросить из базы его данные (например, его роль - админ/не админ и т.д.). Для подключения к базе мне нужна строка подключения, в которой я должен указать настройки подключения.
Цитата:
Юзеров все равно в базе создавать придется.
Для доступа к базе нужен всего один пользователь на все приложение или можно вообще использовать виндовую авторизацию (IntegratedSecurity=true). А в приложении пользователей может быть много. Что касается ролей пользователей в приложении, то все определяется логикой этого приложения (в данном случае видимо хватает админа и обычного пользователя).
Цитата:
Авторизация в приложении имеет смысел если это самое приложение не работает с базой.
Почему? Пользователь, созданный в базе, наделяется правами для работы с самой БД, т.е. чтение, изменения данных, создание таблиц и т.д. Пользователю приложения нужны совсем другие права, например, он должен иметь право заходить только на определенные страницы.
Mextrom
Каким образом связаны сайт и приложение?
1.Если это веб приложение, то сайт уже провел авторизацию. Хотя, если рассматривать веб-приложение как часть функций сайта, а не являющеся сайтом... Тогда да, согласен. Сценарий имеет право быть.
PS.Что-то мне подсказывает, что llerik не имел в виду работу с веб-приложением
2.Если это stand alone программа ведущая любой диалог с базой, то пусть сама и запрашивает базу. Зачем нужен сайт-посредник?
3.Если это stand alone программа НЕ ведущая любой диалог с базой, то можно с натяжкой согласиться с предложенной схемой. Хотя не понятно, каким образом сайт будет передавать данные этой програме.
Накрутить конечно можно все. Но целесообразной логики я все-таки не вижу. Да и передавать login/pass туда и обратно опять же не вижу нужды.(см. дополнение в предыдущем сообщении)
Каким образом связаны сайт и приложение?
1.Если это веб приложение, то сайт уже провел авторизацию. Хотя, если рассматривать веб-приложение как часть функций сайта, а не являющеся сайтом... Тогда да, согласен. Сценарий имеет право быть.
PS.Что-то мне подсказывает, что llerik не имел в виду работу с веб-приложением
2.Если это stand alone программа ведущая любой диалог с базой, то пусть сама и запрашивает базу. Зачем нужен сайт-посредник?
3.Если это stand alone программа НЕ ведущая любой диалог с базой, то можно с натяжкой согласиться с предложенной схемой. Хотя не понятно, каким образом сайт будет передавать данные этой програме.
Накрутить конечно можно все. Но целесообразной логики я все-таки не вижу. Да и передавать login/pass туда и обратно опять же не вижу нужды.(см. дополнение в предыдущем сообщении)
dneprcomp
Да, я имел виду веб-приложение. ASP.NET, например. Если обобщать, то это может быть любое многопользовательское приложение.
Цитата:
Передавать все равно придется, другое дело, что в открытом виде хранить и передавать пароли смысла нет, но об этом уже упоминалось здесь.
Да, я имел виду веб-приложение. ASP.NET, например. Если обобщать, то это может быть любое многопользовательское приложение.
Цитата:
Да и передавать login/pass туда и обратно опять же не вижу нужды.
Передавать все равно придется, другое дело, что в открытом виде хранить и передавать пароли смысла нет, но об этом уже упоминалось здесь.
Здравствуйте!
Помогите разобраться с переписанием функции Delphi на C#
Delphi:
Код: function HexToStr(Sou: string): string;
Var t:integer; sl:string;
begin
With TStringList.Create Do
try
Text:=StringReplace(Sou,#32,#13#10,[rfReplaceAll]);
sl:='';
For t:= 0 to Count - 1 Do
sl:=sl+Chr(StrToInt('$' + Strings[t]));
Result:=sl;
finally
Free;
end;
end;
Помогите разобраться с переписанием функции Delphi на C#
Delphi:
Код: function HexToStr(Sou: string): string;
Var t:integer; sl:string;
begin
With TStringList.Create Do
try
Text:=StringReplace(Sou,#32,#13#10,[rfReplaceAll]);
sl:='';
For t:= 0 to Count - 1 Do
sl:=sl+Chr(StrToInt('$' + Strings[t]));
Result:=sl;
finally
Free;
end;
end;
Прошу подсказать на какие свободные или коммерческие компоненты стоит обратить внимание для создания приложения с пользовательским интерфейсом наподобии Microsoft Visio.
ZBEP
Цитата:
А что хоть эта функция должна делать? Если десятичную строку преобразовывать в шестнадцатиричную, то код ниже. Хотя судя по коду StrToHex это далеко не так.
Вариант простой:
Код: private static string HexToString(string hexString)
{
try
{
ulong tmp = Convert.ToUInt64(hexString, 16);
return tmp.ToString();
}
catch (FormatException ex)
{
// Неверный формат исходной строки
}
catch (OverflowException ex)
{
// Переполнение
}
return "Ошибка";
}
Цитата:
В общем помогите с HexToStr разобраться.
А что хоть эта функция должна делать? Если десятичную строку преобразовывать в шестнадцатиричную, то код ниже. Хотя судя по коду StrToHex это далеко не так.
Вариант простой:
Код: private static string HexToString(string hexString)
{
try
{
ulong tmp = Convert.ToUInt64(hexString, 16);
return tmp.ToString();
}
catch (FormatException ex)
{
// Неверный формат исходной строки
}
catch (OverflowException ex)
{
// Переполнение
}
return "Ошибка";
}
Omicron_Persey_8, спасибо, но что-то не так работает..
Надо к примеру строку "abcd" преобразовать в Hex, т.е. "61 62 63 64" и обратно.
Вот посоветовали сделать так:
Код: static private string HexToStr(string sIn)
{
var sb = new System.Text.StringBuilder();
string[] sArr = sIn.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
sb.Append(string.Join("", sArr.Select(b => ((char)(Convert.ToSByte(b, 16))).ToString()).ToArray()));
return sb.ToString();
}
static private string StrToHex(String sIn)
{
var sb = new System.Text.StringBuilder();
sb.Append(string.Join(" ", sIn.ToCharArray().Select(b => ((int)b).ToString("X")).ToArray()));
return sb.ToString();
}
Надо к примеру строку "abcd" преобразовать в Hex, т.е. "61 62 63 64" и обратно.
Вот посоветовали сделать так:
Код: static private string HexToStr(string sIn)
{
var sb = new System.Text.StringBuilder();
string[] sArr = sIn.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
sb.Append(string.Join("", sArr.Select(b => ((char)(Convert.ToSByte(b, 16))).ToString()).ToArray()));
return sb.ToString();
}
static private string StrToHex(String sIn)
{
var sb = new System.Text.StringBuilder();
sb.Append(string.Join(" ", sIn.ToCharArray().Select(b => ((int)b).ToString("X")).ToArray()));
return sb.ToString();
}
karakurt2
Вот такого добра мне не попадалось.
Вот такого добра мне не попадалось.
Ребяте у мну простой ВЦФ в службе. Но я немогу предупредить клиента что он в отрубе. На комаду убить службу я получаю событие OnStop и делаю так как в коде. Но видимо когда я гашу srvHost - клиенты не успевают ничего получить. Хотелось бы гамотно - хост без ошибок обычно и клиент без ошибок. Кто знает куда копать?
Код: [no] protected override void OnStop()
{
if (srvHost != null)
{
LogWriter.Write("Завершаем хостинг сервиса", LogLevel.Warning);
try
{
wcfService.NotifyAllClients(Notification.System, NotCode.CloseConnect);
/// Тут!!!
srvHost.Close();
LogWriter.Write("Успешно", LogLevel.Report);
}
catch (Exception e)
{
LogWriter.Write("Ошибка при завершении хостинга сервиса: " + e.Message, LogLevel.Error);
}
}
}[/no]
Код: [no] protected override void OnStop()
{
if (srvHost != null)
{
LogWriter.Write("Завершаем хостинг сервиса", LogLevel.Warning);
try
{
wcfService.NotifyAllClients(Notification.System, NotCode.CloseConnect);
/// Тут!!!
srvHost.Close();
LogWriter.Write("Успешно", LogLevel.Report);
}
catch (Exception e)
{
LogWriter.Write("Ошибка при завершении хостинга сервиса: " + e.Message, LogLevel.Error);
}
}
}[/no]
Чет я совсем запутался с этим Encoding XD
Как мне сделать так, что бы StrToHex делала из "Слово" -> "D1 EB EE E2 EE", а не "421 43B 43E 432 43E" или "D0 A1 D0 BB D0 BE D0 B2 D0 BE" ?
Как мне сделать так, что бы StrToHex делала из "Слово" -> "D1 EB EE E2 EE", а не "421 43B 43E 432 43E" или "D0 A1 D0 BB D0 BE D0 B2 D0 BE" ?
ZBEP
Сам метод StrToHex я бы написал так
Код: private string StringToHex (string str)
{
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < str.Length; i++)
{
sb.AppendFormat("{0:x} ", (uint)str[i]);
}
sb.Remove (sb.Length - 1, 1);
return sb.ToString ();
}
Сам метод StrToHex я бы написал так
Код: private string StringToHex (string str)
{
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < str.Length; i++)
{
sb.AppendFormat("{0:x} ", (uint)str[i]);
}
sb.Remove (sb.Length - 1, 1);
return sb.ToString ();
}
Mextrom, из фала гружу в richTextBox.
Добавлено:
Вот мне подсказали как правильно переводить русские символы из String в Hex:
Код:
static private string StrToHexRus(string sIn)
{
// Create a UTF-8 encoding.
UTF8Encoding utf8 = new UTF8Encoding();
Byte[] encodedBytes = utf8.GetBytes( sIn );
encodedBytes = UTF8Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(1251), encodedBytes);
string sResult = "";
foreach (Byte b in encodedBytes)
{
sResult += b > 15 ? String.Format("{0:X} ", b) : String.Format("0{0:X} ", b);
}
return sResult;
}
Добавлено:
Вот мне подсказали как правильно переводить русские символы из String в Hex:
Код:
static private string StrToHexRus(string sIn)
{
// Create a UTF-8 encoding.
UTF8Encoding utf8 = new UTF8Encoding();
Byte[] encodedBytes = utf8.GetBytes( sIn );
encodedBytes = UTF8Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(1251), encodedBytes);
string sResult = "";
foreach (Byte b in encodedBytes)
{
sResult += b > 15 ? String.Format("{0:X} ", b) : String.Format("0{0:X} ", b);
}
return sResult;
}
ZBEP
Для случая кодировки cp-1251 могу предложить такой вариант (маленькая тестовая программа):
Код: using System;
using System.Globalization;
using System.Text;
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
string source = Console.ReadLine();
string hexStr = StringToHex(source);
Console.WriteLine(hexStr);
Console.WriteLine(HexToString(hexStr));
}
private static string StringToHex(string str)
{
byte[] bytes = Encoding.GetEncoding(1251).GetBytes(str);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.AppendFormat("{0:x} ", bytes[i]);
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
private static string HexToString(string hexStr)
{
char[] separators = new char[1] { ' ' };
string[] chars = hexStr.Split(separators, StringSplitOptions.RemoveEmptyEntries);
byte[] bytes = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++)
{
bytes[i] = byte.Parse(chars[i], NumberStyles.AllowHexSpecifier);
}
return Encoding.GetEncoding(1251).GetString(bytes);
}
}
}
Для случая кодировки cp-1251 могу предложить такой вариант (маленькая тестовая программа):
Код: using System;
using System.Globalization;
using System.Text;
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
string source = Console.ReadLine();
string hexStr = StringToHex(source);
Console.WriteLine(hexStr);
Console.WriteLine(HexToString(hexStr));
}
private static string StringToHex(string str)
{
byte[] bytes = Encoding.GetEncoding(1251).GetBytes(str);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.AppendFormat("{0:x} ", bytes[i]);
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
private static string HexToString(string hexStr)
{
char[] separators = new char[1] { ' ' };
string[] chars = hexStr.Split(separators, StringSplitOptions.RemoveEmptyEntries);
byte[] bytes = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++)
{
bytes[i] = byte.Parse(chars[i], NumberStyles.AllowHexSpecifier);
}
return Encoding.GetEncoding(1251).GetString(bytes);
}
}
}
Mextrom, Спасибо!
Работает как надо
Работает как надо
Здравствуйте. Самостоятельно изучаю С# и столкнулся с проблемой если попытаться реализовать измеритель пробега мыши, то как сделать так чтобы с переходом на другую форму измеритель продолжал работать. Как получить координаты мыши я знаю. Мне сказали что нужно подключить какой-то ХУК, Dll, как это делается
Заранее Спасибо
Заранее Спасибо
leonidSDF
Посмотрите здесь
Посмотрите здесь
Здравствуйте, спасибо за ссылку. Пришлось помучится, но все таки реализовал. Но есть несколько неприятных моментов, если кто может, подскажите. Первое заменил я у Тауба Console на messageBox, чтобы программа выдавала код нажатой кнопки и поставил кнопку, чтобы можно было хук отключать. MessageBox вылезает сразу, после этого все виснет примерно секунд на пять, програмама не отвечает, потом очухивается и снова продолжает работать. и так каждый раз при срабатывание хука на всех платформах и компьютерах. Ниже приведен код файла Form1.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static IntPtr _hookID = IntPtr.Zero;
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) { }
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
Process pr = Process.GetCurrentProcess();
ProcessModule prM = pr.MainModule;
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(prM.ModuleName), 0);
}
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
MessageBox.Show(((Keys)vkCode).ToString());
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private void button1_Click(object sender, EventArgs e)
{
if (this.button1.Text == "SetHook")
{
this.button1.Text = "UnHook";
_hookID = SetHook(_proc);
}
else
{
this.button1.Text = "SetHook";
UnhookWindowsHookEx(_hookID);
}
}
}
}
есть еще проблемка. в коде есть функция private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam), в которую вставил messageBox. решил вместо него поставить метку и менять текст по событию . ОДНАКО, указать this.label1.text я не могу потому как это является static методом. Выкрутился я так, создал static переменную, присваиваю ей vkCode и по таймеру ее обновляю (кстати при таком способе не тормозит). А как сделать так, чтобы оно обновлялось по приходу этого события, что это за проблемка со static методами и this.label, может есть способ указать грамотно ссылку к объекту label.text и этого будет достаточно.
Заранее благодарю.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static IntPtr _hookID = IntPtr.Zero;
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) { }
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
Process pr = Process.GetCurrentProcess();
ProcessModule prM = pr.MainModule;
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(prM.ModuleName), 0);
}
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
MessageBox.Show(((Keys)vkCode).ToString());
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private void button1_Click(object sender, EventArgs e)
{
if (this.button1.Text == "SetHook")
{
this.button1.Text = "UnHook";
_hookID = SetHook(_proc);
}
else
{
this.button1.Text = "SetHook";
UnhookWindowsHookEx(_hookID);
}
}
}
}
есть еще проблемка. в коде есть функция private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam), в которую вставил messageBox. решил вместо него поставить метку и менять текст по событию . ОДНАКО, указать this.label1.text я не могу потому как это является static методом. Выкрутился я так, создал static переменную, присваиваю ей vkCode и по таймеру ее обновляю (кстати при таком способе не тормозит). А как сделать так, чтобы оно обновлялось по приходу этого события, что это за проблемка со static методами и this.label, может есть способ указать грамотно ссылку к объекту label.text и этого будет достаточно.
Заранее благодарю.
Здравствуйте. В моей программе присутствует функция открытия файла через диалоговое окно. Пробую запускать программу в XP и ниже не работает вываливается необрабатываемое исключение (обработку исключений я еще не реализовывал). А в чем собственно подвох? Visual Studio 2008. C#.
leonidSDF
Цитата:
Так же, как и с vkCode. Делаешь статическую переменную для label, инициализируешь ее в конструкторе после InitializeComponent, и в HookCallback она у тебя будет доступна.
giv5dot26
Без кода трудно сказать.
Цитата:
А как сделать так, чтобы оно обновлялось по приходу этого события, что это за проблемка со static методами и this.label, может есть способ указать грамотно ссылку к объекту label.text и этого будет достаточно.
Так же, как и с vkCode. Делаешь статическую переменную для label, инициализируешь ее в конструкторе после InitializeComponent, и в HookCallback она у тебя будет доступна.
giv5dot26
Без кода трудно сказать.
Вот пожалуйста:
Код:
private void Tabs_DblClick(object sender, System.EventArgs e)
{
byte x;
int y;
DlgOpenFile.ShowDialog();
y = DlgOpenFile.FileNames.Count() - 1;
if (!FileOpened)
return;
if (y >= 18)
{
MessageBox.Show("Нужно выбрать не более 18 файлов!");
FileOpened = false;
return;
}
for (x = 0; x <= y; x++)
{
Foo(DlgOpenFile.FileNames[x]);
}
}
Код:
private void Tabs_DblClick(object sender, System.EventArgs e)
{
byte x;
int y;
DlgOpenFile.ShowDialog();
y = DlgOpenFile.FileNames.Count() - 1;
if (!FileOpened)
return;
if (y >= 18)
{
MessageBox.Show("Нужно выбрать не более 18 файлов!");
FileOpened = false;
return;
}
for (x = 0; x <= y; x++)
{
Foo(DlgOpenFile.FileNames[x]);
}
}
Здравствуйте.
----
OMICRON PERSEY - 8 Так же, как и с vkCode. Делаешь статическую переменную для label, инициализируешь ее в конструкторе после InitializeComponent, и в HookCallback она у тебя будет доступна.
----
Можно уточнить. Создать статическую переменную ни чего не стоит. У меня уже есть программа которая работает примерно вот так:
Form1 ...{ static int aaa = vkСode, static bool flag = true}...
timer ...{if (flag) this.label.text = aaa }...
И на этом все. то есть, я создал статическую переменную, запустил таймер и каждые 20 мс ищу флаг нажатия клавиши, если такой есть я сбрасываю флаг и печатаю переменную. С такой реализацией, правда не слишком изяшной, даже если программа находится не в фокусе, она успешно отображает буквы с клавиатуры. НО ЭТО ЧЕРЕЗ ПОСРЕДНИКА!!!
Я предполагаю, что вы советуете как то создать статическую переменную которая сможет указывать напрямую на объект label.text.
С официального сайта Microsoft в поддержку Net, там сказано создайте ссылку на объект, так как это статический метод, что то типа {Form tempForm = new FormActivForm}. или типа того, однако такая реализация позволяет отлавливать данные с клавиатуры только если форма находится в фокусе, во всех других случаях она дает исключение. ТАК ЧТО ЭТОТ ВАРИАНТ ТОЖЕ НЕ ПОДХОДИТ!!!
Если не сложно и я правильно понял вашу мысль, бросьте от руки хотя бы пару строк кода, чтобы была ясна мысль как делается такая переменная, и с помощью нее вызывается объект this.label.text.
Спасибо.
----
OMICRON PERSEY - 8 Так же, как и с vkCode. Делаешь статическую переменную для label, инициализируешь ее в конструкторе после InitializeComponent, и в HookCallback она у тебя будет доступна.
----
Можно уточнить. Создать статическую переменную ни чего не стоит. У меня уже есть программа которая работает примерно вот так:
Form1 ...{ static int aaa = vkСode, static bool flag = true}...
timer ...{if (flag) this.label.text = aaa }...
И на этом все. то есть, я создал статическую переменную, запустил таймер и каждые 20 мс ищу флаг нажатия клавиши, если такой есть я сбрасываю флаг и печатаю переменную. С такой реализацией, правда не слишком изяшной, даже если программа находится не в фокусе, она успешно отображает буквы с клавиатуры. НО ЭТО ЧЕРЕЗ ПОСРЕДНИКА!!!
Я предполагаю, что вы советуете как то создать статическую переменную которая сможет указывать напрямую на объект label.text.
С официального сайта Microsoft в поддержку Net, там сказано создайте ссылку на объект, так как это статический метод, что то типа {Form tempForm = new FormActivForm}. или типа того, однако такая реализация позволяет отлавливать данные с клавиатуры только если форма находится в фокусе, во всех других случаях она дает исключение. ТАК ЧТО ЭТОТ ВАРИАНТ ТОЖЕ НЕ ПОДХОДИТ!!!
Если не сложно и я правильно понял вашу мысль, бросьте от руки хотя бы пару строк кода, чтобы была ясна мысль как делается такая переменная, и с помощью нее вызывается объект this.label.text.
Спасибо.
Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
Предыдущая тема: Как удалить/добавить/отключить/включить устройство?
Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.