How To Determine When a Page Is Done Printing in WebBrowser Control

Note this post is originally written in 2012. It was lost when moving my web site from Windows Live Spaces to WordPress. I found a dead link to my web site on Stackoverflow and found an archive from archive.org. So here it is the old article, with dead link updated of course.

The printing from a WebBrowser control can be customized by using custom headers and footers ( https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/267240, archived from http://support.microsoft.com/kb/267240) or replacing the default print template. However, using such techniques conflicts with the PRINT_WAITFORCOMPLETION flag, which is used for synchronous printing.

Since Internet Explorer 6.0, the WebBrowser control raises the DWebBrowserEvents2::PrintTemplateTeardown event when a print template has been destroyed. If the printing involves a custom print template, this is a good indicator of print completion. You can create a event handler function in your application for this event to determin if a the WebBrowser control is finished printing a Web page.

MORE INFORMATION

The WebBrowser control launches another thread which hosts another MSHTML document which renders to the printer. When this thread is finished, if a custom print template is involved, the WebBrowser control destroys the print template and raises PrintTemplateTeardown event. This indicates that the WebBrowser control has completed printing the Web page.

If the default print template and the customization of headers and footers are desired, load the template from the source of IExplorer.exe, and use it as a custom template.

To translate the asynchronous printing to synchronous, a message loop need to be created (better if use with a timeout handler) .

BOOL PrintTemplateTeardownFired=FALSE;
//launch printing……
//loop until PrintTemplateTeardown is set to TRUE in the PrintTemplateTeardown event handler
MSG msg;
while (!PrintTemplateTeardownFired&&GetMessage(&msg, NULL, 0, 0) > 0)
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

Reference

Posted in Uncategorized | Leave a comment

Troubleshooting a memory leak

Got called into a memory leak troubleshooting. The application was leaking memory at 1mb per second. In memory profiler, most of the growing memory are used by byte[] and RuntimeMethodHandle (growing at around a million per minute). Initially I thought it is a disposing problem, but the memory occupied by disposable objects does not increase over time.

Looking at the RuntimeMethodHandle instances, I found that it is closely associated with DynamicResolver, whose instance count grows in a much smaller but steady rate. This leads me to kissdodog’s post Windbg + .Net .NET Memory Profiler 排查内存泄露 but kissdodog only located the problem but didn’t give a cause (some coworker got the blame and fixed it).

Then I want to see if there’s any GDI leak and added handle columns to task manager, surprisingly there’s a handle leak growing at 1/2 per second, but then there is no memory map in the code. Under Process Explorer’s handle view,  the leaking handles are revealed as user tokens, which is even more puzzling because the code doesn’t deal with windows logins. But at least this gives me some clear indicator to divide and conquer.

By commenting out portions of code (more like a human binary search) and watching Task Manager religiously, I found the issue is caused by creating XslCompiledTransform in a loop, something KB316775 cited as a design limitation that the dynamic assemblies can’t be unloaded. Obviously this isn’t fixed even in .Net 4.8. The KB was no longer published by Microsoft and I had to read it off a mirror.

Once the problem is located the fix is easy, making those XslCompiledTransform objects singleton solved the issue.

Posted in Uncategorized | Leave a comment

Icepocalypse 2021 冰狱 2021

this is my dairy about the winter storm occurred in Feb 2021.

这是我2021年二月冬季风暴的日记

Feb 13 Sat. 27-30F. Stockpile food (glad I did it). Heard ice building on roads, so instead I shopped on foot. Almost fell because of invisible ice.

2月13日周六 –3-1度。储粮(幸好我这么做了)。听说路上在结冰所以我走路去买菜。还是有看不见的冰,差点摔倒。

Feb 14 Sun. 12-30F Stay home. Freeze warning, keep water dropping. Listened to police radio for a while and heard nothing but crashes. Person is bleeding on Colorado Hills… that is why we advise everyone (to stay off road)…. several vehicles… we need a tow at…. some of the ten fours sound like sigh and two person exchanging (insurance) info was almost a relief. It snowed the night and sounded like raining cats and dogs.

2月14日周日 –11–1度。宅。冰冻警报,保持水龙头滴水。收听了一下警察的通话,基本上都是车祸。科罗拉多丘有人流血。这就是为什么我们建议所有人(不上路)——多辆车——我们这里需要拖车——很多10-4(警用代码,意即收到)听起来像叹气。两个人交换(保险)信息几乎是好消息。晚上下雪的声音听起来像冰雹。

Feb 15 Mon 10-27F. Snow. Wake up by UPS beeps. Turned it off and woke up again by chilling. Realized the power outage could last for a while, announced my unavailability to coworkers. Then saw this outside

2月15日周一 –13–5度。下雪。被不间断电源吵醒。关掉之后回笼觉,又被冻醒。意识到停电可能会很久,通知同事我一时半会不能上班。然后看到外面是这样

IMG_20210215_092903_584IMG_20210215_093902_266IMG_20210215_093036_943IMG_20210215_093020_146IMG_20210215_093007_902

Went out for some warm food. Big mistake. 4-10 inches of snow and sometimes step on curbs. Wandering dogs. HEB and everything else closed. No cell signals most of the way. Good that almost nobody is driving and for the rest they drive really slow. And snow blindness is a thing.

出去吃点热的——结果是个错误。4-10寸的雪,有时候深一脚浅一脚踩到人行道边。流浪狗。HEB和其他店都关门。路上基本没信号。幸好基本没人开车,开车的也开得很慢。发现雪盲症。

IMG_20210215_114204_266IMG_20210215_105209_154IMG_20210215_105205_772IMG_20210215_104437_903IMG_20210215_103601_631IMG_20210215_103120_485IMG_20210215_103116_952IMG_20210215_101415_919IMG_20210215_101401_288IMG_20210215_095701_025IMG_20210215_095555_479IMG_20210215_095550_763IMG_20210215_095315_934IMG_20210215_095314_903IMG_20210215_095314_872IMG_20210215_094641_666IMG_20210215_095315_934IMG_20210215_094350_810IMG_20210215_094132_686

Power briefly went back for about an hour after 3pm. but that is just enough for cooking and charging power banks.

三点之后短暂恢复供电约一小时,只够做饭和充电宝的。

IMG_20210215_151954_301

Feb 16 Tue 6-25F. Cloudy. Room temperature dropped so much that my dog was crying. So took her to the warmest place in the room.

2月16日周二 –13–4度。多云。室温降到狗狗都在哭了,所以把她移动到房间里最温暖的地方。

DSC_0276

and dress her with a cut rice bag

然后用米袋子剪了一个外套

IMG_20210218_150739_012

Power back again after 3pm for 40 minutes. Cooked and charged.

3点之后又来了40分钟电,做饭和充电。

Started refreshing ERCOT web site. The 60KMW goal was never reached, only briefly touched 50KMW.

开始刷德州电力可靠委员会(ERCOT )网站。60吉瓦的恢复目标当天没达到,仅仅短暂地达到了50吉瓦

Feb 17 Wed. 23-32F. Snow. From the ERCOT report, the grid almost crashed in the morning with almost no margin between generation and load. Generation picked up in the afternoon to 55KMW but power didn’t come back at all today. Did some cleanup, help neighbor and got helped by a neighbor with a hammer.

2月17日周三。-5-0度。雪。根据ERCOT的报表,电网因为发电容量和负载差距太小早上差点挂掉。下午发电容量达到55吉瓦但是整天都没来电。帮邻居清了一下雪,另一个邻居过来帮忙,借给我一个锤子。

 IMG20210217131433DSC_0277momo1613599849553

Pipe started to burst everywhere and I lost water today.

全市水管到处漏,停了水。

Feb 18 Thu. 19-32F. Snow. Slept up early yesterday and woke up at 1am. Then saw this:

2月18日周四。-7-0度。雪。昨天睡早了,早上一点钟就醒了,看到外面是这样

IMG_20210218_011557_980

Brightest night in years.

近年来最亮的晚上。

Power went back on around 2 am. The ERCOT price map is almost green now, with a small deep blue spot indicating negative power prices near Houston. But without water I can no longer cook. Decided to get some water from HEB. My car was actually frozen up like this

两点钟恢复通电。ERCOT的价格地图基本变绿了,只有休斯顿附近一点蓝,意味着电价是负的。但是没水我现在做不了饭。决定去HEB买点水。我的车居然被冻上了,像这样

IMG_20210218_100350_776

So I decided to take a bus which is running for the first time since Monday. The trees along the way are down by the snowstorm:

所以决定坐周一以来第一次运转的公车。路上的树被暴风雪击倒了

IMG_20210218_100806_520IMG_20210218_100748_657IMG_20210218_100743_350IMG_20210218_100740_820IMG_20210218_100739_882

They looked like this in the summer

它们今年夏天是这样的

DSC_0125DSC_0124DSC_0123DSC_0122DSC_0121

On the way there was a pond

路上还有个池塘

IMG_20210218_103101_589IMG_20210218_103405_067

I wonder where the ducks went. And this was the pond in the summer

里面的鸭子不知道去哪里了。这个池塘夏天是这样

DSC_0155

At HEB there’s a long line… and thick ice.

在HEB有很长的队,和很厚的冰

IMG20210218114144

Someone actually fell and one helping on the left almost fell too when running over.

这位老兄居然滑倒了,左边那个去帮忙的跑过去的时候也差点滑倒。

DSC_0278

Got in after an hour of waiting in line. Unfortunately there was no waster or milk on the shelf. Settled for some juice and soymilk.

等了一个小时才进去,不幸的是没有水和牛奶。勉强买了果汁和豆浆。

Icicle fell off and scared a bus rider. But it is a good sign that ice was melting.

一个公车乘客被掉下来的冰凌吓到,但是冰在化是个好消息。

My apartment offered its pool water for toilet use. Nice for them.

我的公寓提供游泳池的水冲厕所,不错。

ERCOT reports 60KMW generation for the first time and the price map is sky blue, means everything normal again.

ERCOT报告首次达到60吉瓦,整个价格地图都是蓝的,这意味着恢复正常。

Posted in Uncategorized | Leave a comment

微软拼音卡顿的问题

微软拼音最近每次激活的时候都要卡上个几分钟。而且不是一个程序只卡一次,中英文切换之后还会继续卡。

用了Process Monitor跟踪了一下,发现每次切换中英文的时候,微软拼音都会在%appdata%\Microsoft\InputMethod\Chs下面创建一个名字为UDPXXXX(这里XXXX是16进制数字).tmp的文件,我这个目录下有六万五千多个这样的文件。从命名风格来看,很明显是在调用GetTempFileName,而这个函数有65535个文件的限制,不删除文件的话,第65536次调用会失败,应该是微软拼音没有处理好调用这个函数失败的情况,也没有删除临时文件的代码,就卡住了。

目前的绕过这个问题的方法是把

del %appdata%\Microsoft\InputMethod\Chs\*.tmp /q

加到每日备份脚本。

已经向微软反映了这个问题。不知道微软为什么临时文件不放%TEMP%放应用程序目录下,以及为什么不定期清理自己创建的临时文件。

Posted in Uncategorized | Leave a comment

Today’s fake email of the day

Today’s fake email of the day

Hi Dear,

How are you doing hope you are fine and OK?

I was just going through the Internet search when I found your email address

…….

So you care about an article titled “
Trap CtrlAltDel; Hide Application in Task List on Win2000/XP” in 2020 and downloaded its source code, but still don’t know my name?

Also when I read the message header (it is called view source in hotmail or view original in gmail)
From: Lisa Williams lw716545@gmail.com
Reply-To: lisawilam@yahoo.com
Message-ID: 1900588789.741179.1601566380447@mail.yahoo.com
References: 1900588789.741179.1601566380447.ref@mail.yahoo.com
X-Mailer: WebService/1.1.16718 YMailNodin Mozilla/5.0 (Windows NT 6.1; rv:81.0) Gecko/20100101 Firefox/81.0
Content-Length: 572
X-IncomingHeaderCount: 14
To: Undisclosed recipients:;
Return-Path: lw716545@gmail.com

So this is a bulk mail, I am BCCed. Kinda strange to do for a letter that express love interest. But Kudos to keep your Firefox version up to date! Although the scammer can lie here too if wanted to just like everywhere else, there is nothing really beneficial to say you mailed it from Microsoft Outlook Express.

Also in the mail header:

Received-SPF: SoftFail (protection.outlook.com: domain of transitioning gmail.com discourages use of 74.6.132.41 as permitted sender)

I wonder why…

Posted in Uncategorized | Leave a comment

Finding the right ruby version

I am installing eHMP on Centos 7. Centos 7 has ruby 2.0 out of box, thus the install

chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

fails with

rb-notify version 0.10.0 needs Ruby 2.2.2 or newer

Following the instructions at https://noobient.com/2019/02/12/installing-rvm-and-ruby-on-centos-7/ I got ruby 2.7 installed. However

sudo chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

fails with the same error.

run

ruby –version

shows that rvm has no effect on sudo. I am still running the script against Ruby 2.0

Supposedly I can sudo and install rvm there, but rvm complained and suggested me to use rvmsudo instead. Then I tried it, rvmsudo doesn’t carry over my environment, even $HOME, thus the script still fails.

After searching for awhile I found a walkaround

rvmsudo bash -c “HOME=$HOME; exec bash” chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

This gets the home directory passed to the script, now the script is complaining

STDERR: ERROR:  While executing gem … (OptionParser::InvalidOption) invalid option: –no-rdoc

The script was pretty old, I know. I have no time to fix the script, so I need to downgrade the ruby version. After testing for each version I settled for 2.3.

rvm install 2.3

rvm use 2.3 –default

sudo gem update –system 2.3

Now the script runs successfully.

Posted in eHMP | Tagged | Leave a comment

Fix sphinxcontrib-googleanalytics on Sphinx 1.8

The Google Analytics extension from

python -m pip install  sphinxcontrib-googleanalytics

does not work on Sphinx 1.8. When I run it, I get the following error

Could not import extension sphinxcontrib.googleanalytics (exception: cannot import name ‘ExtensionError’ from ‘sphinx.application’ (c:\python37\lib\site-packages\sphinx\application.py))

Fix is to change C:\Python37\Lib\site-packages\sphinxcontrib\googleanalytics.py Line 4

from

from sphinx.application import ExtensionError

to

from sphinx.errors import ExtensionError

After that I get another warning

WARNING: extension ‘sphinxcontrib.googleanalytics’ returned an unsupported object from its setup() function; it should return None or a metadata dictionary

Fix is to change the last line from

return app

to

return {‘version’: ‘0.1’}

Posted in Uncategorized | Leave a comment

Blinking wifi icon and black screen on Surface 2

This is the second time I run into this problem after a Windows Update. First time was halfway through last year’s Microsoft MVP Summit and I had to Remote Desktop to my home machine with a spare android tablet and Bluetooth keyboard/mouse to get access to Windows apps.  Good that the summit wifi was amazing but a Surface 2 with touch cover was way easier to carry around than the combination of tablet/keyboard/mouse.

I got around the problem by manually uninstalling  KB3033055 with dism remove package in recovery console command prompt and hide the update afterwards. But recently I got the black screen with blinking wifi icon, again after installing a bunch of Windows Updates.  So it probably has multiple causes.

Anyway this is my way to get update working as of July 2018:

1 factory reset

2 go through initial setup (wifi, microsoft account etc)

3 search for update, this would take a while

4 uncheck everything, only install the 2015 firmware update.

5 turn wifi off, reboot.

6 download kb2919355, KB3173424, KB3172614 and KB3097667 on another machine (you need the ARM edition of those updates, not x86 or x64 so the file names should contain arm) to a usb drive.

7 install in the order of kb2919355, KB3173424, KB3172614 and KB3097667 from usb drive, reboot

8 turn wifi back on and search for updates.

9 install remaining updates and reboot

Microsoft says August 14, 2018—KB4343898 (Monthly Rollup) fixes an issue with KB3033055 which has the same syndrome. Not sure if this has anything to do with KB3097667. Hopefully this is the end of black screen with blinking wifi icon for Surface owners.

Posted in Uncategorized | Leave a comment

如何在64位win10的VS2017环境下搭建汇编环境

用户AcmeContracted安装masm32失败,所以想知道是否能集成masm64到Visual Studio 2017中

VS里面masm不是单独的,是C++工具集的一部分,而在VS2017里C++工具集不是默认安装的,所以要先安装C++工具集。

安装完之后创建个C++的Win32命令项目,然后在解决方案浏览器里选中项目节点,右键,选择Build Dependencies->Build Customisations,在弹出的对话框里选中masm,然后选择OK。这会使得你的项目里的新asm文件使用ml或者ml64编译(具体使用哪个取决于你的项目当前编译配置是32位还是64位)。

另外VS里面新建文件的选择里没有asm文件的模板,随便选个纯文本格式(.h,cpp,.txt,.html都行)的来替代,建完了把扩展名改成asm,然后在解决方案浏览器里右键点文件打开文件属性对话框,把项目类型改成Microsoft Macro Assembler。确定之后这个文件就会用masm来编译了,可以重新打开文件属性对话框检查编译时使用的命令行。

如果的项目在启用asm支持之前已经有了asm文件,这些asm文件的编译设置不会被VS2017版的覆盖(因为有可能在使用第三方的asm)。如果没有值得保留的旧编译设置,可以在解决方案浏览器里右键点文件,选择排除(注意不是删除),再把文件加回来。

Posted in Uncategorized | Leave a comment

Can we run 32 bit and 64 bit code in the same process?

User redstone001 wants to know if it is possible to run 32 bit and 64 bit code in the same process – maybe in a different thread?

As Betteridge’s law of headlines say, any news ending with a question mark can be answered with the word no. But this isn’t news, so … the answer is … yeah? Kind of.

The way that Windows implements a 32 bit emulator (e.g. making  Program Files (x86) appear as Program Files to 32 bit processes) is to load 64 bit system dlls in 32 bit code… but specially crafted 64 bit dlls indeed. To be callable from a 32 bit process, everything they generate have to be 32 bit compatible. E.g. do not provide access outside of the x86 memory address space, and zero out higher 32 bit of handles etc. The way it is written is practically creating 64 bit dlls that enjoy none of the 64 bit benefits, but become much slower and heavier thanks to marshal 32 bit calls to 64 bit before calling other system dlls. Because there is no up side except compatibility, Windows only allows its own 64 bit DLLs to be callable inside a 32 bit process. If you want to reuse your code written for a different CPU architecture, it would be much faster to run a separate process and do interprocess communication.

Posted in Computers and Internet | Leave a comment