太好了,现在我需要知道的只是 SSMS-Setup-ENU.exe 的产品 ID,对吗?
但是我该怎么做呢?当我在另一台机器上安装它并尝试了https://blogs.msdn.microsoft.com/brian_farnhill/2017/07/04/getting-ids-to-use-with-the-package-dsc-resource/我有两个产品 ID:
PS C:\> $x86Path = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
PS C:\> $installedItemsX86 = Get-ItemProperty -Path $x86Path | Select-Object -Property DisplayName, PSChildName
PS C:\> $x64Path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
PS C:\> $installedItemsX64 = Get-ItemProperty -Path $x64Path | Select-Object -Property DisplayName, PSChildName
PS C:\> $installedItems = $installedItemsX86 + $installedItemsX64
PS C:\> $installedItems | Where-Object -FilterScript { $null -ne $_.DisplayName } | Sort-Object -Property DisplayName | sls 'Management Studio'
@{DisplayName=Microsoft SQL Server Management Studio - 17.4; PSChildName={ac84c935-8f13-4f73-b541-7b09a11bdea8}}
@{DisplayName=SQL Server 2017 Management Studio Extensions; PSChildName={6492E746-1C5D-48C2-A92A-97D431F74664}}
@{DisplayName=SQL Server 2017 Management Studio Extensions; PSChildName={70C24F35-7E36-45FC-B289-3D2849E5556B}}
@{DisplayName=SQL Server Management Studio; PSChildName={F8ADD24D-F2F2-465C-A675-F12FDB70DB82}}
@{DisplayName=SQL Server Management Studio; PSChildName={1B8CFC46-1F08-4DA7-9FEA-E1F523FBD67F}}
@{DisplayName=SQL Server Management Studio for Analysis Services; PSChildName={CC6997A7-1638-4E38-B6CF-E776997036B0}}
@{DisplayName=SQL Server Management Studio for Reporting Services; PSChildName={4DDEB555-26D2-4E68-98AF-8F96232C13F2}}
我实际上尝试了一种不同的方法,但得到了相同的结果(可能是因为两者都“基于”相同的数据):
PS C:\> get-wmiobject Win32_Product -Filter "Name like '%sql%management%studio%'" | sort -Property Name | Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
IdentifyingNumber Name LocalPackage
----------------- ---- ------------
{6492E746-1C5D-48C2-A92A-97D431F74664} SQL Server 2017 Management Studio Extensions C:\Windows\Installer\43f1a.msi
{70C24F35-7E36-45FC-B289-3D2849E5556B} SQL Server 2017 Management Studio Extensions C:\Windows\Installer\43f16.msi
{F8ADD24D-F2F2-465C-A675-F12FDB70DB82} SQL Server Management Studio C:\Windows\Installer\43f23.msi
{1B8CFC46-1F08-4DA7-9FEA-E1F523FBD67F} SQL Server Management Studio C:\Windows\Installer\43f27.msi
{CC6997A7-1638-4E38-B6CF-E776997036B0} SQL Server Management Studio for Analysis Services C:\Windows\Installer\43f43.msi
{4DDEB555-26D2-4E68-98AF-8F96232C13F2} SQL Server Management Studio for Reporting Services C:\Windows\Installer\43f3c.msi
两种方法都会产生两个产品 ID:
- F8ADD24D-F2F2-465C-A675-F12FDB70DB82
- 1B8CFC46-1F08-4DA7-9FEA-E1F523FBD67F
那么,哪一个是正确的呢?有没有一种更确定的方法来应对推断正确产品 ID 的疯狂行为?
答案1
我想我终于弄清楚了发生了什么,尽管我还没有检查这是否有助于我使用 Azure Automation DSC 安装 SSMS。
以下是我所做的:
- 将 SSMS-Setup-ENU.exe 重命名为 SSMS-Setup-ENU.zip
- 偷看了里面的内容。唯一的文本文件名为“0”,这是一个 XML 文件。
- 从第一个元素
<BurnManifest xmlns="http://schemas.microsoft.com/wix/2008/Burn">
我得出结论,该 exe 是使用 WIX 刻录创建的。 - 将文件重命名回来。
- 成立https://stackoverflow.com/questions/26749207/extract-contents-of-burn-bootstrapper
- 下载并解压 wix311-binaries.zip,网址为https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm
- 运行
dark.exe -x d:\temp SSMS-Setup-ENU.exe
,它从 SSMS-Setup-ENU.exe 中提取了许多 msi 文件到d:\temp
。 - 成立https://stackoverflow.com/questions/31919064/powershell-get-the-msi-product-code-out-of-a-msi-file-without-installing
- 从答案中保存了 PowerShell 脚本并对其进行了一些修改以简化管道(脚本代码如下)。
- 将所有 msis 通过脚本传输,并使用有问题的产品代码识别两个 msis。
PowerShell 脚本是:
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[ValidateScript({ ($_ -match "\.msi$") -and (Test-Path $_ -PathType Leaf)})]
$path)
process
{
$comObjWI = New-Object -ComObject WindowsInstaller.Installer
$MSIDatabase = $comObjWI.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$comObjWI,@("$Path",0))
$props = @{ Path = "$path" }
@('ProductCode', 'ProductName') |% {
$Query = "SELECT Value FROM Property WHERE Property = '$_'"
$View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query))
$View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
$Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null)
$props[$_] = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1)
}
New-Object psobject -Property $props
}
最终的命令行是:
PS C:\> $g1 = "1B8CFC46-1F08-4DA7-9FEA-E1F523FBD67F"
PS C:\> $g2 = "F8ADD24D-F2F2-465C-A675-F12FDB70DB82"
PS C:\> dir D:\temp\AttachedContainer\x64\*.msi | .\GetProductCodeFromMSI.ps1 | sls "($g1|$g2)"
@{Path=d:\temp\AttachedContainer\x64\sql_ssms.msi; ProductName=SQL Server Management Studio;
ProductCode={F8ADD24D-F2F2-465C-A675-F12FDB70DB82}}
@{Path=d:\temp\AttachedContainer\x64\sql_ssms_loc.msi; ProductName=SQL Server Management Studio;
ProductCode={1B8CFC46-1F08-4DA7-9FEA-E1F523FBD67F}}
PS C:\>
因此,两个产品代码都位于同一个 SSMS 安装中,并对应于 sql_ssms.msi 和 sql_ssms_loc.msi。两者的产品名称相同 - SQL Server Management Studio。
现在,我不知道 sql_ssms_loc.msi 是什么,但我将尝试使用 F8ADD24D-F2F2-465C-A675-F12FDB70DB82,因为它对应于 sql_ssms.msi。将返回结果。
编辑1
使用 F8ADD24D-F2F2-465C-A675-F12FDB70DB82 似乎有效。