存档

文章标签 ‘UWP’

判断某个 UWP 程序是否已经安装

2021年1月20日 没有评论

在一些代码逻辑里,经常需要判断指定的 UWP程序是否已经安装,其实微软已经提供了相应的API了,无论是Win32还是原生的 UWP程序都可以直接使用,这就是 PackageManager,其文档地址见这里

但是这个类,微软给添加了一个标记 [Windows.Foundation.Metadata.WebHostHidden],所以如果是网页里就无法调用了。为了规避掉这个问题,发现了一个类似hack 的方式。

就是使用 QueryUriSupportAsync 方法,向请求的UWP程序发送一个不存在的协议字符串,然后检查其返回值。返回的是一个枚举类型,也就是说,如果是 0(已安装)或者3(不支持该协议),就表明这个程序对于当前用户来说是已安装的。

下面是一段 js 的调用示例代码:

static queryUriSupport(uri, packageName) {
    return Windows.System.Launcher.queryUriSupportAsync(
        new Windows.Foundation.Uri(uri),
        0,
        packageName
    );
}

简单、暴力、直接,恰好解决了网页里的权限问题。

分类: 日常 标签:

根据进程获取 UWP 的包信息

2020年5月15日 没有评论

最近的一个实验项目,要监控UWP程序的启动。发现了一个比较简单的方式是使用 WMI,当有新的进程被创建时,就可以收到一个消息回调,这样的方式比不断地去轮询要优雅和有效率的多。

但是我们的目标UWP,是采用 WinJS开发的,这样会带来一个问题。就是在进程列表里,它是托管在一个叫做 wwahost.exe 的进程里的。如果有多个类似的程序的话,我们无法简单地区分出来。

所以我们需要进一步获取详细信息以便做过滤,幸好微软提供了配套的东西。我们可以使用一个叫做 UserModelId的东西来对不同的UWP程序做区分。下面是来自微软官方的实例代码(https://docs.microsoft.com/zh-cn/windows/win32/api/appmodel/nf-appmodel-getapplicationusermodelid)。

#define _UNICODE 1
#define UNICODE 1

#include <Windows.h>
#include <appmodel.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>

int ShowUsage();
void ShowProcessApplicationUserModelId(__in const UINT32 pid, __in HANDLE process);

int ShowUsage()
{
    wprintf(L"Usage: GetApplicationUserModelId <pid> [<pid>...]\n");
    return 1;
}

int __cdecl wmain(__in int argc, __in_ecount(argc) WCHAR * argv[])
{
    if (argc <= 1)
        return ShowUsage();

    for (int i=1; i<argc; ++i)
    {
        UINT32 pid = wcstoul(argv[i], NULL, 10);
        if (pid > 0)
        {
            HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
            if (process == NULL)
                wprintf(L"Error %d in OpenProcess (pid=%u)\n", GetLastError(), pid);
            else
            {
                ShowProcessApplicationUserModelId(pid, process);
                CloseHandle(process);
            }
        }
    }
    return 0;
}

void ShowProcessApplicationUserModelId(__in const UINT32 pid, __in HANDLE process)
{
    wprintf(L"Process %u (handle=%p)\n", pid, process);

    UINT32 length = 0;
    LONG rc = GetApplicationUserModelId(process, &length, NULL);
    if (rc != ERROR_INSUFFICIENT_BUFFER)
    {
        if (rc == APPMODEL_ERROR_NO_APPLICATION)
            wprintf(L"Desktop application\n");
        else
            wprintf(L"Error %d in GetApplicationUserModelId\n", rc);
        return;
    }

    PWSTR fullName = (PWSTR) malloc(length * sizeof(*fullName));
    if (fullName == NULL)
    {
        wprintf(L"Error allocating memory\n");
        return;
    }

    rc = GetApplicationUserModelId(process, &length, fullName);
    if (rc != ERROR_SUCCESS)
        wprintf(L"Error %d retrieving ApplicationUserModelId\n", rc);
    else
        wprintf(L"%s\n", fullName);

    free(fullName);
}

整体的代码比较简单,没有什么特别好说的。代码中一共调用了2次GetApplicationUserModelId方法,第一次是为了计算数据的长度,然后第二次根据数据长度重新请求以得到最终的数据。

这就是我为什么讨厌C++的原因,把指针的操作搞这么恶心。

在代码验证后,又发现了另外一个API:IsImmersiveProcess ,通过该函数可以简单地判断一个进程是否是Store类型的程序,在有的场合例如唯一性校验上还是有帮助的。有兴趣可以移步 https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isimmersiveprocess

分类: C++, 一句话, 日常 标签: , ,

Win10 UWP 默认控件样式和模板

2017年1月17日 没有评论

很多时候发现设计给出的文档,系统默认的控件并不能直接使用。对于复杂的控件,可以新写一个自定义控件,但是对于一些很简单的控件,就想在系统默认的控件基础上通过调整样式来实现。

那么我们就需要知道系统默认控件的布局和样式是如何定义的,幸好微软已经给出了 UWP 控件的默认样式和模板。

https://msdn.microsoft.com/zh-cn/library/windows/apps/mt299122.aspx

大家一定要好好保存喔,方便查询使用。

分类: 一句话 标签:

win10修复UWP程序无法联网的问题

2017年1月3日 没有评论

衣服自己洗的办公机已经有一段时间不能使用UWP程序上网了,包括微软自带的应用商店,然而win32桌面程序却没有这个问题,很是恼火。

于是自己写了一个测试程序,发现代码会崩溃在

Windows.Networking.Connectivity.NetworkInformation.GetHostNames();

后来在某一个偶然的时机,发现如果开着 Fiddler的情况下,应用商店就可以正常访问了,太神奇了。这么看起来似乎是系统代理的问题导致,但是其它的UWP程序仍然无法上网。

在网上搜索了一番,各种所谓的重置答案都试过,均没有效果。何况,工作中可是直接和UWP相关,这个出问题了那简直是要了老命了。

趁着元旦放假的工夫,想在家尝试解决,后来还是放弃了。突然灵光一闪,听说windows在每次大的更新后,都会重置系统的一些设置,就寻思着从这块下手。

好在上次下载的14393的系统镜像还在,就以升级的方式重新安装了一遍系统,各位同学这里可要记住,千万要勾选“保留个人文档和程序”选项。升级后,终于恢复正常了。剩下的例如文件关联之类的都是小问题,以后慢慢回填就可以了。

回想起整个事情,可能出现的情况,感觉问题可能是出现在科学上网上面,以前曾经把玩过一段时间的蓝灯程序,后来购买了shadowsocks后,就卸载了蓝灯。估计是卸载没有完全卸载干净导致。

虽然代价有点大,但好歹也是终于修复了这个问题。

分类: 一句话 标签:

WUP Slider控件PointerPressed 和 PointerReleased 事件无法触发

2016年11月9日 没有评论

在最近的某个界面上,我们需要添加一个滑动条Slider,并且根据业务需求获取用户点击和松开鼠标的时机。衣服自己洗发现对于通用控件的PointerPressed 和 PointerReleased 事件是无法触发的。

来自微软方面的解释是这2个事件被Slider的子控件给处理了,导致事实上这2个事件无法被我们拦截处理。

解决方法也很简单:

1,为Slider控件设置ManipulationMode属性,其枚举值为Windows.UI.Xaml.Input.ManipulationModes.TranslateRailsX。

2,为控件添加 ManipulationStarted 和ManipulationCompleted 事件,以代替 PointerPressed 和 PointerReleased 事件。

现在大家就可以解决自己的需求了。

分类: 一句话, 日常 标签: ,