Персональная страница Федора Езеева
Главная
Download
Ссылки
MS SQL
Обмен данными
Новости
Статьи
О себе
Крупные разделы...
Коллективная разработка
1С++, OOP, XP
FuncTest
FAQ
Структура 1cv7.md
Дальше Назад Содержание

Как пакуются тексты модулей.

Теория очень проста. Это 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;

Дальше Назад Содержание
Rambler's Top100 1C:TOP-100

© 1998-2004 Fedor Ezeev.

Last updated: 2005-09-28