<p dir="auto">From <a href="http://discuss.rust-lang.org/t/prioritizing-windows-issues/319/2?u=brson" rel="nofollow">http://discuss.rust-lang.org/t/prioritizing-windows-issues/319/2?u=brson</a></p>
<p dir="auto">It appears that on permission managed windows machines (eg. win7) rust generated binaries require administrator privileges to run, even for trivial case applications like println!("Hello World"); these permissions must be accepted ("Run this as administrator") every time the application is launched.</p>
<p dir="auto">I have no idea how this is typically managed in win programming, but having to accept "run this as administrator" every time you run cargo test or launch a binary is really tedious.</p>
<p dir="auto">Currently Rust has no support for adding manifests to Windows executables (.exe and .dll) despite some previous failed attempts (see <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="24874632" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/11207" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/11207/hovercard" href="https://github.com/rust-lang/rust/issues/11207">rust-lang/rust#11207</a>).</p>
<p dir="auto">Application manifests are essentially just an XML resource which is embedded in the executable and is read by Windows to establish how the executable should be run and which DLLs it depends on.  There are also other types of manifests which follow the same basic schema but have slightly different purposes, e.g. you can publish configuration files to install on the system which specify that a particular version of a DLL installed is backwards compatible and should be used in place of a whole range of previous version numbers.</p>
<p dir="auto">Manifests may be useful for several reasons in Rust:</p>
<ul dir="auto">
<li>Allows easily viewable version numbers and descriptive text on an .exe or .dll</li>
<li>Can specify which version of a system (or any other) .dll your application should use, thus avoiding DLL hell - notable alternative use case for this is to ensure version 6 or above of Microsoft Common Controls which will enable XP styles of window controls in 32-bit applications; this particular one probably ought to be automatically included for apps requiring COMCTL32.dll since without you'll get some ugly ancient looking GUIs.</li>
<li>Ability to specify UAC privilege level required for your application and avoid Windows determining this heuristically (temporarily solved for test runs using an environment variable in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="55111162" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/21496" data-hovercard-type="pull_request" data-hovercard-url="/rust-lang/rust/pull/21496/hovercard" href="https://github.com/rust-lang/rust/pull/21496">rust-lang/rust#21496</a>)</li>
<li>Allows use of code signing for distributed binaries (also needs a certificate).  This is a must for writing Windows drivers nowadays.</li>
<li>Enable use of certain features/modes such as (super) high-res scrolling, DPI awareness, printer driver isolation...</li>
</ul>
<p dir="auto">There is another significant feature which should NOT be used by default, which is that you can specify which OS version behaviours are supported by your application, which effectively requests certain APIs to behave differently.  The reason this is bad is that it is impossible to know if anything that plugs in to your app (e.g. shell extensions, which come in through e.g. common file dialog) also supports these behaviours, so it is generally not safe to turn them on.  Even so, for flexibility it would be good to allow users to explicitly request these behaviours.</p>
<p dir="auto">I believe that the scope and format of these application manifests is sufficiently limited (particularly parts most relevant to Rust) that the Rust ecosystem ought to have the ability to generate these by itself with the help of Rust language attributes to specify particular items/settings to go into the manifest.  Having some sane approach to version numbering (which ties into Cargo somehow) would be massively beneficial and avoid all sorts of problems with incompatible binaries.  The version numbers for manifests are required to have four parts 0-65535 (without exception) which Microsoft expliclty labels as major.minor.build.revision in the documentation, and changes in the last two are not to break backwards compatibility, which would generally be done by incrementing the major version rather than minor.  <a href="https://msdn.microsoft.com/en-gb/library/ms973869.aspx" rel="nofollow">This</a> I find to be a good link on the motivations behind the versioning system on Windows and there might be no reason why Rust couldn't implement such automatic revision number stepping on top of a similar version attribute.</p>
<p dir="auto">Likely people will want to override whatever manifest Rust provides (or disable it completely) and this should be catered for.  However, it could potentially be useful to have an option for some sort of hybrid approach where Rust can change certain fields such as version number from an existing manifest file.  N.B. application manifests are always called filename.exe.manifest or filename.dll.manifest so they could always simply be detected from the filesystem rather than specified on the command line or in an attribute (though being able to specify an alternative manifest path via an attribute may be another very useful feature).</p>
<p dir="auto">As a demonstration of most of the things I've said, and to demonstrate how simple the XML is, I have prepared an example, which in this case would normally be called helloworld.exe.manifest:</p>
<div class="highlight highlight-text-xml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;assembly xmlns=&quot;urn:schemas-microsoft-com:asm.v1&quot;
          manifestVersion=&quot;1.0&quot;&gt;
  &lt;assemblyIdentity type=&quot;win32&quot;
                    name=&quot;helloworld&quot;
                    version=&quot;1.7.2.19&quot;
                    processorArchitecture=&quot;x86&quot;/&gt;
  &lt;description&gt;Hello World Application&lt;/description&gt;
  &lt;dependency&gt;
    &lt;dependentAssembly&gt;
      &lt;assemblyIdentity type=&quot;win32&quot;
                        name=&quot;Acme.Soft.SayStuffLib&quot;
                        version=&quot;3.7.2.4&quot;
                        processorArchitecture=&quot;x86&quot;
                        language=&quot;*&quot;/&gt;
    &lt;/dependentAssembly&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;dependentAssembly&gt;
      &lt;assemblyIdentity type=&quot;win32&quot;
                        name=&quot;Microsoft.Windows.Common-Controls&quot;
                        version=&quot;6.0.0.0&quot;
                        processorArchitecture=&quot;x86&quot;
                        publicKeyToken=&quot;6595b64144ccf1df&quot;
                        language=&quot;*&quot;/&gt;
    &lt;/dependentAssembly&gt;
  &lt;/dependency&gt;
  &lt;file name=&quot;hellointl.dll&quot;
        hash=&quot;12345678123456781234567812345678abcdef00&quot;
        hashalg=&quot;SHA1&quot;/&gt;
  &lt;trustInfo xmlns=&quot;urn:schemas-microsoft-com:asm.v2&quot;&gt;
    &lt;security&gt;
      &lt;requestedPrivileges&gt;
        &lt;requestedExecutionLevel level=&quot;asInvoker&quot; uiAccess=&quot;false&quot;/&gt;
      &lt;/requestedPrivileges&gt;
    &lt;/security&gt;
  &lt;/trustInfo&gt;
  &lt;asmv3:application xmlns:asmv3=&quot;urn:schemas-microsoft-com:asm.v3&quot;&gt;
    &lt;asmv3:windowsSettings
        xmlns=&quot;http://schemas.microsoft.com/SMI/2011/WindowsSettings&quot;&gt;
      &lt;dpiAware&gt;true&lt;/dpiAware&gt;
      &lt;printerDriverIsolation&gt;true&lt;/printerDriverIsolation&gt;
    &lt;/asmv3:windowsSettings&gt;
  &lt;/asmv3:application&gt;
&lt;/assembly&gt;"><pre class="notranslate">&lt;?<span class="pl-ent">xml</span><span class="pl-e"> version</span>=<span class="pl-s"><span class="pl-pds">"</span>1.0<span class="pl-pds">"</span></span><span class="pl-e"> encoding</span>=<span class="pl-s"><span class="pl-pds">"</span>UTF-8<span class="pl-pds">"</span></span><span class="pl-e"> standalone</span>=<span class="pl-s"><span class="pl-pds">"</span>yes<span class="pl-pds">"</span></span>?&gt;
&lt;<span class="pl-ent">assembly</span> <span class="pl-e">xmlns</span>=<span class="pl-s"><span class="pl-pds">"</span>urn:schemas-microsoft-com:asm.v1<span class="pl-pds">"</span></span>
          <span class="pl-e">manifestVersion</span>=<span class="pl-s"><span class="pl-pds">"</span>1.0<span class="pl-pds">"</span></span>&gt;
  &lt;<span class="pl-ent">assemblyIdentity</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>win32<span class="pl-pds">"</span></span>
                    <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>helloworld<span class="pl-pds">"</span></span>
                    <span class="pl-e">version</span>=<span class="pl-s"><span class="pl-pds">"</span>1.7.2.19<span class="pl-pds">"</span></span>
                    <span class="pl-e">processorArchitecture</span>=<span class="pl-s"><span class="pl-pds">"</span>x86<span class="pl-pds">"</span></span>/&gt;
  &lt;<span class="pl-ent">description</span>&gt;Hello World Application&lt;/<span class="pl-ent">description</span>&gt;
  &lt;<span class="pl-ent">dependency</span>&gt;
    &lt;<span class="pl-ent">dependentAssembly</span>&gt;
      &lt;<span class="pl-ent">assemblyIdentity</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>win32<span class="pl-pds">"</span></span>
                        <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>Acme.Soft.SayStuffLib<span class="pl-pds">"</span></span>
                        <span class="pl-e">version</span>=<span class="pl-s"><span class="pl-pds">"</span>3.7.2.4<span class="pl-pds">"</span></span>
                        <span class="pl-e">processorArchitecture</span>=<span class="pl-s"><span class="pl-pds">"</span>x86<span class="pl-pds">"</span></span>
                        <span class="pl-e">language</span>=<span class="pl-s"><span class="pl-pds">"</span>*<span class="pl-pds">"</span></span>/&gt;
    &lt;/<span class="pl-ent">dependentAssembly</span>&gt;
  &lt;/<span class="pl-ent">dependency</span>&gt;
  &lt;<span class="pl-ent">dependency</span>&gt;
    &lt;<span class="pl-ent">dependentAssembly</span>&gt;
      &lt;<span class="pl-ent">assemblyIdentity</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>win32<span class="pl-pds">"</span></span>
                        <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>Microsoft.Windows.Common-Controls<span class="pl-pds">"</span></span>
                        <span class="pl-e">version</span>=<span class="pl-s"><span class="pl-pds">"</span>6.0.0.0<span class="pl-pds">"</span></span>
                        <span class="pl-e">processorArchitecture</span>=<span class="pl-s"><span class="pl-pds">"</span>x86<span class="pl-pds">"</span></span>
                        <span class="pl-e">publicKeyToken</span>=<span class="pl-s"><span class="pl-pds">"</span>6595b64144ccf1df<span class="pl-pds">"</span></span>
                        <span class="pl-e">language</span>=<span class="pl-s"><span class="pl-pds">"</span>*<span class="pl-pds">"</span></span>/&gt;
    &lt;/<span class="pl-ent">dependentAssembly</span>&gt;
  &lt;/<span class="pl-ent">dependency</span>&gt;
  &lt;<span class="pl-ent">file</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>hellointl.dll<span class="pl-pds">"</span></span>
        <span class="pl-e">hash</span>=<span class="pl-s"><span class="pl-pds">"</span>12345678123456781234567812345678abcdef00<span class="pl-pds">"</span></span>
        <span class="pl-e">hashalg</span>=<span class="pl-s"><span class="pl-pds">"</span>SHA1<span class="pl-pds">"</span></span>/&gt;
  &lt;<span class="pl-ent">trustInfo</span> <span class="pl-e">xmlns</span>=<span class="pl-s"><span class="pl-pds">"</span>urn:schemas-microsoft-com:asm.v2<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">security</span>&gt;
      &lt;<span class="pl-ent">requestedPrivileges</span>&gt;
        &lt;<span class="pl-ent">requestedExecutionLevel</span> <span class="pl-e">level</span>=<span class="pl-s"><span class="pl-pds">"</span>asInvoker<span class="pl-pds">"</span></span> <span class="pl-e">uiAccess</span>=<span class="pl-s"><span class="pl-pds">"</span>false<span class="pl-pds">"</span></span>/&gt;
      &lt;/<span class="pl-ent">requestedPrivileges</span>&gt;
    &lt;/<span class="pl-ent">security</span>&gt;
  &lt;/<span class="pl-ent">trustInfo</span>&gt;
  &lt;<span class="pl-ent">asmv3</span><span class="pl-ent">:</span><span class="pl-ent">application</span> <span class="pl-e">xmlns</span><span class="pl-e">:</span><span class="pl-e">asmv3</span>=<span class="pl-s"><span class="pl-pds">"</span>urn:schemas-microsoft-com:asm.v3<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">asmv3</span><span class="pl-ent">:</span><span class="pl-ent">windowsSettings</span>
        <span class="pl-e">xmlns</span>=<span class="pl-s"><span class="pl-pds">"</span>http://schemas.microsoft.com/SMI/2011/WindowsSettings<span class="pl-pds">"</span></span>&gt;
      &lt;<span class="pl-ent">dpiAware</span>&gt;true&lt;/<span class="pl-ent">dpiAware</span>&gt;
      &lt;<span class="pl-ent">printerDriverIsolation</span>&gt;true&lt;/<span class="pl-ent">printerDriverIsolation</span>&gt;
    &lt;/<span class="pl-ent">asmv3</span><span class="pl-ent">:</span><span class="pl-ent">windowsSettings</span>&gt;
  &lt;/<span class="pl-ent">asmv3</span><span class="pl-ent">:</span><span class="pl-ent">application</span>&gt;
&lt;/<span class="pl-ent">assembly</span>&gt;</pre></div>
<p dir="auto">This shows providing version number and description of your app, referencing DLLs by assembly name and version which may be Rust built or on the system, referencing a private DLL which must match the expected file using SHA1 hash, activating XP styles by requesting version 6 of common controls, telling UAC that no special privileges are required (even if the app was called setup.exe) and indicating that your app is DPI aware and that the printer driver should run in a separate process (so it doesn't crash your app if it is faulty).  If your app were code signed it would have a public key token as COMCTL32.dll does.</p>
<p dir="auto">I think there's still a lot of work to do on reconciling differences with how Rust is currently and how these features could possibly be implemented, but I think once Rust (and Cargo too most likely) is capable of all the things above and can generate the manifest mostly by itself, things are looking pretty strong on Windows.</p>