Notes for PowerBuilder developers
Notes for PowerBuilder developers using registration-free .Net objects
Programs created by PowerBuilder have proprietary module format on disk. The .EXE file consists of bootstrap code followed by PB code. This format is not understood by Windows resource manipulation functions and, consequently, cannot be modified by Windows API. The effect is that Manifest Maker cannot embed manifest in a PowerBuilder program. To be more precise, the Windows API will succeed, Manifest Maker will suceed, but the resulting .EXE module can no longer be run.
Currently PowerBuilder offers to create win32 side-by-side manifest and embed it in the program. Choosing this option will cause any external manifest to be ignored by Windows and, in effect, will prevent you from using win32 registration-free functionality. See the "Assembly search order" section of the how-to page.
Until PowerBuilder gives an option to choose assembly manifests to be referenced in the embedded manifest, you need to choose an option which does not embed a manifest in the executable. If there is an external manifest, you will need to ignore it. Use Manifest Maker's "Resource Manifest Viewer" (sxs32vrm.exe) to examine your executable. If the viewer shows a manifest file, you need to change PowerBuilder options. You need to make sure that Resource Manifest Viewer displays this message: WARNING: This file does not contain any embedded manifest resources.
For example PowerBuilder 12.5 gives a choice of embedded, external or no manifest:
It is not intuitive that a manifest is created in every case and both "Embedded manifest" and "No manifest" options actually embed a manifest in the program. You must use "External manifest" option. Execution level and UI access options do not matter, this manifest will be overwritten later anyway.
Depending on whether you need a complex win32 side-by-side assembly or not, you may need to create a "Private Assembly" Manifest Maker project or you may be able to just embed assembly manifests in your .Net and COM DLLs. Since the complex assembly is more likely a corporate deployment scenario, let us assume that you have one or more .Net and COM DLLs which you are building and you can modify them as needed. In this case add to your build process a call to sxs32cmd.exe to create and embed win32 assembly manifests in each DLL. Look for "Manifest Maker Visual Studio Integration" for your version of Visual Studio in this how-to page then click the link to the example at the bottom of the page. Your command line will look something like this:
sxs32cmd "/clr:$(TargetPath)" /k:1 /o:Auto
If you are not building your DLL in Visual Studio, you will have the DLL path instead of the "$(TargetPath) macro.
Next you need to create a Manifest Maker "Application Manifest" project for your executable. Note that the correct choice is made in the "Processor" drop-down. Make sure that the "Embed Manifest as Resource" checkbox in Build Options is cleared. Choose all appropriate options including trust and privileges and supported operating systems. Add "Microsoft.Windows.Common-Controls" shared assembly reference, if you are using Common Controls. Now add references to private assemblies defined in your DLLs. Build the manifest using Manifest Maker GUI to verify that all works fine. Keep the original project and save a copy using File / Save for Integration menu option.
Here is an example project with a single .Net DLL and a single program. Note that the DLL has a red "1" on it indicating that the DLL includes an embedded #1 manifest and that the program has no manifest indicator.
For the sake of this illustration let us also select a Windows trust level in Manifest Maker project properties:
The corresponding "manifest.sxs32mm" project file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <sxs32mm version="360" required="360"> <project name="" version="0.0.0.0" type="win32" token="" language="" build="application" processor="x86" target="C:\Projects\example" expanded="C:\Projects\example" clrv="Auto" access="1" relx="."> <assembly xirm="0"> <file path="C:\Projects\example\clrDLL.dll" relx=".\clrDLL.dll" rely=".\clrDLL.dll"/> <file path="C:\Projects\example\pbprogram.exe" relx=".\pbprogram.exe" rely=".\pbprogram.exe"/> <shared name="Microsoft.Windows.Common-Controls" vers="6.0.10586.0" type="win32" toke="6595b64144ccf1df" proc="x86"/> </assembly> <build xirm="0"> </build> </project> </sxs32mm>When you save this project as "saved-project-file.sxs32mm" using the "File / Save for integration" menu option you get:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <sxs32mm version="360" required="360"> <project clrv="Auto" access="1"> <assembly xirm="0"> <file path="C:\Projects\example\clrDLL.dll" relx=".\clrDLL.dll" rely="clrDLL.dll"/> <file path="C:\Projects\example\pbprogram.exe" relx=".\pbprogram.exe" rely="pbprogram.exe"/> <shared name="Microsoft.Windows.Common-Controls" vers="6.0.10586.0" type="win32" toke="6595b64144ccf1df" proc="x86"/> </assembly> <build xirm="0"> </build> </project> </sxs32mm>
Now create a build step which will run sxs32cmd using the saved copy as the project file. Use Visual Studio Integration examples as a guide. Your command line will look something like this:
sxs32cmd /exe:pbprogram.exe /n:0 /k:0 saved-project-file.sxs32mm
/n:0 option. This is required to prevent manifest embedding
which is the default for the
See Command Line Manifest Builder for option details. The
manifest file pbprogram.exe.manifest will now contain:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <assemblyIdentity name="pbprogram.exe" version="0.0.0.0" type="win32" processorArchitecture="x86"/> <description>Built with: Side-by-Side Manifest Maker, Command Line (5.0.5315.0) (x64)</description> <description>Copyright: (c) Maze Solutions LLC. All rights reserved.</description> <description>Licensee: Maze Solutions LLC, www.manifestmaker.com</description> <description>License: 5 users license</description> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> <dependency> <dependentAssembly> <assemblyIdentity name="Microsoft.Windows.Common-Controls" version="6.0.10586.0" type="win32" publicKeyToken="6595b64144ccf1df" processorArchitecture="x86"/> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity name="clrDLL" version="18.104.22.168" type="win32"/> </dependentAssembly> </dependency> </assembly>
Now perform the last sanity check; open the example PowerBuilder program with Manifest Viewer to verify that there is no embedded manifest:
The sequence of build events in the final build process:
- Build your DLL
sxs32cmd /clrcommand to create and embed win32 side-by-side manifest
- Build another DLL as needed...
- Build your executable with no embedded manifest
sxs32cmd /exeto create external manifest for your executable
The resulting target folder will contain each of the DLLs, the executable and the *.exe.manifest file.