![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Add to AutoRun [D7, WinXP]
Goorus © (2004-08-27 13:09:00)Необходимо добавить ярлык в атозагрзку. В самой программе это получилось, но по завершении выдавалась ошибка. Думал это связано с неосвобождением объектов, но у интерфейсов нет метода Free, а _Release не помогал.
Попробывал написать простую демку(форма с кнопкой), работать стало ещё хуже :) Демка даже не добавляет себя в автозагрузку, хотя код не изменялся. Причина: в переменную Folder передаётся неверный путь ("С:\Docum^ "). Вот код:
procedure TForm1.Button1Click(Sender: TObject);
var List:PItemIdList;
SLink:IShellLink;
Folder:PChar;
begin
// создаём ярлык в автозагрузке
// находим папку
SHGetSpecialFolderLocation(0, CSIDL_STARTUP, List);
New(Folder);
SHGetPathFromIDList(List, Folder);
ShowMessage(Folder); // <- неверный путь
// прописываемся
SLink:=IShellLink(CreateComObject(CLSID_ShellLink));
SLink.SetArguments('/a');
SLink.SetDescription('My Prog');
SLink.SetPath( PChar(ParamStr(0)) );
(SLink as IPersistFile).Save(PWChar(WideString(Folder+'\prog.lnk')), False);
end;
jack128 (2004-08-27 15:17:00) [21]WondeRu © (27.08.04 15:03) [13]
finally
Unk := nil;
CoUninitialize; // Здесь мы Завершаем работу с СOM - значит к этому моменту все интерфейсы должны быть освобождены
end;
WondeRu (2004-08-27 15:03:00) [22]еще пример из VCLCom.pas - borland'овская библтотека:
procedure TApartmentThread.Execute;
var
msg: TMsg;
Unk: IUnknown;
begin
try
CoInitialize(nil);
try
FCreateResult := FFactory.CreateInstanceLic(FUnkOuter, nil, FIID, '', Unk);
FUnkOuter := nil;
FFactory := nil;
if FCreateResult = S_OK then
CoMarshalInterThreadInterfaceInStream(FIID, Unk, IStream(FStream));
ReleaseSemaphore(FSemaphore, 1, nil);
if FCreateResult = S_OK then
while GetMessage(msg, 0, 0, 0) do
begin
DispatchMessage(msg);
Unk._AddRef;
if Unk._Release = 1 then break;
end;
finally
Unk := nil;
CoUninitialize;
end;
except
{ No exceptions should go unhandled }
end;
end;
2DiamondShark
Так что почему Вы не присваиваете nil? Счетчик ссылок на объект данного интерфейса не обнулится (пока прога не завершится), соотвествсвенно объект останется в памяти, только указатель на него потеряется! (как смог так и сформулировал, а терминологией у меня проблемы:)
WondeRu (2004-08-27 14:46:00) [23]DiamondShark © (27.08.04 14:29) [10]
Компилятор сам следит за освобождением интерфейсов
и чего люди мучаются?
из модуля DSUtil.pas (входит в DSPack):
......................
function AddGraphToRot(Graph: IFilterGraph; out ID: integer): HRESULT;
var
Moniker: IMoniker;
ROT : IRunningObjectTable;
wsz : WideString;
begin
result := GetRunningObjectTable(0, ROT);
if (result <> S_OK) then exit;
wsz := format('FilterGraph %p pid %x',[pointer(graph),GetCurrentProcessId()]);
result := CreateItemMoniker('!', PWideChar(wsz), Moniker);
if (result <> S_OK) then exit;
result := ROT.Register(0, Graph, Moniker, ID);
Moniker := nil;
end;
.........
procedure TSysDevEnum.GetCat(catlist: TList; CatGUID: TGUID);
var
SysDevEnum : ICreateDevEnum;
EnumCat : IEnumMoniker;
Moniker : IMoniker;
Fetched : ULONG;
PropBag : IPropertyBag;
Name : olevariant;
hr : HRESULT;
i : integer;
begin
if catList.Count > 0 then
for i := 0 to (catList.Count - 1) do if assigned(catList.Items[i]) then Dispose(catList.Items[i]);
catList.Clear;
CocreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_ICreateDevEnum, SysDevEnum);
hr := SysDevEnum.CreateClassEnumerator(CatGUID, EnumCat, 0);
if (hr = S_OK) then
begin
while(EnumCat.Next(1, Moniker, @Fetched) = S_OK) do
begin
Moniker.BindToStorage(nil, nil, IID_IPropertyBag, PropBag);
new(ACategory);
PropBag.Read('FriendlyName', Name, nil);
ACategory^.FriendlyName := Name;
if (PropBag.Read('CLSID',Name,nil) = S_OK) then
ACategory^.CLSID := StringToGUID(Name)
else
ACategory^.CLSID := GUID_NULL;
catlist.Add(ACategory);
PropBag := nil;
Moniker := nil;
end;
end;
EnumCat :=nil;
SysDevEnum :=nil;
end;
.............
VMcL (2004-08-27 14:34:00) [24]>> WondeRu © (27.08.04 14:13) [9]
пожалуйста, указывайте людям на ошибки в более мягкой форме (и желательно исправляйте)!
Нет проблем. Только для этого нужно советы (а особенно неправильные) тоже давать в более мягкой форме.
DiamondShark (2004-08-27 14:29:00) [25]
> WondeRu © (27.08.04 14:13) [9]
Если убрать в конце SLink := nil; работать будет точно так же.
Компилятор сам следит за освобождением интерфейсов, точно так же как он это делает для строк, динмассивов и вариантов.
При выходе за область видимости интерфейс всегда будет освобождён.
И не надо так возмущаться.
В вопросе проблема была из-за неправильного обращения с PChar-ом. Ты же влез с советом, который совершенно не в тему, при этом ещё и не понимая смысла своего же предложения.
WondeRu (2004-08-27 14:13:00) [26]VMcL © (27.08.04 13:46) [6]
Чушь.
DiamondShark © (27.08.04 13:57) [8]
В хелп. Читать до просветления.
пожалуйста, указывайте людям на ошибки в более мягкой форме (и желательно исправляйте)!
данный вариант работает нормально
procedure TForm1.Button1Click(Sender: TObject);
var List:PItemIdList;
SLink:IShellLink;
Folder:array[0..1000] of Char;
begin
SHGetSpecialFolderLocation(0, CSIDL_STARTUP, List);
SHGetPathFromIDList(List, Folder);
ShowMessage(Folder);
SLink:=IShellLink(CreateComObject(CLSID_ShellLink));
SLink.SetArguments('/a');
SLink.SetDescription('My Prog');
SLink.SetPath( PChar(ParamStr(0)) );
(SLink as IPersistFile).Save(PWChar(WideString(Folder+'\prog.lnk')), False);
SLink := nil;
end;
DiamondShark (2004-08-27 13:57:00) [27]
> WondeRu © (27.08.04 13:51) [7]
> DiamondShark © (27.08.04 13:45) [5]
> Думаешь, поможет?
>
> поможет - не поможет - без понятия, но это обязательно!
> Освобождается интерфейс!
В хелп. Читать до просветления.
> New(Folder); - объясните мне эту строчку!
Это ко мне вопрос?
WondeRu (2004-08-27 13:51:00) [28]DiamondShark © (27.08.04 13:45) [5]
Думаешь, поможет?
поможет - не поможет - без понятия, но это обязательно! Освобождается интерфейс!
New(Folder); - объясните мне эту строчку!
VMcL (2004-08-27 13:46:00) [29]>> Goorus © (27.08.04 13:09)
> SLink:=IShellLink(CreateComObject(CLSID_ShellLink));
По-хорошему нужно писать так:
SLink := CreateComObject(CLSID_ShellLink) as IShellLink;
>> WondeRu © (27.08.04 13:40) [4]
> в конце процедуры пиши! SLink := nil
Чушь.
DiamondShark (2004-08-27 13:45:00) [30]
> WondeRu © (27.08.04 13:40) [4]
> в конце процедуры пиши!
> SLink := nil
Думаешь, поможет?
WondeRu (2004-08-27 13:40:00) [31]в конце процедуры пиши!
SLink := nil
а нафига ярлык в автозагрузку? поверь мне, легче в реестре прописать!
DiamondShark (2004-08-27 13:29:00) [32]Кстати, пидл не плохо было бы потом освобождать...
Skier (2004-08-27 13:25:00) [33]не поможет ?
http://www.delphimaster.ru/cgi-bin/faq.pl?look=1&id=988622611&n=15
DiamondShark (2004-08-27 13:25:00) [34]
> New(Folder);
Вот мне интересно, от этой строчки что ожидалось?
procedure TForm1.Button1Click(Sender: TObject);
var
List:PItemIdList;
SLink:IShellLink;
Folder:array[0..MAX_PATH] of char;