Windows installer 如何使用InstallShield升级代码GUID卸载Inno安装程序中的相关产品

Windows installer 如何使用InstallShield升级代码GUID卸载Inno安装程序中的相关产品,windows-installer,inno-setup,installshield,pascalscript,Windows Installer,Inno Setup,Installshield,Pascalscript,我们公司已从使用InstallShield Express切换到使用Inno安装程序(5.5.2版)。我们使用InstallShield进行了多年的旧安装,但始终依赖InstallShield的升级代码GUID来处理以前版本的卸载 我需要能够从新的Inno安装程序中卸载任何以前安装的InstallShield版本 经过一些研究,看起来我需要调用MsiEnumRelatedProducts(),然后卸载所有找到的产品 我找到了这个链接(德语原文)。看起来他已经很接近了,但他从未发布过他的最终解决方

我们公司已从使用InstallShield Express切换到使用Inno安装程序(5.5.2版)。我们使用InstallShield进行了多年的旧安装,但始终依赖InstallShield的升级代码GUID来处理以前版本的卸载

我需要能够从新的Inno安装程序中卸载任何以前安装的InstallShield版本

经过一些研究,看起来我需要调用MsiEnumRelatedProducts(),然后卸载所有找到的产品

我找到了这个链接(德语原文)。看起来他已经很接近了,但他从未发布过他的最终解决方案

他说的代码有效(但对我来说崩溃):

我对Pascal脚本编写还不熟悉,而且我对整个SetLength()部分都很熟悉。他说,它在功能中取代了什么,但却崩溃了

既然其他人说要切换到字符串,我是否应该摆脱它:

type
  TProductBuf = array[0..39] of char;
如果有人能用英语向我展示一个最终的工作函数,那就太棒了

提前谢谢

编辑:
我使用的是Inno安装编译器的ANSI版本。

这里有一个未经测试的翻译,它应该只在消息框中打印出相关的产品GUID。该代码应适用于ANSI以及InnoSetup的Unicode版本:

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

#define UPGRADE_CODE "<your upgrade here>"

const
  ERROR_SUCCESS = $00000000;
  ERROR_NOT_ENOUGH_MEMORY = $00000008;
  ERROR_INVALID_PARAMETER = $00000057;
  ERROR_NO_MORE_ITEMS = $00000103;
  ERROR_BAD_CONFIGURATION = $0000064A;

function MsiEnumRelatedProducts(lpUpgradeCode: string; dwReserved: DWORD;
  iProductIndex: DWORD; lpProductBuf: string): UINT;
  external 'MsiEnumRelatedProducts{#AW}@msi.dll stdcall';

function InitializeSetup: Boolean;
var
  I: Integer;
  ProductBuf: string;
begin
  Result := True;

  I := 0;
  SetLength(ProductBuf, 39);

  while MsiEnumRelatedProducts('{#UPGRADE_CODE}', 0, I, ProductBuf) = ERROR_SUCCESS do
  begin
    MsgBox(ProductBuf, mbInformation, MB_OK);
    I := I + 1;
    SetLength(ProductBuf, 39);
  end;
end;
[代码]
#ifdef UNICODE
#定义AW“W”
#否则
#定义“A”
#恩迪夫
#定义升级代码“”
常数
错误_SUCCESS=$00000000;
错误\u没有足够的\u内存=$00000008;
错误\无效\参数=$00000057;
错误\u无\u更多\u项目=$00000103;
错误\u错误\u配置=$0000064A;
函数MsiEnumRelatedProducts(lpUpgradeCode:string;dwReserved:DWORD;
IPProductIndex:DWORD;lpProductBuf:string):UINT;
外部“MsiEnumRelatedProducts{#AW}@msi.dll stdcall”;
函数初始化设置:布尔;
变量
I:整数;
ProductBuf:字符串;
开始
结果:=真;
I:=0;
设定长度(ProductBuf,39);
而MsiEnumRelatedProducts(“{{#升级_代码}”,0,I,ProductBuf)=错误_成功执行
开始
MsgBox(ProductBuf,mbInformation,MB_OK);
I:=I+1;
设定长度(ProductBuf,39);
结束;
结束;

很抱歉,我花了一些时间才回到这篇文章,但我出于个人原因出去了一段时间。没问题:-)也许我也应该回到这篇文章并测试它。到目前为止,我至少已经纠正了原始代码中的ANSI/Unicode不匹配。您正在导入Unicode版本的函数,但传递的是ANSI字符串(因为
string
代表ANSI InnoSetup中的ANSI字符串)。我在完成之前点击了CR并发布。谢谢你的代码示例,但我还有一个问题。user32.dll的导入应该是msi.dll,我已经修复了它。在那之后,我在while-MsiEnumRelatedProducts循环的某个地方得到了两个访问冲突错误。我有两个,但我只安装了一个以前的产品。我不得不猜测它是在SetLength(ProductBuf,39)调用中,因为安装程序在没有安装任何以前的产品的情况下执行得很好。值得注意的是,在原始帖子的德语评论中提到了这种访问冲突。嗯,奇怪。。。您链接的帖子中写道,您不应该对参数
lpProductBuf
使用
var
,但根据您的需要(它是一个输出参数)。但是,这似乎是另一个文档失败。。。即使是一个坚如磐石的代码库,也没有
var
来定义它。还有,对不起,图书馆的名字。这是我的复制/粘贴错误。。。
type
  TProductBuf = array[0..39] of char;
[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

#define UPGRADE_CODE "<your upgrade here>"

const
  ERROR_SUCCESS = $00000000;
  ERROR_NOT_ENOUGH_MEMORY = $00000008;
  ERROR_INVALID_PARAMETER = $00000057;
  ERROR_NO_MORE_ITEMS = $00000103;
  ERROR_BAD_CONFIGURATION = $0000064A;

function MsiEnumRelatedProducts(lpUpgradeCode: string; dwReserved: DWORD;
  iProductIndex: DWORD; lpProductBuf: string): UINT;
  external 'MsiEnumRelatedProducts{#AW}@msi.dll stdcall';

function InitializeSetup: Boolean;
var
  I: Integer;
  ProductBuf: string;
begin
  Result := True;

  I := 0;
  SetLength(ProductBuf, 39);

  while MsiEnumRelatedProducts('{#UPGRADE_CODE}', 0, I, ProductBuf) = ERROR_SUCCESS do
  begin
    MsgBox(ProductBuf, mbInformation, MB_OK);
    I := I + 1;
    SetLength(ProductBuf, 39);
  end;
end;