65.9K
CodeProject 正在变化。 阅读更多。
Home

在自动化批处理脚本中运行 Microsoft AppLocale 实用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (2投票s)

2008年4月15日

CPOL

3分钟阅读

viewsIcon

89412

downloadIcon

315

在批处理脚本中运行 AppLocale

引言

通过调用用 .NET 编写的包装器,成功地在批处理脚本中运行 Microsoft AppLocale Utility。

背景

Microsoft AppLocale 是一个有用的实用程序,它允许程序在不同的系统区域设置下运行,而无需重置区域设置并重新启动 PC。这对于需要以目标区域设置代码运行的应用程序(如 HTML Help Workshop)非常理想。您可以在此处找到有关该实用程序的更多信息。

但是,如果您想在自动批处理脚本中使用此实用程序,它有两个缺点。

  • 从命令行调用 AppLocale 时会出现一个提示屏幕。
  • AppLocale 运行,在子进程中启动调用的应用程序,然后在子进程仍然活动时退出。

幸运的是,有一个针对 AppLocale 的补丁/技巧可以删除提示屏幕,您可以在此处找到。

第二个问题更棘手,因为您希望在继续下一个批处理命令之前,启动的应用程序能够完成。例如,假设我们希望批处理文件编译一个日语 CHM 文件,然后将其移动到另一台计算机上的某个位置。

  1. AppLocale 将在日语代码页下调用 HTML Help Workshop,一旦应用程序启动,AppLocale 就会退出。
  2. HTML Help Workshop 将开始编译 CHM 文件。
  3. 批处理文件转到下一个命令,该命令是将(当前不存在的)CHM 文件移动到某个位置……于是我们遇到了“文件未找到”错误。
  4. 最终,CHM 文件编译完成,可以进行移动了。

看到了问题所在吗?我们该如何解决呢?很高兴您问了这个问题。

Using the Code

此代码将启动 AppLocale 并获取其 Windows 进程 ID,搜索父进程 ID 等于 AppLocale 进程 ID 的运行进程,然后等待该进程结束。

就我们的目的而言,我们需要在 Visual Studio .NET 中创建一个命令行项目。首先,我们需要创建一个 Process 对象来调用 AppLocale,然后获取其 Process ID,我们可以使用该 ID 来搜索它启动的子进程。对于 StartInfo.Arguments,我们需要以 AppLocale 文档中 noted 的相同方式,传入我们调用的程序、其参数和区域 ID。

Dim procAppLoc As Process
Dim intAppLocID as Integer

'Create the AppLocale process object.
procAppLoc = New Process

'Set up the 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

'Start the process
procAppLoc.Start()

'Get the AppLocale process ID
intAppLocID = procAppLoc.Id

'Wait for AppLocale to spawn the child process and exit
procAppLoc.WaitForExit()
procAppLoc.Dispose()

接下来,我们使用一个 Win32_Process 对象,它收集的信息比常规的 Process 对象更多,以搜索父进程 ID 等于我们的 AppLocale 进程 ID 的进程。

Dim objWMI As Object
Dim colItems As Object
Dim objItem As Object
Dim intChildProcessID As Integer

'Set up Win32_Process object
objWMI = GetObject("winmgmts:\\.\root\CIMV2")
colItems = objWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL")

'Find the child process and retrieve its ID value
intChildProcessID = -1
For Each objItem In colItems
   If objItem.ParentProcessId = intAppLocID Then
      intChildProcessID = objItem.ProcessId
   End If
Next

因此,既然我们已经找到了 AppLocale 启动的应用程序的进程 ID,我们就可以将其放入一个 Process 对象中,并在它退出后再继续执行。

Dim procChild As Process

If intChildProcessID > -1 Then
   'Get the child process object
   procChild = Process.GetProcessById(intChildProcessID)

   'Wait for the child process to exit
   procChild.WaitForExit()
   procChild.Dispose()
End If

现在,我们创建的程序将在启动的子进程结束之前等待,然后它自身也结束,批处理脚本就可以继续执行下一个命令了。

一旦安装了 AppLocale,并且 AppLocale 可执行文件被打了补丁,这段代码也被编译好了。现在,您可以用这个程序来代替调用 AppLocale,使用相同的参数集。

MyAppLocWrapper.exe program [arguments] /L[local id]

关注点

除了 AppLocale 之外,还有一个替代方案,那就是 SBAppLocale。它不适合我们的需求,但这并不意味着它不适合您,我建议您考虑将其作为一种选择。您可以在此处找到有关 SBAppLocale 的信息。

我注意到的一点是,AppLocale 在从命令行调用时可能会非常挑剔。以下是一些注意事项:

  • AppLocale 只能调用可执行文件,不能调用批处理文件。
  • 将所有程序参数都用引号括起来。
  • 始终使用绝对路径。
  • 如果您看到 GUI 窗口出现,那可能意味着它不喜欢输入的参数。
  • 始终删除 C:\Windows\AppPatch\AppLoc.tmp 文件,以确保运行的干净。
  • 在“控制面板”>“区域和语言选项”>“语言”选项卡中,选中“补充语言支持”部分中的所有复选框。

一个绕过无法启动批处理文件的技巧是,使用 cmd.exe 作为被调用的程序来运行 AppLocale,如下所示:

C:\Windows\AppPatch\AppLoc.exe C:\WINDOWS\system32\cmd.exe "/c
C:\Scripts\MyBatchFile.bat FakeParameter1" /L1041
© . All rights reserved.