我们有一个混合 VB6 应用程序和一些 .NET 代码库。 VB6 项目已接近容量,因此我将主应用程序迁移到 WinForms 应用程序。由于遗留代码库和可用资源的数量较多,因此不可能将其全部迁移到 .NET 应用程序。我们计划保留 VB6 项目作为第二个进程来访问那些我们现在不会迁移的表单,使用 IPC 的命名管道。
现在,我正在尝试将任务栏上的两个进程分组。我发现的所有内容都指向使用 Win32 API 的
SetCurrentProcessExplicitAppUserModelID()
为两个进程提供相同的 AUMID。
在.NET应用程序中,我有:
[DllImport("shell32.dll", SetLastError = true)]
static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr), In] string AppID);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
SetCurrentProcessExplicitAppUserModelID("MyCompany.MyApplication");
// Other presumably irrelevant initialization
}
.NET 应用程序使用
Process.Start
作为其初始化的一部分来启动 VB6 应用程序。在 VB6 应用程序中,我有:
Private Declare Function SetCurrentProcessExplicitAppUserModelID Lib "shell32.dll" (appID As Long) As Long
Private Sub Main()
Dim strAUMID As String
strAUMID = "MyCompany.MyApplication"
SetCurrentProcessExplicitAppUserModelID StrPtr(strAUMID)
' Other presumably irrelevant initialization
End Sub
我希望通过这些更改将两个进程的表单分组在任务栏上的单个图标下,但它们仍然按进程分开。我尝试添加一些诊断代码(我在上面省略了)以尝试深入了解它。
.NET 应用程序似乎正在按预期工作。当我使用
GetCurrentProcessExplicitAppUserModelID()
时,它会输出 "MyCompany.MyApplication"
。
但是,当我在 VB6 应用程序中使用 Get 时,它会输出其他内容。 VB6 中的 Get 将返回
StrPtr
而不是 String
。我在 https://www.vbforums.com/showthread.php?682690-Using-the-results-of-StrPtr 找到了代码,将 StrPtr
转换为相应的 String
,但它没有转换回到"MyCompany.MyApplication"
。
我不知道还能尝试什么。
编辑: 这是 .NET 应用程序中的当前代码。
[DllImport("shell32.dll", SetLastError = true)]
static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr), In] string AppID);
[DllImport("shell32.dll", SetLastError = true)]
static extern int GetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr), Out] out string AppID);
[STAThread]
static void Main()
{
var result = SetCurrentProcessExplicitAppUserModelID("MyCompany.MyApplication");
MessageBox.Show(result.ToString());
string appId;
result = GetCurrentProcessExplicitAppUserModelID(out appId);
MessageBox.Show($"{result}: {appId}");
// Other code
}
Set 和 Get 均返回 0,appID 为 MyCompany.MyApplication。
这就是 VB6 应用程序中的内容。
Private Declare Function SetCurrentProcessExplicitAppUserModelID Lib "shell32.dll" (appID As Long) As Long
Private Declare Function GetCurrentProcessExplicitAppUserModelID Lib "shell32.dll" (ByRef appID As Long) As Long
Private Declare Function SysAllocString Lib "OleAut32" (ByVal strPtr As Long) As String
Private Sub Main()
Dim ret As Long
Dim appID As Long
Dim appString As String
Dim strAUMID As String
strAUMID = "MyCompany.MyApplication"
ret = SetCurrentProcessExplicitAppUserModelID(StrPtr(strAUMID))
MsgBox CStr(ret)
ret = GetCurrentProcessExplicitAppUserModelID(appID)
appString = StrConv(SysAllocString(appID), vbFromUnicode)
MsgBox CStr(ret) + ": " + appString
' Other code
End Sub
Get 和 Set 均返回 0,appString 显示为“??”。
看起来你的
Declare
定义是错误的。 SetCurrentProcessExplicitAppUserModelID
的参数需要是ByVal
,因为旧VBA/VB6中的默认值是ByRef
。
您还需要使用
GetCurrentProcessExplicitAppUserModelID
释放从 CoTaskMemFree
获得的指针。
Private Declare Function SetCurrentProcessExplicitAppUserModelID Lib "shell32.dll" (ByVal appID As Long) As Long
Private Declare Function GetCurrentProcessExplicitAppUserModelID Lib "shell32.dll" (appID As Long) As Long
Private Declare Function SysAllocString Lib "OleAut32" (ByVal strPtr As Long) As Str
Private Declare Sub CoTaskMemFree Lib "Ole32" (ByVal strPtr As Long)
Private Sub Main()
Dim ret As Long
Dim appID As Long
Dim appString As String
Dim strAUMID As String
strAUMID = "MyCompany.MyApplication"
ret = SetCurrentProcessExplicitAppUserModelID(StrPtr(strAUMID))
MsgBox CStr(ret)
ret = GetCurrentProcessExplicitAppUserModelID(appID)
appString = StrConv(SysAllocString(appID), vbFromUnicode)
If ret = 0 Then CoTaskMemFree(appID)
MsgBox CStr(ret) + ": " + appString
' Other code
End Sub