|
Дальше
Назад
Содержание
Как пакуются тексты модулей.
Теория очень проста. Это zip с обрезанным заголовком. Сама 1С пользуется библиотекой zlibeng.dll,
которая входит в поставку самой 1С. Этим же способом пользуются и gcomp, и 1С++.
Надо сказать, что исходный код gcomp плохо пригоден для изучения приемов работы со
zlibeng.dll. Гораздо лучше для этого подходит код компоненты 1С++.
А если точнее, то код метода CModuleString::LoadModule() в той части, где происходит загрузка текста модуля
из ert файла. Этот код приведен ниже:
bool CModuleString::LoadModuleFromERT(const CString& strFileName)
{
IStoragePtr pStgRoot;
IStorage* pStorage = NULL;
HRESULT hr;
USES_CONVERSION;
hr = ::StgOpenStorage(
T2COLE(strFileName),
NULL,
STGM_READ | STGM_SHARE_DENY_WRITE,
//STGM_READ,
NULL,
0,
&pStorage);
if (FAILED(hr))
{ //ошибка
CString StrError;
StrError = "Не удалось прочитать файл: ";
StrError += strFileName;
pBkEndUI->DoMessageLine(StrError, mmBlackErr);
return false;
}
pStgRoot.Attach(pStorage, false);
IStreamPtr pStream;
IStream *pIStr = NULL;
hr = pStgRoot->OpenStream(T2COLE("MD Programm text"),0,STGM_READ | STGM_SHARE_EXCLUSIVE,0,&pIStr);
if( FAILED(hr) )
{
pBkEndUI->DoMessageLine("failed IStorage::OpenStream", mmBlackErr);
return false;
}
pStream.Attach(pIStr, false);
IStreamPtr pStreamOut;
pIStr = NULL;
if (S_OK != CreateStreamOnHGlobal(NULL, TRUE, &pIStr))
{
pBkEndUI->DoMessageLine("error in CreateStreamOnHGlobal", mmBlackErr);
return false;
}
pStreamOut.Attach(pIStr, false);
try
{
IzlibEnginePtr iLibEngine;
iLibEngine.CreateInstance(L"V75.zlibEngine");
hr = iLibEngine->pkDecompress(pStream, pStreamOut);
if (FAILED(hr))
{
pBkEndUI->DoMessageLine("error iLibEngine->pkDecompress", mmBlackErr);
return false;
}
STATSTG St;
pStreamOut->Stat(&St, STATFLAG_NONAME);
ULONG cbStreamSizeOut = St.cbSize.LowPart;
LPTSTR lpStr = GetBufferSetLength(cbStreamSizeOut);
if (lpStr == NULL)
{
pBkEndUI->DoMessageLine("lpStr == NULL", mmBlackErr);
return false;
}
LARGE_INTEGER __zero;
__zero.QuadPart = __int64(0);
if (pStreamOut->Seek(__zero, 0, NULL) != S_OK)
{
pBkEndUI->DoMessageLine("pStreamOut->Seek(__zero, 0, NULL) != S_OK", mmBlackErr);
return false;
}
ULONG pcbRead = 0;
// main job here
if (pStreamOut->Read(&lpStr[0], cbStreamSizeOut, &pcbRead) != S_OK)
{
pBkEndUI->DoMessageLine("pStreamOut->Read(&lpStr[0], cbStreamSizeOut, &pcbRead) != S_OK", mmBlackErr);
return false;
}
}
catch (_com_error& err)
{
CString str;
str.Format("V75.zlibEngine Error:%s", err.ErrorMessage());
pBkEndUI->DoMessageLine(str, mmBlackErr);
return false;
}
return true;
}
|
Однако если не хочется закладываться на наличие на компьютере установленной 1С, или просто таскать за собой
zlibeng.dll - то можно использовать и другие методы. Например скачать и посмотреть
www.mmf.newmail.ru\Zlib.zip. Пример использования
(так же любезно предоставленный MMF) приведен ниже.
unction GetErtModuleText(const FileName : string): string;
var
RootStg: IStorage;
MetaStream: IStream;
StringStream: TStringStream;
OS: TOLEStream;
begin
Result := '';
OLECheck(StgOpenStorage(StringToOLEStr(FileName),
nil, STGM_READ or STGM_DIRECT
or STGM_SHARE_EXCLUSIVE,
nil, 0, RootStg));
OLECheck(RootStg.OpenStream(StringToOLEStr('MD Programm text'),
nil, STGM_DIRECT or STGM_READ or STGM_SHARE_EXCLUSIVE, 0, MetaStream));
StringStream := TStringStream.Create('');
try
OS := TOleStream.Create(MetaStream);
try
try
OS.Position := 0;
ZDecompressStream(OS, StringStream);
finally
OS.Free;
end;
Result := StringStream.DataString;
except
end;
finally
StringStream.Free;
end;
end;
|
Дальше
Назад
Содержание
|