Ideally yes. Or, you can just reset the variables locally before CoUninitialize() is called (don't forget to clear the PROPVARIANT, too), eg:
var
Store: IPropertyStore;
v: PropVariant;
InitHr: HResult;
begin
if OpenDialog1.Execute then
begin
InitHr := CoInitialize(nil);
if FAILED(InitHr) and (InitHr <> RPC_E_CHANGED_MODE) then OleError(InitHr);
try
OleCheck(SHGetPropertyStoreFromParsingName(PChar(OpenDialog1.FileName), nil, GPS_READWRITE, IPropertyStore, store));
try
OleCheck(store.GetValue(PKEY_Music_AlbumTitle, v));
try
if v.vt = VT_EMPTY then
Showmessage('Album Title not found')
else
Showmessage(v.bstrVal);
finally
PropVariantClear(v); // <-- add this
end;
finally
store := nil; // <-- calls Release()
end;
finally
if SUCCEEDED(InitHr) then CoUninitialize;
end;
end;
end;
However, Co(Un)Initialize() really should not be called more than 1 time per thread. For instance, in this case, they should be called at program startup/cleanup only, eg:
private
InitHr: HResult;
procedure TMainForm.FormCreate(Sender: TObject);
begin
InitHr := CoInitialize(nil);
if FAILED(InitHr) and (InitHr <> RPC_E_CHANGED_MODE) then OleError(InitHr);
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
if SUCCEEDED(InitHr) then CoUninitialize;
end;
// the above would be better handled by moving Co(Uninitialize)() into
// the main DPR directly, before TApplication is initialized, and after
// TApplication.Run() is finished, respectively...
...
procedure TMainForm.DoSomething;
var
Store: IPropertyStore;
v: PropVariant;
begin
if OpenDialog1.Execute then
begin
OleCheck(SHGetPropertyStoreFromParsingName(PChar(openDialog1.FileName), nil, GPS_READWRITE, IPropertyStore, store));
OleCheck(store.GetValue(PKEY_Music_AlbumTitle, v));
try
if v.vt = VT_EMPTY then
Showmessage('Album Title not found')
else
Showmessage(v.bstrVal);
finally
PropVariantClear(v); // <-- still needed
end;
end;
end;