将相同的用户应用程序模型 ID 分配给 WinForms 应用程序和 VB6 应用程序

问题描述 投票:0回答:1

我们有一个混合 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 显示为“??”。

.net winapi vb6
1个回答
0
投票

看起来你的

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
© www.soinside.com 2019 - 2024. All rights reserved.