存档

‘日常’ 分类的存档

获取chrome当前标签页的地址

2020年7月3日 没有评论

在评估一个demo的时候,有一个需求是要获得用户当前浏览器正在访问的网页是否命中我们的白名单,如果是的话,则会开启一系列的优化模式设定。

经过一番搜索,发现可以使用微软的自动化测试框架来间接满足我们的要求。

MS UI Automation是MSAA技术的一个替代品:即让控件和应用程序具有更好的可达性(accessible)。简单来讲,它就是几个dll,提供了一套API和Interface,及其相应的模式,让软件的开发者遵循该模式去实现相应的interface,从而软件的使用者(不仅仅是客户,还包括例如测试人员想编写一些自动化测试代码来完成程序相关的业务逻辑)能更好的使用该软件。

在UI Automation中,所有的窗体、控件都表现为一个AutomationElement, AutomationElement 中包含此控件或窗体的属性,在实现自动化的过程中,我们通过其相关属性进行对控件自动化操作。对于UI用户界面来说,所有显示在桌面上的UI,其实际是一个UI Tree,根节点是desktop。我们可以使用UI Spy或者是SPY++来获得Window和Control的相关信息。在UI Automation里,根节点表示为AutomationElemnet.RootElement. 通过根节点,我们可以通过窗体或控件的Process Id、Process Name或者Window Name找到相应的子AutomationElement,例如 Dialog、Button、 TextBox、Checkbox等标准控件,通过控件所对应的Pattern进行相关的操作。

Process[] procsChrome = Process.GetProcessesByName("chrome");

if (procsChrome.Length <= 0)
{
    Console.WriteLine("未找到 chrome 进程");
}

foreach (Process proc in procsChrome)
{
    // the chrome process must have a window 
    if (proc.MainWindowHandle == IntPtr.Zero)
    {
        continue;
    }

    AutomationElement root = AutomationElement.FromHandle(proc.MainWindowHandle);
    Condition conditions = new AndCondition(
        new PropertyCondition(AutomationElement.ProcessIdProperty, proc.Id),
        new PropertyCondition(AutomationElement.IsControlElementProperty, true),
        new PropertyCondition(AutomationElement.IsContentElementProperty, true),
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)
    );

    AutomationElement bar = root.FindFirst(TreeScope.Descendants, conditions);

    if(bar != null)
    {
        var url = bar.GetCurrentPropertyValue(ValuePatternIdentifiers.ValueProperty).ToString();
        Console.WriteLine(url);
    }
}

不过,根据网上的说法,这样的代码只在v53以上版本才有效果。目前浏览器版本都7、80了,对于一个demo而言,应该可以满足大部分要求了。

分类: 日常 标签:

图像阈值处理cv2.threshold函数

2020年6月29日 没有评论

最近做图片处理时,看别人代码使用了 opencv 的阈值函数 threshold,网上搜索了下这个函数的使用说明。

简单地讲,所谓阈值就是说如果待处理的数据达到了某个临界点后,如何处理的方式。

python里定义如下:
cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

参数说明如下:
src:源图片
thresh:阈值,取值范围0~255
maxval:填充值,取值范围0~255
type:阈值类型,表示的是这里划分的时候使用的是什么类型的算法,常用值为0(cv2.THRESH_BINARY)

图中(x,y)表示的是图像中的坐标
INV 表示的是取反
一般的(BINARY)效果是:
将一个灰色的图片,变成要么是白色要么就是黑色。(大于规定thresh值就是设置的最大值(常为255,也就是白色))

下面是几个方式的效果图

THRESH_BINARY
THRESH_BINARY_INV
THRESH_TRUNC
THRESH_TOZERO
THRESH_TOZERO_INV

实际操作上来说,建议传入已经灰度处理后的图像。

分类: Python, 日常 标签:

根据进程获取 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++, 一句话, 日常 标签: , ,

由于管理员设置的策略,该磁盘处于脱机状态

2020年4月15日 没有评论

服务器在安装了一次系统更新后,数据盘不见了。跑到后台看磁盘还在,于是进磁盘管理看,可以看到那块磁盘,但是未加载。提示由于管理员设置的策略,该磁盘处于脱机状态。

按照网上的说法,非常忐忑低执行了操作,担心数据一下子没有了。后来成功加载回来了,数据没有丢失。

1.运行:cmd
2.输入:diskpart 回车进入diskpart命令行
3.DISKPART> san
4.DISKPART> san policy=onlineall
5.DISKPART>list disk
6.DISKPART> select disk 1
7.DISKPART>attributes disk clear readonly
8.DISKPART>online disk

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

正式在家远程办公

2020年3月12日 没有评论

节前放假的时候,忘记带电源线,没有想到这个就是噩梦的开始哇。

由于疫情的影响,又是封城,结果一直买不到电源线。直到最近,各个省市逐渐复工,快递才开始工作。

终于收到了电源线。

可以干活了,可以当键盘侠了。

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

npm 镜像源管理

2020年2月12日 没有评论

最近的项目使用了 nodejs,有时候在安装 npm 包时,下载速度那个捉急哇。

尝试了搜索下,果然发现了淘宝的镜像源,果断换之。

首先,查看当前的 npm 源地址,输入 npm config list

不出意外的话,可以看到输出里包含这样的结果:metrics-registry = “http://registry.npm.nodejs.org/”

我们改为淘宝的镜像:npm set registry https://registry.npm.taobao.org/

后来再安装 npm 包就很快了,这点还是要谢谢阿里的同学。

如果有一天,各位肉身到了国外,用不上了,就可以使用 rm 命令删除掉: npm config rm registry

祝各位前程似锦。

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

win10 英文系统控制台中文显示乱码

2019年11月1日 没有评论

最近写了一个console的小工具,但是发给对方,在界面上中文显示乱码。原因也很简单,就是因为对方使用的是英文系统,其语言代码页用的是英语。可以通过下面的方法来解决。

打开控制面板,切换图标按照类型显示,选择“时钟、语言和区域”链接,再选择“区域”,切换到最后一个“管理”选项卡。

在对话框的底部,有一个“更改系统区域设置…”的按钮,点击后会弹出一个新的对话框,在里面选择“中文(简体,中国)”,然后就一路确认,最后按照提示重启系统。

系统重启完成后,再运行程序,就可以正常显示中文了。

分类: 日常 标签:

C#中接收系统屏幕锁定和解锁的事件

2019年10月22日 没有评论

最近在做一个 demo,需要去监听用户是否有锁屏,或者注销操作。用 C++ 可以去接收特定的消息去处理,但我总觉得 C# 应该有更好的实现。

搜索了一番,果然找到了,还是微软好呀,啥都为我们考虑到了,搞了一点动力都没有。

为了实现这样的效果,需要使用 Microsoft.Win32.SystemEvents 类,他提供了一些事件,我们可以注册这些事件来完成自己的需求。

Microsoft.Win32.SystemEvents.SessionSwitch += new Microsoft.Win32.SessionSwitchEventHandler(SystemEvents_SessionSwitch);  
void SystemEvents_SessionSwitch(object sender, Microsoft.Win32.SessionSwitchEventArgs e)  
{  
  if (e.Reason == Microsoft.Win32.SessionSwitchReason.SessionLock)  
  {   
    // 屏幕锁定  
  }  
  else if (e.Reason == Microsoft.Win32.SessionSwitchReason.SessionUnlock)  
  {   
    // 屏幕解锁  
  }  
}

是不是很简单?都不需要实例化类。但是需要注意的是,因为是静态类,所以在必要的时候,需要显示地去取消事件注册,以避免内存泄露。

分类: 日常 标签:

下载 Google Drive 文件

2019年9月11日 没有评论

最近在跟进一些和机器学习相关的事情,就觉得自己的数学知识实在是太渣了,有一些还给了老师,剩余的部分不够用。

诶哟喂,这个公式怎么就推导出这个结论了?

扯远了,有一些数据集是放在墙外的,要下载回来就颇费点功夫了。因为我用的梯子是免费的,服务器后端貌似做了些限制,导致在下载大文件的时候无法成功下载。

有的模型或者数据就放在别人的Google Drive里,中转到自己的空间里就想着怎么可以下载回来。

在网上发现了一个工具 Gdrive,是命令行方式的,虽然官方说不再支持了,但是看起来似乎够简洁。

首先,去 https://github.com/gdrive-org/gdrive/releases 下载和自己系统对应的版本,然后给移动到 /usr/bin 下 ,为其添加执行权限, chmod +x /usr/bin/gdrive 。

首先运行 gdrive about 命令,会显示一个链接地址,该地址即为验证链接,复制地址,在浏览器里打开(这里需要翻墙),登录成功,给予gdrive 访问权限后,浏览器界面里会显示一串字符。

复制该字符,然后粘贴到命令行里,回车。如果会显示云盘的大体信息时,就表明前置依赖都已经配置好了。

后面就很简单了,都是常用命令:

gdrive list 显示根目录下的文件夹和文件

gdrive upload xxx 上传文件到云盘里

gdrive download xxx 下载文件或者文件夹到本地

gdrive mkdir xxx 创建目录

我这里试了一下,貌似通过别人分享的内容,使用 list 参数是没有列出来的。这意味着白折腾了,囧。

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

增驾报名

2019年8月13日 2 条评论

距离上一次报名已经过去了好几年了,可是我仍然不会开车。嗯,哪种车都开不好。

小电驴已经陪伴了我好几个年头了,现在电池就需要一天一充了,而且最关键的是有的时候道路颠簸下,就直接断电了,也不清楚具体问题出现在哪里。

现在随着政策要求越来越严格,搞一个摩托车作为备选是明智的。 上个月终于去报名了,刚交完钱,学费就降了400软妹币。

上完法培课,又去考了科目一,现在就卡在科目二了。诶,头疼。要是可以直接买一个该多好呀。

分类: 日常 标签: