CustomAction log name error 0x8007007a in WiX - windows

I am currently working on a custom action in a DLL that I export to be used by a WiX installer and I recently discovered the following error in the log when I ran the installer:
<exported_name_cut_off>: Error 0x8007007a: Failed to copy CustomAction log name: <exported_name_NOT_cut_off>
As I am relatively new to Windows programming and Wix, when I noticed the DLL function name was cut off in the error message I immediately thought there must be some limit of 31 characters on exported function names in DLLs, but that apparently is not the case; it turns out that this is a limitation of WiX of which I was unaware.
So, I have two questions here:
Is there a limit on the length of an exported or imported function name in DLLs? I could not find any mention of this in the MSDN help. If it is relevant, I am coding in C++ and using Visual Studio 2010 on Windows 7 x64.
I found this, but unfortunately, there was no good answer given for why there is such a limit in WiX. Does anyone out there know why it is limited in this way? Is it still the case in WiX versions greater than 3.5.2519 (the version I am using)?

You control the name you pass to WcaInitialize; it doesn't have to be an actual function or custom action name so you can shorten it however you want. The WcaLog* functions use it to prefix your logging so it's not vital; you can even pass NULL if you want.
The limit still exists in WiX v3.6 and v3.7 beta builds.

Related

vsdraCOM causes the codebase path to point to build path

We have a couple of dlls we like to install using an msi.
In our test environment, we are using regasm -codebase to register the dlls.
As I understand from googling, this is accompliched in an msi project by setting the register property to vsdraCOM.
The problem is that when we run the installer and checks the registry, the codebase path is set to the path the file were in when building the msi.
I'm going to expand on Hans' answer and that link info, and it may be more than a comment can hold.
That reg file will contain the path to the file and the link article recommends using [TARGETDIR], which is basically wrong if the file is not being installed to the application folder. The path to your file should be written as [#file-key] in the reg file that you import. In a VS setup project the file-key will be (just an example) something like _B049230C37DE4B6787C578DCEE30252A. Open your MSI file with Orca, go to the File Table and use the file key in the File column that corresponds to your file name.
That comes from here:
http://msdn.microsoft.com/en-us/library/aa368609%28v=vs.85%29.aspx
the 7th bullet point. It resolves to the file path wherever it is installed to.
The other thing that can be done is to let Visual Studio do its incorrect thing, then go to the Registry table with Orca, find the path and put that [#file key] in it such as [#_B049230C37DE4B6787C578DCEE30252A] and people sometimes do those kinds of updates with a post build script to update the MSI.
None of these are great, but they should work and get you out of using the GAC. VS setup projects really should be using that [#file key] syntax, and it's just a silly bug I assume.
Speaking as someone who's made a full time living writing installs for 18 years, my first suggestion would be to switch to Windows Installer XML. If you insist on using .VDPROJ, I would suggest reading: Redemption of Visual Studio Deployment Projects.
The concept is you use Windows Installer XML to create a merge module and then consume that merge module with .VDPROJ. In Wix, you use Heat to harvest the DLL. It will extract the COM / Regasm metadata and author it as Registry table entries. This provides a nice clean encapsulation using authoring best practices and avoids the need to do any post build hacking of the built MSI database.

Visual Studio Project Name with containing ".com"

I work with Visual Studio 2010. I wanted to create a Project (Windows Forms Application) with the Name:
MyCompany.MyApplication.CommunicationConfiguration.Test
If I want run this project I get the error message:
Error while trying to run project: Unable to start program '...\bin\Debug\MyCompany.MyApplication.CommunicationConfiguration.Test.exe'. Access is denied.
After trying with different names and option I found out that visual studio has problem if the project name contains '.Com'.
So names like '.Com.Test' , 'HelloWorld.Communication' etc. throws exceptions. But if '.com' is the end of the name there is no problem.
My question now is, if someone knows if there is a rule which says that '.com' is not allowed in project names unless at the end of the name. I didn't found any rule in the internet and also visual studio doesn't warn by creating a project with '.com' inside the name.
Thanks in advance for your help!
Regards
rhe1980
I'm not getting a repro for this at all, Windows 7 x64. This is almost surely environmental, most likely related to your anti-malware software. Looks like it might fumble the parsing of the filename, giving up the ghost when it contains multiple dots. The .com part of the problem is somewhat significant, it is the filename extension for 16-bit non-relocatable programs back in the MS-DOS days.
Try this on another machine. You could try killing processes with Taskmgr.exe one by one to find the trouble-maker.

Can't add multiple files - limitation of Windows Installer?

I've been looking at various different ways of making an installer (see How to create a robust, minimal installer for Windows? for details), and I've run into the same thing in a couple of them (WiX and the visual studio installer creator); there doesn't seem to be a way to say "When you build the installer, include every file matching c:\somefolder\*.xml".
I can go and select *.xml and add all the files that match to the project at once, but then if I add another .xml file to my program later, I'd need to go and add that to the installer myself.
Is this a core limitation of windows installer, that I can't just tell it "sort all the XML files in this folder out and don't bother me about them"?
WiX toolset contains an utility called Heat. It can generate the WiX authoring for you based on your needs. The output can be further transformed by XSL templates (-t switch).
Hope this helps.
InstallShield also has this ( see Dynamic File Linking ) but honestly I don't like this pattern in general. It's non-deterministic in nature. I speak from 14 years of experience when I say that if a file is added or removed from my application I want to explicitly add it or remove it from my applications installer. Any magic to automate this has always bitten me in that it takes what should have been a build time error and turns it into a run time error.
My best practice is to write some automation that compares what was available to be consume against what was consumed by the installer. The two lists must match 100% or otherwise fail the build. When the build fails you must choose to either add the file to the installer or cease to archive the file to the directory. With the right tooling, it's trivial to add a file to the installer and the result is 100% accuracy of developer intent being applied to the installer.

Embedding an application manifest into a VB6 exe

I have recently gone through a bunch of standalone utility apps written in VB6 to make sure that registry virtualization is turned off for Windows Vista and above. I created a standalone manifest file for each exe, set the requestedExecutionLevel appropriately (some of them need to modify HKEY_LOCAL_MACHINE registry keys, others do not), and tested them. They all appear to work correctly.
I have only one small problem remaining. Since they are standalone utilities, people are used to just copying them around the network and running them manually. If anyone forgets to copy the manifest file as well as the exe, then the exe will silently write to the virtualized registry key instead of the real one and cause hard-to-debug problems.
The obvious solution is to embed the manifest into the exe as a resource. All the articles I have read on the net tell you to embed the resource like this:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
This should work just fine, except that the VB compiler always creates the application icon with resource ID = 1. When I tried the above code, Windows refused to run the exe, complaining about a resource error (I'll update this post with the details later). I tried changing the resource ID to another number, after which Windows ran the program successfully but did not recognise the manifest contents.
Does anyone know of a way to get an embedded manifest to work in a VB6 exe, or should I just stick with an external file?
UPDATE 1
The text given above is the whole content of the .rc file. I compile it to a .res file like this:
"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"
And embed it in the VB6 project file like this:
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
When I read the compiled exe into the VS2008 resource editor, it looks like this:
RegistryTestVB6.exe
Icon
1 [Neutral]
RT_MANIFEST
1 [English (United States)]
Version
1 [English (United States)]
When I construct an exact equivalent VB.NET test app in VS2008, then load that into the resource editor, it looks like this instead:
RegistryTestNET.exe
Icon
32512 [Neutral]
RT_MANIFEST
1 [Neutral]
Version
1 [Neutral]
UPDATE 2
Testing - the .NET exe runs fine on both Windows XP and Windows 7. However, the VB6 exe produces the following error on XP:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
and the following error on 7:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
Looking in the event log I see the following entry:
Activation context generation failed for "RegistryTestVB6.exe". Error in manifest or policy file "RegistryTestVB6.exe" on line 10. Invalid Xml syntax.
Needless to say the XML isn't invalid, it's exactly the same file with the same encoding that I used for the .NET exe, and that one works.
RESOLUTION
The VB6 compiler does indeed require that an arbitrary text file included in a resource must be an exact multiple of 4 bytes. I simply added spaces to the XML until Notepad++ told me that the total file size including BOM was a multiple of 4.
Thanks to both Michael and Jim for pointing me in the correct direction. Just a pity I can't mark you both as the answer!
Interestingly enough, I had to do the exact same thing recently. Following the steps Christian described, I got it to work the first time through. For prosperity, here is the entire workflow I followed:
Created a RC file as described in the orginal question
Created a app.manifest, preserving whitespace characters, which are VERY IMPORTANT for this to work. As stated in previous answers, the file size must be a multiple of 4.
Ran RC.EXE as described in the original question against the rc to generate the .res file
Edited my Project.VBP file to include the following line near the top:
ResFile32="Resources.res"
Built EXE in standard vb6 environment. When deployed on a vista or win7 machine, the shield shows up and the user is prompted to run as administrator. When opening the EXE file in studio, I verified the resources.
Notepad++ tells me that the encoding on my app.manifest file is ANSI. It did not include an byte order mark at the start of the file.
If you are still having troubles, let me know and I'll share whatever I can with you. Other than that, I'm not sure what to tell you other than Works on my Machine!
VB6 has a quirk in that any resource element must be an exact multiple of 4 in length. Try padding the manifest file out with spaces to ensure this, and see if that changes the behavior.
This quirk was documented in Microsoft article Q297112 (archive).
Also, you might add the resource using the VB6 IDE instead of editing the VBP. The effect may be the same, but the resource editor is the standard means for doing this.
Using the Resource Compiler (rc.exe) is going the long way around. There is a much simpler option for embedding an application manifest within an executable, whether C++ or VB6 or just about any other language. The Manifest Tool (mt.exe) was written specifically to embed manifests within binaries and is provided free of charge with the Windows SDK. The added benefit of using mt.exe is that it automatically handles any necessary padding.
Simply run the following command line after the binary has been compiled. I have used the naming convention used internally by the Visual C++ 2005 compiler, where the manifest filename contains the full program name with ".intermediate.manifest" appended.
mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1
Update: I have personally been using this in an automated build process with VB6 executables for over two years now. It has been so successful that we have eliminated OS compatibility tests - specific to manifests - from our regression testing.

VB6 install on Windows Vista as a Standard User

I have a VB6 application that needs to be installed on Windows Vista as a Standard User. Using Visual Studio 2005 I have created a setup project that will place the application in a standard user safe place or folder. I also have a dll that I want to install and register to the users application data folder. Once my windows installer is created in VS'05 I flipped the word count properties' 3rd bit using msiinfo.exe so that Vista will not prompt Admin credentials when it runs the msi. The application installs without any problems until it tries to register the dll to the users application data folder. When it reaches that point it throws an error stating that it cannot register the type library for the dll. It appears the installer does not have the authority to register a dll to the users folder. Is this correct? My understanding was that Vista only complained about standard users updating or changing items that affected all users of a machine. Any ideas? Thoughts? Suggestions?
Steve
My suggestion is, if you are able, to use regfree com / manifest files instead of registering the ocx/dll files, which as you mention is a real chore under a basic user account.
There is an excellent free app you can use to build the manifest for you as well here: http://mmm4vb6.atom5.com/
We have been using this for a few years now, with no issues.
EDIT The MMM website is down. I see here that the author was having trouble with their hosting and has provided another location to get Make My Manifest - download it here.
Instead of registering your DLL files directly, you can use RegFree COM.
This involves creating an XML manifest file for your app, so Windows will look for your DLL files in the application folder, instead of using the system registry to find them.
This means your app will run properly without your installer having to register DLLs.
These links have more info:
http://msdn.microsoft.com/en-us/magazine/cc188708.aspx
http://www.devx.com/vb/Article/32888/1954
You can use the free Make My Manifest software to create the manifest files you need:
http://mmm4vb6.atom5.com/
Generally I agree to what Joel Coehoorn says in his answer.
However, knowing how the registry works in this regard, I can make the suggestion that you try to manually register your DLL to HKEY_CURRENT_USER\SOFTWARE\Classes, basically repeating what regsvr32.exe would do to HKEY_LOCAL_MACHINE\SOFTWARE\Classes.
It's a bit of a hack, and maybe it won't work, but you can try it.
related post on MSDN: http://msdn.microsoft.com/en-us/library/ms693350.aspx (thanks to MarkJ pointing this out in the comments)
related post on vbforums.com: http://www.vbforums.com/showthread.php?t=507228
Unattended Make My Manifest is a remake of MMM that can be used to generate manifests in automated builds. It uses a script file to add depended COM components.
Registry-free COM: MakeMyManifest is well spoken of. It is an automatic tool for creating manifests for VB6 projects: I haven't tried it myself.
DirectCOM is an alternative to registry-free COM. It also has fans, again I haven't tried it.
EDIT The MMM website is down. I see here that the author was having trouble with their hosting and has provided another location to get Make My Manifest - download it here.
There is a semi-automatic technique for creating manifests for registry-free COM. You can create the manifests with Visual Studio 2008 (you can use a free version like Visual Basic Express Edition). Then make a couple of edits by hand to make the manifests suitable for use from VB6. See this section of this MSDN article for step-by-step instructions - ignore the rest of the article which is about ClickOnce.
Registering a DLL does impact all users (DLLs are registered globally) and therefore requires Admin permissions. There is no way around that.
The solution for newer programming environments is that the DLL doesn't need to be registered to be used. However, since vb6 relies on COM you're probably out of luck.

Resources