Внедрение манифеста приложения в VB6 exe
Недавно я прошел кучу автономных приложений для приложений, написанных на VB6, чтобы убедиться, что виртуализация реестра отключена для Windows Vista и выше. Я создал автономный файл манифеста для каждого exe, соответствующим образом установил requestedExecutionLevel
(некоторые из них должны изменить HKEY_LOCAL_MACHINE
ключи реестра, другие - нет) и протестировали их. Кажется, что все работают правильно.
У меня остается только одна небольшая проблема. Поскольку они являются автономными утилитами, люди привыкли просто копировать их по сети и запускать их вручную. Если кто-то забывает скопировать файл манифеста, а также exe, exe будет молча писать в виртуализированный раздел реестра вместо реального и вызывать проблемы с отладкой.
Очевидным решением является включение манифеста в exe в качестве ресурса. Все статьи, которые я прочитал в сети, расскажут вам, как включить этот ресурс:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
Это должно работать нормально, за исключением того, что компилятор VB всегда создает значок приложения с идентификатором ресурса = 1. Когда я попробовал вышеуказанный код, Windows отказалась запускать exe, жалуясь на ошибку ресурса (я обновлю это сообщение с подробностями позже). Я попытался изменить идентификатор ресурса на другой номер, после чего Windows успешно выполнила программу, но не узнала содержимое манифеста.
Кто-нибудь знает, как заставить встроенный манифест работать в exe VB6, или я должен просто придерживаться внешнего файла?
ОБНОВЛЕНИЕ 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.
Спасибо и Майклу, и Джиму за то, что он указал мне в правильном направлении. Жаль, что я не могу отметить вас обоих как ответ!
Ответы
Ответ 1
Интересно, что недавно мне пришлось сделать то же самое. Следуя шагам, описанным Кристианом, я заставил его работать с первого раза. Для процветания, вот весь рабочий процесс, за которым я следовал:
- Создан RC файл, как описано в оригинальном вопросе
-
Создан app.manifest, сохраняющий пробельные символы, которые ОЧЕНЬ ВАЖНЫ, чтобы это работало. Как указано в предыдущих ответах, размер файла должен быть кратным 4.
-
Запустите RC.EXE, как описано в исходном вопросе, к rc, чтобы сгенерировать файл .res.
- Отредактировал мой файл Project.VBP, добавив следующую строку вверху:
ResFile32 = "Resources.res"
-
Встроенный EXE в стандартной среде vb6. При развертывании на компьютере с Vista или Win7 появляется экран и пользователю предлагается работать от имени администратора. Открывая EXE файл в студии, я проверил ресурсы.
-
Notepad++ говорит мне, что кодировка в моем файле app.manifest - ANSI. Он не включал метку порядка байтов в начале файла.
Если у вас все еще есть проблемы, дайте мне знать, и я поделюсь с вами всем, что смогу. Кроме этого, я не уверен, что вам сказать, кроме работ на моей машине!
Ответ 2
У VB6 есть особенность в том, что любой элемент ресурса должен быть кратным длине 4. Попробуйте заполнить файл манифеста пробелами, чтобы убедиться в этом, и посмотрите, не изменит ли это поведение.
Эта причуда была задокументирована в статье Microsoft Q297112 (архив).
Кроме того, вы можете добавить ресурс, используя IDE VB6 вместо редактирования VBP. Эффект может быть таким же, но редактор ресурсов является стандартным средством для этого.
Ответ 3
Использование компилятора ресурсов (rc.exe) идет полным ходом. Существует гораздо более простой вариант для встраивания манифеста приложения в исполняемый файл, будь то С++ или VB6 или любой другой язык. Инструмент манифеста (mt.exe) был написан специально для встраивания манифестов в двоичные файлы и предоставляется бесплатно с помощью SDK Windows. Дополнительным преимуществом использования mt.exe является то, что он автоматически обрабатывает любые необходимые дополнения.
Просто запустите следующую командную строку после компиляции двоичного файла. Я использовал соглашение об именах, используемое внутренне компилятором Visual С++ 2005, где имя файла манифеста содержит полное имя программы с добавлением ".intermediate.manifest".
mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1
Обновление: Я лично использовал это в автоматическом процессе сборки с исполняемыми файлами VB6 уже более двух лет. Это было настолько успешным, что мы исключили тесты совместимости ОС - специфичные для манифестаций - из нашего регрессионного тестирования.