In windows, for some x64 based systems you will face sometimes a weird behaviour when you try to run some executable from your application that is located in the (C:\Windows\system32
) directory of Windows, for example with dfrgui.exe
, an application that allows the user to defrag the disks on the system. It could be theoretically started with the following code:
// First way
Process processToStart = new Process
{
StartInfo =
{
FileName = @"dfrgui.exe",
WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.System)
}
};
processToStart.Start();
// Second way
Process.Start(@"C:\Windows\system32\dfrgui.exe");
However, when you run the code on the mentioned platform, you will see nothing, absolutely nothing. There's no exception, no stack trace, just nothing. This problem can be pretty frustrating, fortunately there's a solution for this problem that you can easily implement in your application without so much hassle.
In this article, we'll explain you how to prevent this behaviour and run any executable located in the System32 directory of Windows with C# in Winforms.
1. Create Wow64Interop class
In order to run any executable located in the system directory of windows (C:\Windows\system32
) you will need to disable the file system redirection for the calling thread. File system redirection is enabled by default on every system, so you will need to run a native method of Windows namely the Wow64DisableWow64FsRedirection
function. Previously, the predilect function to achieve this was Wow64EnableWow64FsRedirection
, however this function may not work reliably when there are nested calls. To ensure the correct functionality of your application, be sure to use the Wow64DisableWow64FsRedirection method. The class will contain as well the method to revert what we did at the beginning with the previous function, namely the Wow64RevertWow64FsRedirection method, any data allocation on behalf of the Wow64DisableWow64FsRedirection
function is cleaned up by this function.
We can include this helper in our code in the following way. Proceed to include this method on your Winforms application creating the following class within your own namespace. This class name will be Wow64Interop
(filename Wow64Interop.cs
) and contains the following code:
using System;
using System.Runtime.InteropServices;
namespace Sandbox
{
public class Wow64Interop
{
const string Kernel32dll = "Kernel32.Dll";
[DllImport(Kernel32dll, EntryPoint = "Wow64DisableWow64FsRedirection")]
public static extern bool DisableWow64FSRedirection(ref IntPtr ptr);
[DllImport(Kernel32dll, EntryPoint = "Wow64RevertWow64FsRedirection")]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
}
}
After including the class, it should be exposed publicly in your application as we'll use it later to run the app.
2. Run your application that is inside the system32 directory
Now, as mentioned at the beggining we need to disable as first the file system redirection for the calling thread, so we will wrap our code initialize the application inside a try-catch block that will run before the Wow64Interop.DisableWow64FSRedirection(true)
method that will allow you to start the executable (disables the redirection):
// Required namespaces
using System;
using System.Diagnostics;
using System.Windows.Forms;
IntPtr wow64Value = IntPtr.Zero;
try
{
// 1. Disable initially the Wow64FSRedirection
Wow64Interop.DisableWow64FSRedirection(ref wow64Value);
// 2. Prepare the code that starts another executable
// Run the application from the system32 directory
// In this case we will run the dfrgui.exe app
//
// C:\Windows\system32\dfrgui.exe
Process processToStart = new Process
{
StartInfo =
{
FileName = @"dfrgui.exe",
WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.System)
}
};
// Start the application
processToStart.Start();
}
catch (Exception exc)
{
Console.WriteLine("Unabled to disable/enable WOW64 File System Redirection");
Console.WriteLine(exc.Message);
}
finally
{
// 3. Let the Wow64FSRedirection with its initially state
Wow64Interop.Wow64RevertWow64FsRedirection(wow64Value);
}
The code should now start the application without any issue (in case that you don't have the permissions, you will see at least the exception triggered cause of your credentials, but you will see at least something, unlike the code we had at the beginning). Don't forget to revert the changes made to the redirection again once the executable starts inside the finally statement (Wow64Interop.Wow64RevertWow64FsRedirection(true)
).
Happy coding !