存档

文章标签 ‘c#’

无头浏览器 PuppeteerSharp

2023年9月3日 没有评论

在研究无头浏览器的时候,发现了一些不错的工具,例如 phantomjs 就可以让你以前端 js 脚本的方式来操作页面,以满足一些自动化测试方面的需求。后来又发现了 puppeteer,有很多开发语言的实现。

而今天提及的 PuppeteerSharp 就是 .Net 的实现。可能我执念太深,总觉得 Net 是相当不错的选择。

PuppeteerSharp 是一个控制无头Chrome 浏览器的库,它允许开发者通过编程方式模拟浏览器行为,执行网页操作,截取网页截图,获取网页内容,可以把网页转换成PDF等等。

截图

using var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(
new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.GoToAsync("http://www.google.com");
await page.ScreenshotAsync(outputFile);

也支持设置页面的尺寸

await Page.SetViewportAsync(new ViewPortOptions
{
Width = 500,
Height = 500
});

生成 pdf 文件

using var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions {Headless = true});
await using var page = await browser.NewPageAsync();
await page.GoToAsync("http://www.google.com"); // In case of fonts being loaded from a CDN, use WaitUntilNavigation.Networkidle0 as a second param.
await page.EvaluateExpressionHandleAsync("document.fonts.ready"); // Wait for fonts to be loaded. Omitting this might result in no text rendered in pdf.
await page.PdfAsync(outputFile);

动态注入 html 元素

await using var page = await browser.NewPageAsync();
await page.SetContentAsync("My Receipt");
var result = await page.GetContentAsync();

执行脚本

await using var page = await browser.NewPageAsync();
var seven = await page.EvaluateExpressionAsync("4 + 3");
var someObject = await page.EvaluateFunctionAsync("(value) => ({a: value})", 5);
Console.WriteLine(someObject.a);

等待某个选择器

using (var page = await browser.NewPageAsync())
{
await page.GoToAsync("https://www.baidu.com");
await page.WaitForSelectorAsync("div.main-content")
await page.PdfAsync(outputFile));
}

等待函数的执行

using (var page = await browser.NewPageAsync())
{
await page.GoToAsync("https://www.baidu.com");
var watchDog = page.WaitForFunctionAsync("()=> window.innerWidth < 100");
await page.SetViewportAsync(new ViewPortOptions { Width = 50, Height = 50 });
await watchDog;
}


分类: C#, 日常 标签:

SharpShell

2023年7月29日 没有评论

最近在搜索使用C#来实现文件扩展模块,即右键属性对话框里的设置,这个基本上是 com 实现的,当然就是支持 C++,这个东西对我来说过于复杂了,全网搜索了下,最后发现了一个项目满足自己的需求,这里推荐给大家,希望大家喜欢。

https://github.com/dwmkerr/sharpshell#property-sheet-extensions

分类: 一句话, 工具 标签:

.Net 6 使用 Winform API

2022年4月6日 没有评论

最近的项目在计划切换到使用 .net6 来编译,虽然微软官网有提供转换工具,但是作为强迫症人群,还是选择了从0开始创建项目,在创建后,再拷贝相关代码。

很显然的,有一些函数或者命名空间在 .net6里并无法找到对应的,官方也提及,可以先试一试 Microsoft.Windows.Compatibility 这个 NuGet 包。VS2022 的右键菜单里还提供了一个很实用的功能,就是移除未使用的引用,所以大家可以放心地先引用。

如果你的项目使用了注册表,那么就需要添加 Microsoft.Win32.Registry 这个 NuGet 包。

很可惜,我的代码里使用了 System.Windows.Forms 的API去判断电源是 DC 还是 AC 模式,上述都没有很好地解决问题。

经过一番搜索,发现下面的解决方式,
1、右键卸载项目
2、编辑项目的 csproj 文件,在 PropertyGroup 节点下添加 true和true 这两个配置。
3、设置 .net6.0属性,替换为 .net6.0-windows,如果有其它的编译需求,例如 net461也可以加进去,以英文分号分割。
4、重新加载项目

当然,这么做也意味着编译后的二进制文件并不能在 Linux 平台上运行,仅仅意味着使用 .net6编译而已,不过这个对于衣服自己洗来说已经足够了,本身项目就是跑在 windows 平台上的。

分类: 日常 标签:

获取Firefox当前打开的标签页地址

2020年9月3日 没有评论

说起三大浏览器,当然少不了火狐浏览器了。我们继续探讨如何获取该浏览器的当前标签页地址。

首选我们需要下载 NDde.dll 这个文件,添加其引用。

using NDde.Client;

DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
dde.Disconnect();

MessageBox.Show(url);

虽然是要借助于第三方的库,但是可用快速实现 Demo 也是蛮不错的选择了。

关于NDde,原来的官网已经停止维护了,我看Github上有一个fork该项目的地址,https://github.com/anphonic/NDde 大家可以移步看看。

分类: 一句话 标签:

获取IE当前打开的标签页地址

2020年8月3日 没有评论

在前面的文章中,有分享获取chrome标签页地址的代码。现在,再来看看如何查找到 IE标签页的地址。

首先,我们需要添加2个引用:

1、引用c:\windows\system32\SHDocVw.dll

2、引用COM组件Microsoft HTML Object Library

SHDocVw.ShellWindows sws = new SHDocVw.ShellWindows();
StringBuilder sb = new StringBuilder();
foreach (SHDocVw.InternetExplorer iw in sws)
{
	sb.AppendLine(iw.LocationURL);
}
MessageBox.Show(sb.ToString());

这里iw是所有一打开的IE,包括IE本身或者基于IE内核的企业浏览器,还包括我的电脑打开的所有窗口。
你可根据实际情况筛选掉 file 开头的地址。http开头的都是当前打开的IE的地址。

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

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)  
  {   
    // 屏幕解锁  
  }  
}

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

分类: 日常 标签:

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 事件。

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

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

RestSharp 访问https网站出错的问题

2016年6月20日 没有评论

工作中的一个小工具,使用了RestSharp 来向JIRA系统中同步信息。前段时间说是安全升级,更新了jira的ssl证书,结果就导致了同步流程的失败,后来发现原因就在于ssl证书使用了自签名的ssl证书。不知道为什么,我想到了12306的自签名证书。

移除NuGet引用,下载最新版本的源码,重新编译还是一样的问题。

网上也有很多人询问,大部分都可以解决问题的方法如下:

client.RemoteCertificateValidationCallback = new RemoteCertificateValidationCallback((a,b,c,d)=> { return true; });

不过对于我这边没有效果。后来终于在某个小帖子上发现了一句话,一尝试果然解决了问题。

在需要发送请求前,需要先设置协议类型:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

从感觉上来说,这个问题应该是仅仅和服务器设置有关,不一定适合所有的玩家。不对,是同学,最近玩游戏有点过份了。

分类: 一句话 标签: , ,

CodeLite命令行中文显示乱码

2016年2月16日 没有评论

有时候想快速写一段C++代码来验证某个功能,感觉使用VS就过于重量级了,关键是衣服自己洗比较洁癖,不喜欢看到有无用的工程项目。所以一直想有一个轻量级的编辑器可以快速编译验证。

于是衣服自己洗发现了CodeLite 和 CodeBlock这2个跨平台,相对轻量的工具。

使用过程中,发现CodeLite的命令行输出中中文显示乱码,一开始还以为自己是软件没有安装好,重新下载安装还是不行。后来经过一番搜索,网上观点认为是 G++ 的问题,需要额外添加编译选项。

选择工程项目,右键属性,切换到Compiler,在 C++ Compile Options 里添加一个选项  -fexec-charset=GBK;  即可。其实还可以把这个配置单独新增进去,以后就只用勾选就可以了。

特别需要说明,设置完成后,需要把项目清理重新编译,不然看不到效果,衣服自己洗在这里被坑了好几次了。

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

win32 程序窗体居中

2015年12月20日 没有评论

C#对于窗体居中很简单,只需要简单设置一个属性就可以了,但是对于C++,还需要额外的写点代码。下面是衣服自己洗分享的代码,可以直接拷贝到项目中。

inline static BOOL CenterWindow(HWND hwndWindow,bool isDesktopParent = true)
{
HWND hwndParent;
RECT rectWindow, rectParent;

hwndParent = isDesktopParent ? GetDesktopWindow() : GetParent(hwndWindow);

//make the window relative to its parent
if (hwndParent != nullptr)
{
GetWindowRect(hwndWindow, &rectWindow);
GetWindowRect(hwndParent, &rectParent);

int nWidth = rectWindow.right – rectWindow.left;
int nHeight = rectWindow.bottom – rectWindow.top;

int nX = ((rectParent.right – rectParent.left) – nWidth) / 2 + rectParent.left;
int nY = ((rectParent.bottom – rectParent.top) – nHeight) / 2 + rectParent.top;

int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

//make sure the window never moves outside of the screen
if (nX < 0) nX = 0;
if (nY < 0) nY = 0;
if (nX + nWidth > nScreenWidth) nX = nScreenWidth – nWidth;
if (nY + nHeight > nScreenHeight) nY = nScreenHeight – nHeight;

MoveWindow(hwndWindow, nX, nY, nWidth, nHeight, FALSE);

return TRUE;
}

return FALSE;
}

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