Introduction
Run Microsoft AppLocale Utility successfully in a batch script by calling it with a wrapper written in .NET.
Background
The Microsoft AppLocale is a nifty utility that allows a program to run under a different system locale without having to reset the region settings and reboot the PC. This is ideal for applications, such as HTML Help Workshop, that require to be run under a target locale code. You can find more info about the utility here.
However there are two drawbacks to this utility if you want to use it in an automated batch script.
- A nag screen appears when calling AppLocale from the command line.
- AppLocale runs, spawns the called application in a child process, then quits while the child process is still active.
Luckily there is a patch/hack for AppLocale to remove the nag screen that can be found here.
The second issue is a bit more tricky because you want the spawned application to complete before continuing to the next batch command. For example, let's say we want a batch file to compile a Japanese language CHM file, then move it to a location on another computer.
- AppLocale will call HTML Help Workshop under the Japanese code page, and as soon as the application is launched, AppLocale will quit.
- HTML Help Workshop will begin to compile the CHM file.
- The batch file goes to its next command which is to move (a currently non-existent) CHM file... and we get file not found errors.
- Finally the CHM file is finished compiling and ready to be moved.
See the problem? How can we get around this? Well I am glad you asked.
Using the Code
What this code will do is launch AppLocale and grab its Windows Process ID, search for the running processes whose Parent Process ID is equal to AppLocale's Process ID, then wait for that process to end.
For our purposes, we want to create a command-line project in Visual Studio .NET. First we need to create a Process object to call AppLocale, then grab its Process ID which we can use to search for the child process that it launches. For StartInfo.Arguments
we want to pass in the program we are calling, its arguments and local ID in the same style noted in the AppLocale documentation.
Dim procAppLoc As Process
Dim intAppLocID as Integer
procAppLoc = New Process
procAppLoc.StartInfo.FileName = "C:\Windows\AppPatch\AppLoc.exe"
procAppLoc.StartInfo.Arguments = Program we are calling, its arguments & local ID
procAppLoc.StartInfo.ErrorDialog = True
procAppLoc.EnableRaisingEvents = True
procAppLoc.Start()
intAppLocID = procAppLoc.Id
procAppLoc.WaitForExit()
procAppLoc.Dispose()
Next we use a Win32_Process
object which gathers more information than the regular Process
object, to search for the process that has a Parent Process ID equal to our AppLocale Process ID.
Dim objWMI As Object
Dim colItems As Object
Dim objItem As Object
Dim intChildProcessID As Integer
objWMI = GetObject("winmgmts:\\.\root\CIMV2")
colItems = objWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL")
intChildProcessID = -1
For Each objItem In colItems
If objItem.ParentProcessId = intAppLocID Then
intChildProcessID = objItem.ProcessId
End If
Next
So now that we found the Process ID of the application that AppLocale launched, we can place this into a Process object and wait for it to exit before continuing.
Dim procChild As Process
If intChildProcessID > -1 Then
procChild = Process.GetProcessById(intChildProcessID)
procChild.WaitForExit()
procChild.Dispose()
End If
Now the program we have created will wait for the spawned child process to end before it ends itself and the batch script can move to the next command.
Once AppLocale is installed, the AppLocale executable file is patched and this code is compiled. You can now call this program instead of calling AppLocale with the same set of arguments.
MyAppLocWrapper.exe program [arguments] /L[local id]
Points of Interest
There is another alternative to AppLocale, and that is SBAppLocale. It did not work for our needs but that doesn't mean it won't work for you and I would suggest considering it as an option. You can find information about SBAppLocale here.
One thing I noticed is that AppLocale can be very finicky when being called from the command line. Here are a few points to note:
- AppLocale can only call executables and not batch files.
- Pass in all of the program arguments surrounded by quotes.
- Always use absolute paths.
- If you see the GUI window appear, it probably means it didn't like what was input.
- Always delete the C:\Windows\AppPatch\AppLoc.tmp file to ensure a clean run.
- In Control Panel > Regional and Language Options > Language tab, check all boxes in the "Supplemental language support" section.
A trick to get around not being able to launch a batch file is to run AppLocale with cmd.exe as the called program like this:
C:\Windows\AppPatch\AppLoc.exe C:\WINDOWS\system32\cmd.exe "/c
C:\Scripts\MyBatchFile.bat FakeParameter1" /L1041