Форум: "Начинающим";
Текущий архив: 2007.12.16;
Скачать: [xml.tar.bz2];
ВнизПолучение названий продуктов запущенных приложений Найти похожие ветки
← →
Hint (2007-11-17 11:14) [0]Использую вот такой код:
function GetVersionString(pData: pointer; nDataSize: DWORD; sKey: string): string;
type
V_LIST = record
w1: DWORD;
w2: DWORD;
w3: PCHAR;
end;
LANGANDCODEPAGE = record
wLang, wCodePage: word;
end;
PLANGANDCODEPAGE = ^LANGANDCODEPAGE;
var
buf: PCHAR;
dwDummy: DWORD;
p: PLANGANDCODEPAGE;
c: array[0..1024] of char;
vl: V_LIST;
begin
VerQueryValue(pData, "\VarFileInfo\Translation", pointer(p), dwDummy);
vl.w1 := p^.wLang;
vl.w2 := p^.wCodePage;
vl.w3 := @sKey[1];
wvsprintf(c, "\StringFileInfo\%.4x%.4x\%s", PCHAR(@vl));
if VerQueryValue(pData, c, pointer(buf), dwDummy) then result := buf else result := "";
end;
function GetProductName(sFilename: string): string;
var
nDataSize, dwDummy: DWORD;
pData: pointer;
begin
result:="";
if sFilename="" then exit;
nDataSize := GetFileVersionInfoSize(@sFilename[1], dwDummy);
if nDataSize <= 0 then exit;
GetMem(pData, nDataSize);
GetFileVersionInfo(@sFilename[1], 0, nDataSize, pData);
result := GetVersionString(pData, nDataSize, "ProductName");
FreeMem(pData);
end;
procedure TfrmMain.FormCreate(Sender: TObject);
var
i,j:integer;
ph: THandle;
mh: hmodule;
procs: array[0..$FFF] of dword;
count, cm: cardinal;
ModName: array[0..max_path] of char;
s1,s2: string;
begin
if EnumProcesses(@procs, sizeof(procs), count) then
begin
j:=count div 4 - 1;
for i:=0 to j do
begin
ph:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, procs[i]);
if ph > 0 then
begin
EnumProcessModules(ph, @mh, 4, cm);
GetModuleFileNameEx(ph, mh, ModName, sizeof(ModName));
s1:=string(ModName);
s2:=GetProductName(s1); //!!!
m.Lines.Add(ExtractFileName(s1)+" - "+s2);
CloseHandle(ph);
end;
end;
end;
end;
И почему-то у некоторых пользователей при вызове GetProductName происходит ошибка. Код находится в DLL, ошибка возникает у 1 человека из 50. Как найти причину - не знаю. Вроде все правильно, но что-то не так...
← →
Kolan © (2007-11-17 11:15) [1]> И почему-то у некоторых пользователей при вызове GetProductName
> происходит ошибка
Так и написано «Ошибка»?
← →
Hint (2007-11-17 11:24) [2]Поток, содержащий вызов GetProductName завершает свою работу
← →
Leonid Troyanovsky © (2007-11-17 12:08) [3]
> Hint (17.11.07 11:24) [2]
Боже мой, потоки, формы - и все свалено в dll.
Странно, что у 49 что-то работало.
--
Regards, LVT.
← →
Hint (2007-11-17 13:23) [4]Формы там нет. Код скопирован из DLL в пустой проект с формой, чтобы было проще искать ошибку.
А DLL и поток - почему бы и нет? DLL при инициализации создает один служебный поток.
← →
Leonid Troyanovsky © (2007-11-17 13:31) [5]
> Hint (17.11.07 13:23) [4]
> А DLL и поток - почему бы и нет? DLL при инициализации создает
> один служебный поток.
Показывай, как. И где завершается.
Впрочем, можно и почитать
http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-11-17 13:34) [6]
> Hint (17.11.07 13:23) [4]
> Формы там нет. Код скопирован из DLL в пустой проект с формой,
> чтобы было проще искать ошибку.
Какой код работал в dll?
--
Regards, LVT.
← →
Hint (2007-11-17 13:45) [7]В DLL:
begin
createthread(nil, 0, @MyThread, nil, 0, mt);
end;procedure MyThread;
begin
while true do
begin
sleep(10000);
search;
end;
end;
Где search - тоже самое, что и FormCreate, только вместо m.Lines.Add:if s2="xxx" then ...
← →
Leonid Troyanovsky © (2007-11-17 13:59) [8]
> Hint (17.11.07 13:45) [7]
Во-первых, BeginThread.
Во-вторых, while true do - в печь.
В-третьих, тема then .. - не раскрыта.
В-четвертых, как осуществлялась инициализация,
не показано.
--
Regards, LVT.
← →
Hint (2007-11-17 14:09) [9]Спасибо, от CreateThread уже избавился (почитал справку в чем разница).
---
Мне нужно, чтобы код выполнялся пока приложение не будет закрыто, поэтому и использую "while true do". Есть какие-то другие варианты?
---
If then - не важно. Что-то вроде:if s2="xxx" then MessageBox(0,"xxx","xxx",0);
В любом случае этот код уже не выполняется, т.к. на GetProductName все прерывается.
---
Какая инициализация?
← →
Leonid Troyanovsky © (2007-11-17 14:20) [10]
> Hint (17.11.07 14:09) [9]
> Мне нужно, чтобы код выполнялся пока приложение не будет
> закрыто, поэтому и использую "while true do". Есть какие-
> то другие варианты?
Например,
while (WaitForSingleObject(hEventStop, 10000) <> WAIT_OBJECT_0) do
Но, это лишь как пример, т.к. у WFSO есть и другие возвращаемые значения.
> If then - не важно.
Отнюдь.
> В любом случае этот код уже не выполняется, т.к. на GetProductName
> все прерывается.
Что значит "все прерывается"?
> Какая инициализация?
> DLL при инициализации создает один служебный поток.
--
Regards, LVT.
← →
Hint (2007-11-17 14:29) [11]Под инициализацией я ивел ввиду код между begin и end (BeginThread).
while true do
begin
sleep(x);
if EnumProcesses(@procs, sizeof(procs), count) then
begin
j:=count div 4 - 1;
for i:=0 to j do
begin
ph:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, procs[i]);
if ph > 0 then
begin
EnumProcessModules(ph, @mh, 4, cm);
GetModuleFileNameEx(ph, mh, ModName, sizeof(ModName));
s1:=string(ModName);
ATL("before");
s2:=GetProductName(s1); //!!!
ATL("after");
m.Lines.Add(ExtractFileName(s1)+" - "+s2);
CloseHandle(ph);
end;
end;
end;
ATL("done");
end;
Если добавить в код вызов функции ATL, которая записывает передаваемую ей строку в текстовый файл, то у большинства пользователей в файле будут каждые N секунд появляться строки:
> before
> after
> ...
> before
> after
> done
> ...
А у одного человека из 50ти:
> before
> after
> ...
> before
Приложение будет работать дальше, а записи в файл уже не произойдет. При чем "done" не появится ни разу.
← →
Leonid Troyanovsky © (2007-11-17 14:45) [12]
> Hint (17.11.07 14:29) [11]
> Под инициализацией я ивел ввиду код между begin и end (BeginThread).
Это место весьма проблемное, я ж ссылку приводил.
Лучше взять за правило делать экспортируемые процедуры Init/Fin
> Приложение будет работать дальше, а записи в файл уже не
> произойдет.
Например, в том самом потоке возникло исключение, убившее поток
(немного странно, что не процесс). Т.е., то, что в then .. - важно,
скорее всего, неправильная/отсутствующая синхронизация.
--
Regards, LVT.
← →
Hint (2007-11-17 15:15) [13]Дело в том, что исключение происходит в GetProductName, т.к. "after" в логе уже не появляется.
ATL("before");
s2:=GetProductName(s1); //!!!
ATL("after");
if s2="xxx" then ...
В принципе я об этом написал в первом сообщении, только код упростил, чтобы не было лишних вопросов про поток и DLL =) Т.к. думаю в данном случае это не важно (есть before, нет after, значит ошибка в GetProductName). Но эта функция у меня, как и у многих других, работает нормально в данном контексте (совместно с EnumProcesses). Получается при запросе информации о каком-то приложении происходит ошибка. Что это может быть за приложение? Функция GetProductName написана не корректна или я что-то не принимаю в учет?
← →
Leonid Troyanovsky © (2007-11-17 15:27) [14]
> Hint (17.11.07 15:15) [13]
> это может быть за приложение? Функция GetProductName написана
> не корректна или я что-то не принимаю в учет?
Мне многое не нравится в оном написании, начиная со String,
который, видимо, попадает куда-то в exe.
А так - MSDN - в зубы, Win32Check - в руки - и вперед.
И никаких 1024.
--
Regards, LVT.
← →
Hint (2007-11-17 15:33) [15]Вот нашел сообщение с похожей проблемой:
http://t3stament01.name/08/visnet-getfileversioninfosize/
← →
Leonid Troyanovsky © (2007-11-17 15:35) [16]
> Hint (17.11.07 15:15) [13]
> чтобы не было лишних вопросов про поток и DLL
Зря думаешь, что лишние.
Хотя, с другой стороны, как еще было узнать о
некорректности GetProductName :)
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-11-17 16:03) [17]
> Hint (17.11.07 15:33) [15]
> Вот нашел сообщение с похожей проблемой:
Вот, это понятней.
Т.е., исключения нет, а есть бесконечное ожидание.
Вполне возможно, что некоторые файлы локированы,
а GetFileVersionInfo требуется мапить файл для
определения размера ресурса.
Хотя, не очень понятно, почему это exe, а не длл.
Может, на той машине какой-нить терминальный сервис?
Ну, и для того, чтобы избежать подобного, нужно
перед GetFileVersionInfo убедится можно ли файл читать.
Неохота лезть в MSDN, но, кажется, что там д.б. об этом.
--
Regards, LVT.
← →
Hint (2007-11-17 16:08) [18]Кстати, может быть проблема из-за запущенного RAdmin?
← →
Leonid Troyanovsky © (2007-11-17 16:13) [19]
> Hint (17.11.07 16:08) [18]
> Кстати, может быть проблема из-за запущенного RAdmin?
Не знаю, у меня его нет.
Надо логировать имена процессов и смотреть.
Да и какая разница? Если файл локирован на чтение,
то никакой GetFileVersionInfo не получить.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-11-17 16:26) [20]
> Leonid Troyanovsky © (17.11.07 16:03) [17]
> Ну, и для того, чтобы избежать подобного, нужно
> перед GetFileVersionInfo убедится можно ли файл читать.
Не, не так.
Нужно открыть на чтение, а после GFVI - закрыть(хендл).
Если на открытие - отлуп, то ресурсы не прочитать.
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.16;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.063 c