如何从带通配符的字符串中获取 Appx 全名?

How to get Appx full name from a string with wildcard?

在 Powershell 中,此命令 Get-AppxPackage *name* 可以显示包的完整详细信息。是否可以使用任何 Windows API 来获得相同的结果?

我看过这个 and details of all Package Query APIs。但它们都需要完整的包名称或 运行 包进程句柄。这些不适用于通配符字符串。

例如,如果我安装了这个包 Microsoft.WindowsCalculator_8wekyb3d8bbwe 我可以使用 Get-AppxPackage *Calculator* 命令获取详细信息。任何 Windows API 都可以吗?我想避免 system()CreateProcess() 之类的事情。

您可以浏览应用程序文件夹并从 xml 清单文件中获取名称。需要管理员权限才能访问应用程序文件夹。

此示例列出了名称中包含 "xbox" 的所有应用。该逻辑可以很容易地适应 C# 或其他语言。

$appNameFilter = '*xbox*'

[System.Collections.Generic.List[string]]$appList = @()

$apps = Get-ChildItem 'C:\Program Files\WindowsApps' -Recurse -Filter 'AppxManifest.xml'

foreach( $app in $apps ) {

    $xml     = [xml](Get-Content $app.FullName)
    $appName = $xml.Package.Properties.DisplayName

    if( $appName -like $appNameFilter -and !$appList.Contains( $appName )) {
        $appList.Add( $appName )
    }
}

$appList

感谢@f6a4 的回答。我采取了相反的方式来实现我的目标。这是我的程序:

我找到一个 answer 来查找 Powershell 中 Get-AppxPacage cmdlet 后面的 DLL。使用此命令(Get-Command Get-AppxPackage).dll,Powershell 显示 DLL 文件路径如下:

C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.Windows.Appx.PackageManager.Commands\v4.0_10.0.0.0__31bf3856ad364e35\Microsoft.Windows.Appx.PackageManager.Commands.dll

在文件资源管理器中转到该路径并在任何 .NET 反编译器中打开 Microsoft.Windows.Appx.PackageManager.Commands.dll 文件。这里我使用了dnSpyGet-AppxManifest 命令部分具有此 C# 代码:

protected override void ProcessRecord()
{
    AppxPackage appxPackage = this.packageManager.FindPackage(this.Package);
    if (appxPackage != null)
    {
        string str;
        if (appxPackage.IsBundle)
        {
            str = "\AppxMetadata\AppxBundleManifest.xml";
        }
        else
        {
            str = "\AppxManifest.xml";
        }
        using (FileStream fileStream = new FileStream(appxPackage.InstallLocation + str, FileMode.Open, FileAccess.Read))
        {
            using (XmlReader xmlReader = XmlReader.Create(fileStream, new XmlReaderSettings
            {
                DtdProcessing = DtdProcessing.Ignore
            }))
            {
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(xmlReader);
                base.WriteObject(xmlDocument);
            }
        }
    }
}

我将该代码转换为与 Windows API 类似的 C 代码。这是代码片段:

ExpandEnvironmentStringsW(L"%ProgramFiles%\WindowsApps", Buffer, MAX_PATH);

swprintf(FirstFile, MAX_PATH, L"%ls\*", Buffer);

hFile = FindFirstFileW(FirstFile, &fileInfo);
if (hFile != INVALID_HANDLE_VALUE) {
    do {
        if (wcsstr(fileInfo.cFileName, AppxName) != 0) {
            memcpy(PackageName, fileInfo.cFileName, MAX_PATH);
        }
    } while (FindNextFileW(hFile, &fileInfo) != 0);
}