Fix for applications that do not support high DPI

I recently got a Microsoft Surface Pro, which has a high DPI display.  Many apps do not display properly, because they are not DPI-aware.  Here’s how to fix that in Windows 10/Windows Server 2016:

  1. If the program(s) you need to fix are in the Program Files folder(s), you’ll need Administrator rights.
  2. In your registry, tell Windows to prefer external program manifests over embedded ones:
    1. In RegEdit, go to the key:
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide
    2. Add a new DWORD 32-bit value:
      PreferExternalManifest
      and set it to 1.
  3. Create a text file in the same folder as the program with the exact same name as your the program including the .exe extension, and add a second extension, .manifest.  So, if your program is called Program.exe, you’ll create a new text file called Program.exe.manifest.
  4. Edit the text file, and add the following code to it:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    
    <dependency>
      <dependentAssembly>
        <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0" processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*">
        </assemblyIdentity>
      </dependentAssembly>
    </dependency>
    
    <dependency>
      <dependentAssembly>
        <assemblyIdentity
          type="win32"
          name="Microsoft.VC90.CRT"
          version="9.0.21022.8"
          processorArchitecture="amd64"
          publicKeyToken="1fc8b3b9a1e18e3b">
        </assemblyIdentity>
      </dependentAssembly>
    </dependency>
    
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
      <security>
        <requestedPrivileges>
          <requestedExecutionLevel
            level="asInvoker"
            uiAccess="false"/>
        </requestedPrivileges>
      </security>
    </trustInfo>
    
    <asmv3:application>
      <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
        <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
      </asmv3:windowsSettings>
    </asmv3:application>
    
    </assembly>
    

Note that if you right-click and select Properties in Windows 10, there’s also a compatibility mode tab which has a setting that lets you override the application’s scaling properties.  However, this doesn’t seem to work on an RDP connection.  The manifest method above does work in RDP.

Source

A Development SMTP Server for Testing

I needed a development SMTP server that I could use for testing with Microsoft Outlook, which would save the e-mails in a folder so I could go back to them.  I was already aware of python -m smtpd -n -c DebuggingServer localhost:25, but this solution allows me to open the results in Outlook.

I use this with Cygwin on Windows.

import smtpd
import asyncore
import io
import uuid
import os

class FileSMTPServer(smtpd.SMTPServer):
    def process_message(self, peer, mailfrom, rcpttos, data):
        f_name = os.path.join('mailroot', str(uuid.uuid4()) + '.eml')
        with open(f_name, "w") as out_file:
            out_file.write(data)
            

if not os.path.isdir('mailroot'):
    os.mkdir('mailroot')
    
print("Development SMTP Server Listening on Port 25")
server = FileSMTPServer(('127.0.0.1', 25), None)

asyncore.loop()

Save it as smtp-test-server.py, and run it with python smtp-test-server.py.  It’ll create a folder called mailroot which will store each e-mail with a unique ID.

Note that you’d need to run this with sudo on Linux, or change the port number (port 25 in this example) to one above 1024.

Debian Root Drive on an F2FS Filesystem

F2FS is a filesystem that was initially developed by Samsung for flash devices.  I’ve seen several benchmarks (e.g. xda-developers) that seemed to imply that F2FS was faster than EXT4 on flash devices, so I decided to try it, as my EXT4 USB was very slow.  Writing this on an F2FS Debian root on a USB flash drive right now, I can attest to the fact that it is much snappier than a similar installation using EXT4.

As of this writing, Grub2 doesn’t support booting to an F2FS partiton, so the trick to getting an F2FS root is to have an EXT4 partition for your /boot, which loads the drivers and chroots into your root.

I haven’t worked out all the kinks yet, but here is the basic outline:

  1. Partition your flash drive with 3 partitions:
    1. /dev/sdX1 as EXT4 – your boot partition
    2. /dev/sdX2 as F2FS – your root (/) partition
    3. /dev/sdX3 as your swap
  2. Debootstrap /dev/sdX2, chroot, and mount sdX1 under /boot
    1. More specifically, I mounted sdX1 under /mnt, and then bind-mounted the /mnt/boot subfolder to /boot (mount --bind /mnt/boot /boot).  You might not have to do this; I’d think it should work with just /boot, but I haven’t tested it.  I copied /vmlinuz and /initrd.img from the host to /mnt/, so Grub would be able to find them easily.
  3. In your chroot, make sure you have /dev bind-mounted from the host, and have mounted /proc, /sys, and /dev/pts
  4. apt-get all of the packages you need, configure the system, etc.
  5. Be sure you change the root password with passwd, or create a new user account with sudo privileges!  Otherwise, you won’t be able to log into your system (guilty as charged).
  6. Build the f2fs driver into your initramfs
    1. echo f2fs >> /etc/initramfs-tools/modules
    2. update-initramfs -u
  7. apt-get install grub2 (if you haven’t already), and then do a grub-install /dev/sdX
  8. Do an update-grub2
  9. Make sure you have updated your /etc/fstab to mount the proper drives.  I like to use blkid to get the UUIDs of the drives for my fstab, but that’s up to you.
  10. Unmount everything and try to boot
  11. For some reason, Grub completely found the wrong hard drive, which brought me to a grub rescue> prompt.  I made it boot by using the following (my USB was on hd0 — YMMV):
    1. set root=(hd0,msdos1)
    2. set prefix=/boot/grub
    3. insmod normal
    4. normal
  12. Now you should have the normal Grub menu.  Then, I had to manually edit the default menu item, by pressing e.
    1. I replaced all instances of hd1,msdos1 with hd0,msdos1, and for some reason it was mounting my F2FS partition as ro — I changed that to rw.
  13. Now hit Ctrl+X to boot
  14. If all goes according to plan, this should boot into the Debian system.
  15. I re-installed Grub for good measure: grub-install /dev/sdX && update-grub2
  16. Now, I had to manually edit /boot/grub/grub.cfg to make the changes I specified above — replacing hd1,msdos1 with hd0,msdos1, and setting my F2FS partition as rw
    1. NOTE: these changes will be overridden whenever update-grub2 is run (either by you or by updating your packages).  This is why I said I “haven’t worked out all the kinks” yet.  This is only a temporary fix.

 

Generating a .NET DLL for use with VBA

This process will allow you to generate a single DLL that contains an embedded type library as well as a COM-exposed .NET library, and be used in Tools->References in VBA.  It can be used without registering the COM object with REGASM.

I may not find the time to add detail to this, but I am putting it here as a reminder for myself.  I implemented this as a proof-of-concept, but haven’t done anything with it yet. If anyone viewing this needs help with it, feel free to leave a comment with Disqus below.

Process Overview

  1. Develop a .NET COM-visible DLL.  Note that you don’t need to use REGASM to register it for this process.
    1. COM visibility is needed to interop with Office products.  If the DLL isn’t COM-visible, VBA can’t “see” its objects and methods
  2. Add the UnmanagedExports NuGet to your project
  3. Add a static method to your class to instantiate your COM object
  4. Decorate the static method with the [DllExport] attribute (from the UnmanagedExports library)
    e.g.

    ...
    using RGiesecke.DllExport;
    using System.Runtime.InteropServices;
    ...
    [Guid("{AAAAA...AAA}")]
    [ClassInterface(ClassInterfaceType.None)]
    public class MyCOMObject : IMyCOMObject
    {
      ...
      //COM Implementation
      ...
      [DllExport("CreateMyCOMObject", CallingConvention = CallingConvention.StdCall)]
      public static IMyCOMObject CreateMyCOMObject()
      {
        return new MyCOMObject();
      }
    }
    
  5. Compile the DLL (NOTE: must be in x86 or x64 mode; Any CPU will not work with UnmanagedExports!)
  6. Generate a type library (tlbexp)
  7. Generate an IDL file by opening the TLB file with the OLE/COM Object Viewer (File->View TypeLib…)
    1. Note the OLE/COM object viewer (oleview.exe) comes with the Windows SDK, so it must be installed
  8. Export the type library to a .IDL file (Save As…)
  9. Edit the IDL file to add a module section, before the closing bracket in the library definition:
    e.g.

    ...
    library MyVBALibrary
    {
      ...
      //Your new entry starts here
      [dllname("MyVBALibrary.dll")]
      module MyLibrary
      {
        [
          helpstring("Static method that instantiates a new instance of your COM object"),
          entry("CreateMyCOMObject")
        ]
        IMyCOMObjectsInterface __stdcall CreateMyCOMObject();
      };
      //Your entry ends here
    ...
    };
    
  10. Compile the IDL file into a new tlb file (note this is different than the TLB file already generated!!). Make sure you put it into a subfolder, because the midl tool won’t overwrite the original .tlb.
    midl /output .\outputsubfolder\ MyVBALibrary.idl
    
  11. Create a new resource file (e.g. MyVBALibrary.rc), and add a single line:
    1 typelib "MyVBALibrary.tlb"
    
  12. Move the .tlb file from the subdirectory into your current working directory (overwriting the old tlb file)
  13. Compile the .rc file:
    rc MyVBALibrary.rc
    
  14. This should create a new .res file, e.g. MyVBALibrary.res
  15. Assuming your project is a C# project; go to the project properties->Applicaton tab, and under “Resources,” click the “Resource File.” radio button.  Click the ellipsis (…), and select the MyVBALibrary.res file you generated in the previous step
  16. Recompile the project

Now, this dll can be used in your VBA project by adding a reference to it in Tools->References.  To instantiate a new .NET object from your COM class, use the CreateMyCOMObject() function you created.

Troubleshooting

The DLL must be in the path that VBA is searching for, or you will get a “File Not Found” exception.   You may have to use “ChDrive” and “ChDir” in your VBA code to find the DLL, as it will look in its current folder.

References

How To Make C DLL More Accessible to VB with a Type Library

Unmanaged Exports

Google Chrome in a Docker Container

(with sound and WebGL!)

If you’re a Linux enthusiast and haven’t already hopped on the Docker bandwagon, do.  Docker containers are a great way to deploy your web-based applications, or test out untrusted code, but they can also be used as a way to run apps on your Linux desktop that you might not fully trust.  It’s kind of like running your applications in a plastic bag — it makes it harder for them to break out and destroy your system.

Let’s run Google Chrome in a Docker container.

I will assume you are using Ubuntu 14.10.  First, install the latest Docker.  This tutorial expects Docker 1.4.1+.

Now, as a normal (unprivileged) user with sudo access, run the following commands in a shell:

sudo docker run transistor1/chrome config > start.sh
sudo chmod +x start.sh
./start.sh

You should be prompted for your sudo password, to run the Docker container.  That’s it! For subsequent runs, you can just run the

./start.sh

command.

Now, head on over to Chrome Experiments, and test out your WebGL and sound. Enjoy!