Add a manifest to control your application Vista UAC behavior


Try this on Windows XP or Vista (I don’t remember if manifests are allowed on Win2000: can someone confirm please? Thanks)


 


Start Notepad, then choose File->Open and navigate to c:\windows\system32\notepad.exe and click Open.


Hit Ctrl-F to find the text “assembly”


You’ve now found the embedded XML manifest file.


 


Try the same with VFP9.EXE, then an EXE that you have built with VFP9


 


On XP, this manifest can specify additional dependencies. For VFP9, it indicates which version of Windows Common Controls to use. For an EXE that VFP built the manifest is the same as VFPs.


 


On Vista, this manifest can further specify security requirements for an application.


For example, on Vista, applications are not allowed to write into “Program Files” or Windows directories. Similarly with the registry. Some applications will attempt to write these.


If there is no requestedExecutionLevel, then the registry and file virtualization will be turned on. The program “thinks” it’s writing to “Program Files”, but it’s really writing to C:\Users\<username>\AppData\Local\VirtualStore\Program Files. The registry redirects HKEY_LOCAL_MACHINE\Software to HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\SOFTWARE\<Application Registry Keys>


 


You can further control Vista UAC settings by running secpol.msc and navigating to Local Security Settings->Local Policies->Security Options


 


Try this on Vista: Start->Run->Cmd. Try to write a file to Program Files or Windows directories-> “Access Denied”


 


The MT.EXE tool that ships with Visual Studio or the Vista SDK can allow you to embed a manifest as a Windows Resource in an EXE file. Historically, only a Linker could build and manipulate a Windows Resource. Starting with Windows NT, the resources could be manipulated from within a program using the BeginUpdateResource  family of functions.


 


Foxpro EXE files have been built the same way for about 18 years: using a Fox resource architecture. There is a stub loader, and 0 or more sections (such as the .APP) physically appended to the file. Windows tools that manipulate the EXE file format do not pay attention to any data appended to an EXE file, so when these tools write out the result, they do not write out any additional data. With no APP, the loader merely puts up a File->Open dialog requesting an APP to run.


 


These Windows Tools use the BeginUpdateResource  family of functions, but Foxpro could not, because it still had to run on Windows 95 as well as NT


 


Starting with VFP8 (I think) VFP was able to add a generated Type Library as a Windows Resource inside a DLL, using the BeginUpdateResource functions. Now you know why this feature doesn’t work on Win 95.


 


Start Task Manager on Windows Vista, choose the Processes tab, choose View->Select Columns->Virtualization.


You will see that some processes have virtualization Enabled, Disabled, or nothing at all (depending on the privileges of the launcher) in that column.


 


Save this code as TestVista.Prg and run it


 


IF _vfp.StartMode>0     && If we’re running as an EXE


      MESSAGEBOX(“Look at Task Pane Virtualization column for TestVista”)


      RETURN


ENDIF


BUILD PROJECT TestVista FROM TestVista


BUILD EXE TestVista FROM TestVista


!/n TestVista    


RETURN


 


 


It builds an EXE that will show a MessageBox and then runs it. With the MessageBox showing, look at the Task Manager. The Virtualization is Enabled.


 


Now run this line from a VS Command prompt (Start->All Programs->Microsoft Visual Studio->Visual Studio Tools->VS Command prompt) in the same directory


 


mt -manifest TestVista.Exe.Manifest -outputresource: TestVista.exe;#1


 


Then run the TestVista.Exe. The Open File dialog shows up requesting an APP to run. Now the Virtualization is blank.


 


The sample below shows how to create a simple project hook that allows you to embed any file as a manifest. Try running it on Vista, with various values of requestedExecutionLevel.


 


For more about Vista User Account Control and manifests, see


·         Registry Virtualization


·         http://download.microsoft.com/download/5/6/a/56a0ed11-e073-42f9-932b-38acd478f46d/WindowsVistaUACDevReqs.doc


·         The Windows Vista Developer Story: Windows Vista Application Development Requirements for User Account Control (UAC)


·         Manifest Resources


·         Creating a Manifest for Your Application   


·         For another example of project hooks and modifying the VFP built EXE/DLL, see Calvin Hsia‘s WebLog : Strongly typed methods and properties


 


(Another way to see a manifest: Using Visual Studio, you can chose File->Open->File to open an Executable. The default is to open it with the Resource Editor.


There’s a little down arrow that you can choose on the File->Open dialog so that you can choose to open the file using a different tool, such as the Binary Editor.


In the resource view, you can see the Manifest file of an executable.)


 


 


 


The sample code below creates a manifest and creates a project hook that will embed a manifest file


 


CLEAR


IF _vfp.StartMode>0     && If we’re running as an EXE


      MESSAGEBOX(“Look at Task Pane Virtualization column for TestVista”)


      RETURN


ENDIF


MODIFY COMMAND PROGRAM() nowait


#if .t.


BUILD PROJECT TestVista FROM TestVista


BUILD EXE TestVista FROM TestVista


!/n TestVista    


RETURN


#endif


 


 


 


CLEAR ALL


CLEAR


IF LOWER(JUSTFNAME(PROGRAM()))!=”testvista”


      ?”This sample file must be called TestVista”


      RETURN


ENDIF


#if .f.


      To use with your project, you only need the projecthook class


#endif


 


SET SAFETY off


 


IF FILE(“TestVista.Exe”)


      DELETE FILE TestVista.Exe


ENDIF


fAddManifest=.t.


IF !FILE(“TestVista.pjx”)


      BUILD PROJECT TestVista FROM TestVista


ENDIF


MODIFY PROJECT TestVista NOWAIT


IF fAddManifest


      *cExLevel=”highestAvailable”


      cExLevel=”asInvoker”


*     cExLevel=”requireAdministrator”


      TEXT TO cXML  TEXTMERGE 


            <?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>


            <assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>


                  <assemblyIdentity version=”1.0.0.0″ processorArchitecture=”X86″ name=”CalvinsDemo” type=”win32″/>


            <trustInfo xmlns=”urn:schemas-microsoft-com:asm.v3″>


                        <security>


                              <requestedPrivileges>


                                    <requestedExecutionLevel level=”<<cExLevel>>” />


                              </requestedPrivileges>


                        </security>


                  </trustInfo>


                  <dependency>


                      <dependentAssembly>


                          <assemblyIdentity


                              type=”win32″


                              name=”Microsoft.Windows.Common-Controls”


                              version=”6.0.0.0″


                              language=”*”


                              processorArchitecture=”x86″


                              publicKeyToken=”6595b64144ccf1df”


                          />


                      </dependentAssembly>


                  </dependency>


            </assembly>


      ENDTEXT


      STRTOFILE(cXML,”TestVista.Exe.xml”)


      _vfp.ActiveProject.ProjectHook = NEWOBJECT(‘MFestPHook’)    && use projecthook to modify typelibrary if necessary


ENDIF


BUILD EXE TestVista FROM TestVista


_vfp.ActiveProject.Close


 


*Now test it. Try running it from Windows Explorer or a CMD prompt


!/n TestVista


#define RT_MANIFEST 24  && from winuser.h


#define FOX_SIG 33536


 


DEFINE CLASS MFestPHook AS ProjectHook


      PROCEDURE AfterBuild(nError)


            IF nError=0


                  ExeName=JUSTSTEM(_vfp.ActiveProject.Name)+”.Exe”


                  MFest=ExeName+”.xml”


                  IF FILE(MFest)    && if a manifest exists


                        strMFest=FILETOSTR(MFest)     && read in the manifest into a string


                        DIMENSION asec[1] && preserve 2 sections of EXE


                        nSects=0


                        h=FOPEN(ExeName)


                        fpos=FSEEK(h,0,2) && go to EOF


                        FOR i = 1 TO 20


                              FSEEK(h,fpos-14,0)


                              pmt=FREAD(h,14)


                              sig=BITAND(CTOBIN(SUBSTR(pmt,1,2),”2sr”) ,0xffff)


                              sz=CTOBIN(SUBSTR(pmt,11,4),”4sr”)


*                             ?i,sz,sig,TRANSFORM(sig,”@0x”)


                              IF sig != FOX_SIG


                                    nSects = i-1


                                    EXIT


                              ENDIF


                              FSEEK(h,fpos-sz,0)


                              DIMENSION  asec[i]


                              asec[i]=FREAD(h,sz)


                              fpos = fpos – sz


                        ENDFOR


                        FCLOSE(h)


                        DECLARE integer BeginUpdateResource IN WIN32API string , integer


                        DECLARE integer EndUpdateResource IN WIN32API integer, integer


                        DECLARE integer UpdateResource IN WIN32API integer,integer,integer,integer, string, integer


                        DECLARE Integer GetLastError IN win32api


                        h=BeginUpdateResource(ExeName,0)


                        IF h =0


                              ?”Err=”,GetLastError()


                        ELSE


                              UpdateResource(h,RT_MANIFEST,1,0×409,0,0) && del existing one, if any


                              UpdateResource(h,RT_MANIFEST,1,0×409,strMFest+CHR(0),LEN(strMFest))


                              IF EndUpdateResource(h,0)=0


                                    ?”Err=”,GetLastError()


                              ENDIF


                              h=FOPEN(ExeName,2)


                              fpos=FSEEK(h,0,2)


                              FOR i = 1 TO nSects


                                    FWRITE(h,asec[i])


                              ENDFOR


                              FCLOSE(h)


                        ENDIF


                        ?”Added manifest”


                  ENDIF


            ENDIF


ENDDEFINE


 


 235882

Comments (15)

  1. Olaf doschke says:

    AFAIK, if we’d change the manifest built into vfp9.exe to

    <requestedExecutionLevel level="requireAdministrator" />

    vfp9 would require you to elevate to adminstrator privilages, which eg would enable compiling projects that include COM servers on Vista.

    How can we invoke such elevation dialogs just when the extended priviliges are needed, eg ask for confirmation of elevation, when such a project is BUILD?

    More generally, would the vfp team consider VFP language enhancements other than fiddling around with manifests, which allow such operations?

    It would be rather disappointing if we could only have rough control for the whole application.

    Bye, Olaf.

  2. Ben Tam says:

    When TestVista.exe is built with <requestedExecutionLevel level="requireAdministrator" />, an admin elevation prompt will show as expected when we issue the following the command in the VFP Command Window:

    Run /n TestVista.exe

    However, error will be got when the same command is issued inside another VFP EXE file. What makes the difference? Actually, calling any EXEs (e.g., a setup program) which require admin elevation within a VFP EXE (rather than the VFP Command Window) will result in the same failure, no matter the EXEs being called are VFP EXEs or not.

    In order to successfully run such admin-elevation-required EXEs inside a parent VFP EXE, we have to use the following workaround. However we will get an annoying DOS window.

    cCmd=GetEnv(‘ComSpec’)+’ /c TestVista.exe’

    Run &cCmd

    If an elevation-required VFP EXE can successfully be run within a parent VFP EXE (without the annoying DOS window), it could be a solution (although not a perfect one) to the problem raised by Olaf doschke.

  3. Markus Winhard says:

    The link "Creating a Manifest for Your Application" is broken. Use this one instead: http:/msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/e84fe257-5160-4537-a8ea-e780f8774d5c.asp

    Markus Winhard

  4. Hi Calvin,

    in order to better understand what’s up with VFP 9, manifests and Vista I ran some tests using your code above. Then I began to change the code and wrote some code of my own to export the standard manifest included in a VFP 9 exe. The results are called ExportManifest.prg, ClearManifest.prg and ImportManifest.prg. I wanted to share these ‘ManifestTools’ with the community and published them on my website: http://www.bingo-ev.de/~mw368/vfp9_vista.html  I hope you don’t mind.

    Markus Winhard

  5. Apparently, the borders of some forms don’t get painted correctly on Windows Vista. When executing a

  6. Wap says:

    Buenos diaz, zolodrancci &#12483; !

    <a href= http://donne63.ovp.pl >sfondi donne</a> [link=http://donne63.ovp.pl ]sfondi donne[/link] [url=http://donne63.ovp.pl]sfondi donne[/url]

  7. Cesar Chalom says:

    Here are some of the links that I often visit regarding VFP9 SP2 and Sedna. The official Microsoft Visual…

  8. Debra Stubbs says:

    I have used you code to add a manifest to my VFP exe for several months with great success.  The size of my exe has now increased to 17+ megabytes and now I am unable to use you code to create a manifest.  It is crashing on the line asec[i]=FREAD(h,sz) with the error "function argument value, type, or count is invalid".  At the time of crash, i=1, h=37, and sz=17,779,509.  Any advice?

  9. bob bolda says:

    Curious if anyone can point me to a resource helping with the equivalent for the above functions BITAND and CTOBIN for VFP 8, not VFP 9.  

    I’m assuming this is possible.

  10. FreeAspx.it says:

    <a href="http://www.freeaspx.it&quot; target="_blank"> If you are italian you can find here code c# and VB.NET</a>

  11. Nelson says:

    I just wanted to point out two things:

    1- That I changed the version to match that of my application. It worked on Vista and Windows2003 and stopped working on XP with some "generic" message "The application cannot start because there’s an error in the configuration".

    After two days of looking around on the internet thinking that it had to do with DLL dependencies, we found out that it was the "version" format. I changed it to something like 7.2.0 and the manifest expect 4 numbers, so making it 7.2.0.0 finally made work. I’m very disappointed that Microsoft considered that worth not running the EXE.

    2- After signing the code (with authenticode) so that Vista doesn’t nag about "unknown publisher", the embedded manifest no longer worked, meaning, that it no longer considered the security in Vista to be "asInvoker". Instead, it assumed that it required Administrator privileges all the time. I read somewhere that’s the "default" for applications with no manifest. So this lead me to believe that the embedded manifest was no longer good (after signing the exe). So I had to just create the manifest and DON’T embed it with the exe, instead just send it side by side with the exe, by just changing the name to the name of the exe with .manifest at the end. For example if the exe was myapp.exe, the manifest was myapp.exe.manifest

    If you embed the manifest and then sign the exe, the manifest no longer works in Vista.

  12. There is currently a big incompatibility between MS FS X and Visual Studio. So how to create a manifest that FSX should use a specific version of mfd80.dll. The original one is replace by visual studio 2008. Any idea?

    Rudolf

  13. Paul Symons says:

    This doesn't work on large exe's. My one is over 36M and the fread fails.  But by putting the fread that reads the code contents in a loop – It can be made to work…

    As in

    j =20

    FOR i = 1 TO j

    FSEEK( m.lnHandle, m.lnPos – 14, 0 )

    lcPmt = FREAD( m.lnHandle, 14 ) &&last 14 bytes of the file

    lnSig = BITAND(CTOBIN( LEFT( m.lcPmt, 2 ), "2sr" ) ,0xffff )

    lnSize = CTOBIN( SUBSTR( m.lcPmt, 11, 4 ), "4sr" )

    *? i, lnSize, lnSig, TRANSFORM( lnSig, "@0x" )

    IF NOT m.lnSig == FOX_SIG

    lnExeSections = i – 1

    EXIT

    ENDIF

    FSEEK( m.lnHandle, m.lnPos – m.lnSize, 0 )

    *!* DIMENSION laExeSections[ i ]

    *!* laExeSections[ i ] = FREAD( m.lnHandle, m.lnSize )

    lnChunksize = m.lnSize

    DO WHILE lnChunkSize >0

    && If the exe is too big – it can't read it

    IF VARTYPE(laExeSections[ i ]) != 'L'

    i = m.i + 1

    j = m.j + 1

    ENDIF

    DIMENSION laExeSections[ i ]

    laExeSections[ i ] = FREAD( m.lnHandle, MIN(m.lnChunkSize,10000000) )

    lnChunkSize = m.lnChunksize -10000000

    ENDDO

    lnPos = m.lnPos – m.lnSize

    ENDFOR

  14. MK says:

    Latest stylish Michael Kors Handbags Sale Online, large range of top quality michael kors purses,bags & wallets at michael kors online store are hot sale,you can enjoy the lowest price michael kors outlet on MK Online Store now!