Встраивание манифеста приложения в исполняемый файл VB6 - PullRequest
16 голосов
/ 02 февраля 2010

Недавно я просмотрел несколько автономных утилит, написанных на VB6, чтобы убедиться, что виртуализация реестра отключена для Windows Vista и выше. Я создал отдельный файл манифеста для каждого exe-файла, соответствующим образом установил requestedExecutionLevel (некоторые из них должны изменить ключи реестра HKEY_LOCAL_MACHINE, другие нет) и протестировал их. Все они работают правильно.

У меня осталась только одна маленькая проблема. Поскольку они являются автономными утилитами, люди привыкли просто копировать их по сети и запускать их вручную. Если кто-то забудет скопировать файл манифеста, а также исполняемый файл, то исполняемый файл будет молча записывать в виртуальный раздел реестра вместо реального и вызывать проблемы, которые трудно отладить.

Очевидное решение - встроить манифест в exe как ресурс. Все статьи, которые я читал в сети, говорят о том, что вы должны встраивать ресурс так:

#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"

Это должно работать просто отлично, за исключением того, что компилятор VB всегда создает значок приложения с идентификатором ресурса = 1. Когда я попробовал приведенный выше код, Windows отказалась запускать exe, жалуясь на ошибку ресурса (я обновлю это пост с подробностями позже). Я попытался изменить идентификатор ресурса на другой номер, после чего Windows успешно запустила программу, но не распознала содержимое манифеста.

Кто-нибудь знает способ заставить встроенный манифест работать в VB6 exe, или я должен просто придерживаться внешнего файла?

ОБНОВЛЕНИЕ 1

Приведенный выше текст является полным содержимым файла .rc. Я компилирую его в файл .res, например:

"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"

И внедрить его в файл проекта VB6 следующим образом:

Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\WINDOWS\system32\stdole2.tlb#OLE Automation
Form=Main.frm
ResFile32="Resources.res"
IconForm="FMain"
Startup="FMain"
HelpFile=""
Title="Windows Vista Registry Test - VB6"
ExeName32="RegistryTestVB6.exe"
Path32=""
Command32=""
Name="RegistryTestVB6"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionComments="Windows Vista Registry Test - VB6"
VersionCompanyName=""
VersionFileDescription="Windows Vista Registry Test - VB6"
VersionLegalCopyright=""
VersionProductName="Windows Vista Registry Test - VB6"
CondComp=""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1

Когда я читаю скомпилированный exe-файл в редакторе ресурсов VS2008, он выглядит так:

RegistryTestVB6.exe
    Icon
        1 [Neutral]
    RT_MANIFEST
        1 [English (United States)]
    Version
        1 [English (United States)]

Когда я создаю точное эквивалентное тестовое приложение VB.NET в VS2008, а затем загружаю его в редактор ресурсов, оно выглядит следующим образом:

RegistryTestNET.exe
    Icon
        32512 [Neutral]
    RT_MANIFEST
        1 [Neutral]
    Version
        1 [Neutral]

ОБНОВЛЕНИЕ 2

Тестирование - .NET exe работает нормально как в Windows XP, так и в Windows 7. Однако VB6 exe выдает следующую ошибку в XP:

Это приложение не удалось запустить из-за неправильной конфигурации приложения. Переустановка приложения может решить эту проблему.

и следующая ошибка на 7:

Не удалось запустить приложение, поскольку его параллельная конфигурация неверна. Пожалуйста, смотрите журнал событий приложения или используйте инструмент командной строки sxstrace.exe для более подробной информации.

Просматривая в журнале событий, я вижу следующую запись:

Сбой генерации контекста активации для "RegistryTestVB6.exe". Ошибка в файле манифеста или политики «RegistryTestVB6.exe» в строке 10. Неверный синтаксис XML.

Само собой разумеется, что XML не является недействительным, это точно такой же файл с той же кодировкой, которую я использовал для .NET exe, и эта работает.

РАЗРЕШЕНИЕ

Компилятор VB6 действительно требует, чтобы произвольный текстовый файл, включенный в ресурс, был кратным 4 байтам. Я просто добавил пробелы в XML, пока Notepad ++ не сказал мне, что общий размер файла, включая спецификацию, был кратен 4.

Спасибо и Майклу, и Джиму за то, что они указали мне правильное направление. Жаль, я не могу отметить вас обоих как ответ!

Ответы [ 3 ]

9 голосов
/ 10 февраля 2010

Интересно, что недавно мне пришлось сделать то же самое. Следуя шагам, описанным Кристианом, я заставил его работать с первого раза. Для процветания, вот весь рабочий процесс, за которым я следовал:

  1. Создан RC файл, как описано в оригинальном вопросе
  2. Создан app.manifest, сохраняющий пробельные символы, которые ОЧЕНЬ ВАЖНЫ, чтобы это работало. Как указывалось в предыдущих ответах, размер файла должен быть кратным 4.

  3. Запустите RC.EXE, как описано в исходном вопросе, к rc для создания файла .res

  4. Отредактировал мой файл Project.VBP, добавив следующую строку вверху:

ResFile32 = "Resources.res"

  1. Встроенный EXE в стандартной среде vb6. При развертывании на компьютере с Vista или Win7 появляется экран и пользователю предлагается работать от имени администратора. При открытии файла EXE в студии я проверил ресурсы.

  2. Notepad ++ сообщает, что кодировка в моем файле app.manifest - ANSI. Он не включал метку порядка байтов в начале файла.

Если у вас все еще проблемы, дайте мне знать, и я поделюсь с вами всем, что смогу. Кроме этого, я не уверен, что вам сказать, кроме Работает на моей машине!

9 голосов
/ 02 февраля 2010

VB6 имеет причуду в том, что любой элемент ресурса должен быть точно кратным длине 4. Попробуйте заполнить файл манифеста пробелами, чтобы убедиться в этом, и посмотрите, изменит ли это поведение.

Эта странность была задокументирована в Статья Microsoft Q297112 (архив) .

Кроме того, вы можете добавить ресурс, используя IDE VB6 вместо редактирования VBP. Эффект может быть таким же, но редактор ресурсов является стандартным средством для этого.

7 голосов
/ 13 июля 2011

Использование Resource Compiler (rc.exe) решает проблему. Существует гораздо более простая опция для встраивания манифеста приложения в исполняемый файл, будь то C ++, VB6 или любой другой язык. Manifest Tool (mt.exe) был написан специально для встраивания манифестов в двоичные файлы и предоставляется бесплатно вместе с Windows SDK. Дополнительным преимуществом использования mt.exe является то, что он автоматически обрабатывает любые необходимые отступы.

Просто запустите следующую командную строку после компиляции двоичного файла. Я использовал соглашение об именах, используемое внутри компилятором Visual C ++ 2005, где имя файла манифеста содержит полное имя программы с добавлением «.intermediate.manifest».

mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1

Обновление: Я лично использую это в процессе автоматической сборки с исполняемыми файлами VB6 уже более двух лет. Он оказался настолько успешным, что мы исключили тесты совместимости ОС - специфичные для манифестов - из нашего регрессионного тестирования.

...