发篇技术文档,大家猜猜我要干啥? / 启动应用程序并获得应用程序的主窗体句柄

本人原创加STEEMIT首发
不过原创的时间略为久远,至少十几年前了,那时候还是比较好学的。
《启动应用程序并获得应用程序的主窗体句柄》


Image source

摘要

通过使用CreateProcess、EnumWindows、GetWindowThreadProcessId等函数,实现启动应用程序并获取应用程序主窗体句柄。

常规的方法与问题

一般来讲,如果我们的程序要对其它程序进行操作,我们首先是通过应用程序的标题或者类名来查找应用程序(最顶层)窗体,并获得窗体句柄。然后通过发送消息来控制其它应用程序的行为。

Platform SDK中函数原型如下:

1
2
3
4
HWND FindWindow( 
LPCTSTR lpClassName,
LPCTSTR lpWindowName
);

The FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

通过这种方式进行查找,时常会遇到一些问题:

1) 首先必须知道窗体类或者窗体标题。
实际上,我们并不是总是事先知道窗体标题,或者知道窗体类。
2) 应用程序必须已经打开
有时候,应用程序并没有启动。
那么我们需要先启动应用程序,然后再使用FindWindow查找。
3) 如果应用程序已运行多个实例,则查找到的第一个实例未必是我们想要的实例。
我们需要查找到的,就是我们想要的。
4) 对于复杂的窗体标题,容易输入错误
我们需要一种简洁的方式,而不是每次去看窗体标题,然后再输入标题。

有没有一种方式能解决上述问题呢?

如果我们可以先启动应用程序,然后返回应用程序的窗体句柄,这样的话就会避免上述的种种问题。

CreateProcess启动应用程序

CreateProcess函数原型

我们可以通过CreateProcess来启动应用程序。

CreateProcess 函数原型如下:

1
2
3
4
5
6
7
8
9
10
11
12
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);

有关此函数的相关信息,可以查询MSDN获取。

相关参数信息

我们主要用到的信息有:

1
2
3
LPCTSTR lpApplicationName,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation

LpApplicationName 用来指定应用程序的全路径。
LpStartupInfo 指STARTUPINFO结构体的指针,用来设置待启动的应用程序的信息。
lpProcessInformation 指向PROCESS_INFORMATION结构体的指针,用来返回新进程的信息。

参数简介

lpApplicationName

[in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer.

lpStartupInfo

[in] Pointer to a STARTUPINFO structure that specifies the window station, desktop, standard handles, and appearance of the main window for the new process.

lpProcessInformation

[out] Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.

STARTUPINFO结构体

STARTUPINFO结构体定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;

PROCESS_INFORMATION结构体

PROCESS_INFORMATION结构体定义如下:

1
2
3
4
5
6
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

由此我们可以看出,通过CreateProcess启动应用程序,我们可以获取应用程序的进程句柄,线程句柄,进程ID以及线程ID。

GetWindowThreadProcessId

那么我们如何才能进一步获取应用程序主窗体的句柄呢?

我们知道,如果知道了窗体的句柄(HWND),那么通过以下函数可以获取到dwProcessId,那么是否可以反过来通过线程ID来获取窗体的句柄呢?

1
2
3
4
DWORD GetWindowThreadProcessId(          
HWND hWnd,
LPDWORD lpdwProcessId
);

我们知道,一个窗体对应一个线程。所以可以通过GetWindowThreadProcessId来获取对应的线程ID。但是一个线程可能对应有0到多个窗体,所以没有办法直接获取窗体的句柄。

EnumWindows function

那么如果我们能获取所有的顶层窗体,然后通过比较进程ID,是不是就可以确定相应进程ID所对应的顶成窗体呢?幸运的是Windows提供了这样一种机制,让我们枚举所有的顶层窗体,那就是EnumWindows。

EnumWindows原型&参数

1
2
3
4
BOOL EnumWindows(
WNDENUMPROC lpEnumFunc,
LPARAM lParam
);
  • lpEnumFunc
    [in] Pointer to an application-defined callback function. For more information, see EnumWindowsProc.

  • lParam
    [in] Specifies an application-defined value to be passed to the callback function.

The EnumWindows function enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.

EnumWindows枚举屏幕上的顶层窗体,轮流将窗体的句柄传入回调函数中,直到最后一个窗体被枚举完成,或者回调函数返回FALSE。

EnumWindowsProc定义

EnumWindowsProc定义如下:

1
2
3
4
BOOL CALLBACK EnumWindowsProc(
HWND hwnd,
LPARAM lParam
);

整体思路&细节问题

整体思路

至此,我们的思路已然明晰,实现我们的目的需要如下步骤:

  • 通过CreateProcess启动应用程序,并记录返回的进程ID
  • 通过EnumWindows枚举屏幕的顶层窗体
  • 在枚举回调函数中,调用GetWindowThreadProcessId获取窗体对应的进程ID并与CreateProcess获取的进程ID比较,如相同,则记录窗体的句柄,并返回。

细节问题

在实际实现过程中,我们遇到了一些问题。

应用程序初始化问题

应用程序启动之后,需要进行一系列的初始化等操作,包括创建窗体等。如果我们启动应用程序后直接就通过EnumWindows枚举屏幕的顶层窗体,那么可能由于窗体还没有创建导致枚举失败。

通过调用WaitForInputIdle函数,可以等待窗体初始化完毕。

1
2
3
4
DWORD WaitForInputIdle(
HANDLE hProcess,
DWORD dwMilliseconds
);

The WaitForInputIdle function waits until the specified process is waiting for user input with no input pending, or until the time-out interval has elapsed.

Parameters
*hProcess
[in] Handle to the process. If this process is a console application or does not have a message queue, WaitForInputIdle returns immediately.

  • dwMilliseconds
    [in] Time-out interval, in milliseconds. If dwMilliseconds is INFINITE, the function does not return until the process is idle.
窗体标题

为了让我们的判断更加可靠,我们可以在枚举函数中使用GetWindowText判断一下窗体标题的长度是否为零。

总结

通过对MSDN中Platform SDK Window、Process等相关内容的学习和了解,并通过实际操作测试检验和总结,我们得到一种启动应用程序并获取应用程序主窗体句柄的使用并可靠的方法。对此此种方法进行简单的封装后,可以很方便的在我们的应用程序中使用,进而可以应用在控制其它应用程序等多种用途。


十多年前的我是多么努力啊
再看看十多年以后,哎。

你们猜到我要干什么了吗?不是干坏事,呵呵


This page is synchronized from the post: 发篇技术文档,大家猜猜我要干啥? / 启动应用程序并获得应用程序的主窗体句柄

写在Reputation 70之际(Reputation 70+, Followers 1000+, SP 10000+): 一: 玩steemit经历回顾

Capture.PNG

缘起,为何发帖

很久以前就看大家各种发帖庆祝Followers 突破几百大关,上千大关

然后我也想发帖庆祝一下啊,可惜当时声望分倒是够了,但是Followers 不足 1000,人气惨淡,总不能发帖庆祝类似Followers 突破955吧😀, 前两天Followers 终于突破 1000大关了,于是赶紧截屏记录下来,不去想这里多少机器人,终归算作里程碑事件吧。然后又苦苦期待Steem Power 突破10000大关,但是就是不突破,无奈之下,自己Power UP了一些SteemPower,总算凑够 1W了,这算不算作弊呢?😀

既然Reputation 70+, Followers 1000+, SP 10000+,当然要发帖回顾一下,发帖庆祝一下了。

玩Steemit经历回顾

这个帖子先不搞啥赠送烤箱的活动啦,先自己回顾一下玩steemit经历吧


其实也没啥值得大书特书的事情,来到STEEMIT也纯属偶然,当时看老聂、小辉他们在一个我们常去的论坛宣传STEEMIT,好奇之下,就翻墙注册了Facebook,然后注册了Steemit了。来了之后一头雾水,这是啥玩意啊,咋玩啊,研究半天发出第一个帖子。

刚刚翻看了一下,第一个帖子居然还被 @deanliu 老师点赞了呢,感动死了。


然后觉得这应该是个类似博客一样的东西,于是乎又写了一篇博文


第二个帖子就得到了神级人物的关照,一下子就赚了近37个SBD,那兴奋劲就甭提了。一下子就爱上了这个社区。


然后开始尝试创作各类帖子,收入有高有低。


写了一些技术贴,也曾一度幻想有没有机会超过dan


也曾晒过旅游贴,回顾一下居然才发现我也曾爆过照片


居然很久以前就提示过大家密码的重要性以及各类私钥等


给steemit 提的建议,现在这个功能终于有了


那是就经历过steem 暴跌,我在4SBD到1.5SBD期间曾一路买进


研究STEEMIT的新功能,以及把STEEM和IOT的一些设备结合起来


初次去了解机器人


热帖附点评的第一期,这个我坚持办了很久


第一次写机器人,机器人的第一票就被大西瓜钓去了,威武霸气


倡议大家珍惜羽毛,不要抄袭


CN区净化行动11个月以前我们就在做


点赞机器人每天可以给我赚一听可乐


年轻的时候也曾文艺过


香蕉派是我最喜欢的玩具


原创IOT相关的翻译


有了零星的比特币


文学创作不要停


这大概是最悲哀的一篇博文了


DIY小车的坑一直没有填


用爱迪生做的智能浇花系统的坑总算填上了


大家一起听课的日子


学习steemit 的签名


额,这里还有坑,其实工具我一直在用,咋发布出去没想好,有些纠结


Dan 退出steemit 团队,我用树莓派和Airplay功能将音箱改造成无线音箱


值得纪念的日子,老道茶馆第一天开张


菩萨保佑,点赞收益还够买可乐的


搞了个活动,人气火爆, 0.2SBD当时算巨款了吧


写了篇安全提示,被大神们关照


新人突然多了起来,写了一些教程贴


硬叉19到临前一个小时发布的帖子,也是我有史以来收入最高的帖子。


HF19之后的帖子,不用翻大家都能看到了,就不一一回顾了。

总结

今天在 @incrediblesnow 小兄弟的帖子里被称作元老之类。我给他回复让他编辑掉。

真的因为距离元老、鼻祖、龙头老大还差着几十亿光年的距离呢,或许在STEEMIT上或者STEEMIT中文区上,我永远也达不到这样的地位,所以很不喜欢这样的称谓。

说白了,我只是和大家一样混中文区而已,水平可能还不如大家,无非是混的时间长、运气不太坏,声望分过了70而已,你们混久了,可能比我还强。从我回顾我以往的帖子可以看出,我也一直在探索,无论是发帖形式、还是机器人、还是学习steem相关或者不想关的技术、或者是所谓的文学创作,我一直在尝试。

玩steemit一年多,最大的收获就是收获了很多朋友,希望大家能在STEEMIT上一起开开心心的玩下去。需要感谢的人也很多,就不一一点名了,挂在嘴上没啥实际意义,不是吗?😀


This page is synchronized from the post: 写在Reputation 70之际(Reputation 70+, Followers 1000+, SP 10000+): 一: 玩steemit经历回顾

继续聊当年我掌握的屠龙(西方恶龙)技: (二) IDS & XACS &iAMT

上文聊到了手机开发和手机系统开发

搞了两年手机开发,我就转行了,换到一个全新的领域,改做网络安全。
如果是在BREW和SMS领域还算得上半个权威的话,在网络安全领域完全是个小白。所以基本上是一边工作一边努力学习。

IDS

网络安全领域我参与的第一个项目是IDS,全称Intrusion Detection Systems,意即入侵检测系统。你可能知道防火墙但是未必听说过IDS和IPS, 防火墙主要是配置一些规则和策略,根据规则策略决定放行或者阻断IP或端口的访问,IPS和防火墙类似,但是先进那么一点点。而IDS的作用就如同它的名字,主要是检测。

我加入时,公司的IDS产品已经做得相当完善了,并且大卖特卖,用我们产品经理的话说,我们躺着啥也不用干,就靠卖COPY的收入就可以过得相当滋润了。但是啥也不干,好意思嘛。于是从原理到底层各种学习和研究。比如TCP/IP协议的各种封包机制,ARP、FTP、SMTP等各种协议分析,都学习的很透彻。

IDS的机制其实很简单,本质上就是监听。放在本机上,就是把网卡设置成混杂模式,如果是路由器则更简单,有监听口,这样所有局域网的数据包都可以收到了。然后根据监听到的数据匹配攻击规则,就可以判断出来是否有入侵发生了。说到监听,除了写程序,那时候用的最多的工具就是Sniffer和IRIS,我比较喜欢IRIS用来学习和分析各种协议的封包非常方便和直观。而规则库是基于snort的Rules, snort本身就是一款开源的IDS系统,详情可以参见: https://www.snort.org/

找了一下2005年Windows下设置Snort成功后在别人技术贴(CU)底下的合影

我们做的则是裁减slackware、进行协议分析、与snort规则比对、以及超级强大的Window 端管理。尤其是Delphi做的Windows管理端那是相当强大了。忘记说了,当时IDS组的负责人也在 steemit.com 上哦,Delphi超级高手,不过他很少发帖,我就不爆他ID了:)

当时为了熟悉一些常用的入侵手段,项目组成员的电脑成了大家彼此练手的对象,于是工作期间经常听到此起彼伏的骂声: “我靠,那个畜生又把我电脑干蓝屏了”。至于监视彼此的邮件内容、还有FTP都上传下载了啥好玩的东西,更是家常便饭。所以IDS项目组混过以后,我就练就了极强的安全意识,比如说邮件都用SSL连接(SSL链接: POP 995, SMTP 465), FTP则要么用SFTP,要么用FTPES(FTP over explicit TLS/SSL),否则被人监视的感觉真的很不爽。

说要被监视,不得不顺便提一下大墙,大墙和IDS基本类似哦,尤其是以前常用的RESET功能,更是我们IDS中切断链接的常用伎俩。

后来我们产品经理和部门经理闹别扭,拉着N多IDS成员集体辞职,但是最终只有组长和产品经理断然离去,毕竟和不明朗的未来比起来,还是赚死工资更稳妥一些。但是IDS项目也就因此停止继续投入研发资源了,反正产品已经很成熟了,卖COPY就是了。说到COPY,不得不提到一个节点的问题,所谓多少节点,就是一台IDS能同时监控多少其它主机,比如说支持10个节点的设备卖20W,支持100个节点的设备卖100W,有段时间专门负责处理多少个节点,大多数时候,就是源码里改个常量😀 如果那些花几百上千万买了支持N多节点设备的用户知道这件事,不知会作何感想。或者人家根本不在乎这些事,能花出去更多的钱,才是能耐,不是嘛。

XACS

IDS项目落幕以后,我又参与了一段时间Firewall研发,但是刚刚熟悉一点点就被抽调到一个很重要的项目中去,负责底层的开发。X是26个字母中的一个,我就不写出来,以免引起一些不必要的麻烦。

简单的说,这个就是个访问控制系统。

大家都去过医院,医院有一些管理系统比如HIS、PACS、LIS等等,简单点说就是存储用户数据、用户检查影像数据、用户病历数据等等,具体哪个是哪个,我时至今日也对应不上,不过不影响我们继续讲故事啦。这些系统有个很重要的问题,就是用户不分级、医生不分级。

举例说,某个重要的人物(政要等),去医院看病,是不是也要建立用户档案、也要存影像检查数据、也要保存病历数据?但是问题来了,一个小医生也可以登陆这些系统,也可以看到这些资料,如果把这些资料泄露出去,就可以造成一个不必要的麻烦或者恶劣的影响。而我们的XACS就这在这些系统上插入一个访问控制层,将用户数据分级,将医生权限分级,这样权限低的医生就无法看到权限高的用户的数据了。

这些系统最大的难点就在于要很很多系统打交道,而这些系统都有各自不同的机制用到不同的数据库,比如说Oracle、SQL Server 、MySQL、ACCESS等等,于是我就努力学习在c程序中如何和这些数据库打交道才能完成和不同系统的交互。

神马UnixODBC、FreeTDS、OCI(Oracle C Interface)一顿学习,尤其是OCI,印象中应该上千页的文档,为了实现某个功能我累的头晕眼花。


上边照片不是我工作单位哦,是去他们那测试和实施我们的系统,涉密单位,所以把名头抹掉了。感慨一下,那时候的头发好浓密啊(头发都去哪里了呢?)。头昏眼花加班加点干了好几天,克服了无数之前没有想到的障碍,终于把测试系统成功部署。值得一说的是,因为我想在宾馆上网,但是宾馆有网口没网线,我一小弟居然从涉密单位中给我顺出来一条网线,真是胆大之极啊😀

后来就把系统移交给他们了,也不知道现在各大医院运行的系统里是否有我写的代码?

IAMT

继 IDS & XACS以及其它一些乱七八糟的项目之后,我又带领团队参与了和Intel 合作的iAMT项目,百度上相关的词条就是我在06年创建的哦。当时Intel的工程师对我这边抱有极大的期许,可是我对部门领导的一些做法颇不认同,最后这个项目草草了事后我去了集团其它子公司。据说,仅仅是据说,Intel的人把我们这边的领导骂了个狗血淋头,然后原部门每逢例会,第一件事必然是对我进行批判。当然了,我是缺席这种批判会的,然而我的N多小弟不断传达最新消息给我。

结论

无论是IDS中学习的TCP/IP协议封包以及其它各种技术,还是XACS中的OCI等技术,现在应该都没有没落,然而十几年过去了,我早已忘得一干二净了,除了拿来回忆一下,估计再也写不出当年的代码了。有些技术技能,就像当年的头发一样,一去不返了,呜呼哀哉!


This page is synchronized from the post: 继续聊当年我掌握的屠龙(西方恶龙)技: (二) IDS & XACS &iAMT

聊聊当年我掌握的屠龙(西方恶龙)技: (一) Brew & SMS

今天偶然发现自己以前写的一篇文档,是有关Windows编程的,突然颇有感慨。
发现这些年从事过不少乱七八糟的工作

  • 单片机系统开发
  • 手机软件、手机系统开发
  • 网络安全系统开发
  • 医疗器械相关软件开发
  • 服务器管理、服务器端软件开发
  • 科学计算程序开发和维护
  • IOT相关的开发

基本上就是不停的学、不停的忘。不由想起之前自己掌握的一些(当时)很强大的技能。

Brew

说到手机软件开发,大家难免想到IOS和安卓系统,很可惜,我搞手机软件开发的时候这些系统还没出来。

我在公司做手机软件的时候,主要是协助索尼爱立信把Qualcomm 的BREW平台移植到他们新的手机型号上去,那时候我国内还很少有搞BREW的,我算是最早的一批,当时还有个网站叫移动未来,域名叫MOVE2008,没错,参与到这个网站的时候是2003年,那时候2008年就是我们所期盼的未来。我是网站管理员之一,然后我们一起讨论BREW,又要联系出版社出书等等。BREW,全称是Binary Runtime Environment for Wireless,翻译成中文叫无线二进制运行环境,当时联通要靠这个技术以及CDMA技术与移动打个翻身仗。那时候联通对BREW的宣传和期望有甚于现在的IOS吧。然而支持BREW的设备迟迟没有推向市场,那时候又是SYMBIAN占据了所谓“智能手机”的大部分市场,BREW最终铩羽而归。后来IOS、安卓等系统的出现,它彻底成为了历史。

而我傲视群雄的BREW技能,就再也没有什么机会发挥了,彻彻底底的成了屠龙(西方恶龙)技。


既然提到Symbian,就顺便说两句,那时候Symbian手机真的是神迹一般啊。比如这款9210,合上之后就是一个手机,翻盖之后就变成了一部小电脑,真正的全键盘哦,当时上边能处理word、图表、PPT,就是说可以跑个精简版的Office,还能跑媒体播放器啥的,能听歌,能看视频,给人的感觉就是一机在手,夫复何求!记得有一天晚上在公交上玩这个手机,旁边一个漂亮妹妹上来搭讪说,你这个就是高科技吧?可惜当时不懂得装X配合妹妹,我和谦虚的说,就是一个手机。然后继续低头玩!手机害死人啊。😡

对了,记不清赵薇还是Maggie Q主演的一部什么电影,里边一个场景就是两个人拿着高科技设备互相通讯,道具就是Nokia 9210哦。当时我对这个设备情有独钟,所以电影上看到倍感亲切。

9210在我眼里一切都是那么完美,直到后来出现了N86和N95.


N86 吸引我的就是能上WIFI,听歌功能强了一大块。我长草了好久,知道N95出来,为啥N95出来就不鸟N86了,无它,N95号称机皇啊。不要说我喜新厌旧,当年的9210C在回头看,无论从配置还是功能,都简直弱爆了。

我没关注过Symbian什么时候死的,后来后知后觉发现Symbian已死,觉得颇为感慨。如果说BREW的消亡不出所料,但SYMBIAN我一直以为它会成为世界第一呢。

GSM、SMS

上边说的是手机软件开发,虽然BREW移植算和系统有一点点关联,但其实手机系统的东西我们知晓的并不多,无非是知道索尼爱立信的一些输入法(t9)、计算器之类的东西。

而真正接触手机系统是参与后来与EPSON合作的一个项目中。没错,大家都知道EPSON做打印机啥的,可能不知道EPSON还一度企图做手机呢。大致就是一个裁剪的Linux系统,用MicroWindows做窗体。然后我主要负责其中短信以及电话相关部分。主要涉及的技术都是欧洲电信标准协会的一些文档


这些是我当年熟读的一部分文档。

手机开发很好玩,学习完这些技术后,我经常利用自己掌握的技术发一些奇怪的短信给朋友。比如说Flash SMS,就是短信到达后不进入收件箱,直接显示在屏幕上,你读完了,短信就没有了。有些类似后来啥软件开发的阅后即焚的功能吧。

因为短信功能涉及到编码尤其是中文编码需要按照很复杂的规则编解码(PDU),在当时我们裁剪的系统还不支持UNICODE(或者说我当时没意识到😭),总之中文短信涉及到UNICODE编码,我们采取的方式是做了个很大的编码表然后查表,刚开始测试的时候,我忘记我范的是什么错误,但是我记得我一条短信发出去N久,目标机还没有收到,后来到了午饭时间,大家说不等短信了,吃饭去吧,然后吃饭回来,发现短信到达了😀 当然了,当时移动网络也经常有延迟。

后来不知道 什么原因(肯定不是我短信慢的缘故),这个项目也破产了。然后我熟读ETSI文档,精通各种类型短信编解码以及发送收取的技术,又成了屠龙技。

后来我把Linux上开发的短信功能,深度优化并移植到Windows系统上来,做了个短信息收发工具,并且加入数据库管理短信息以及联系人等等,功能非常完备,运行也很稳定。我准备用这个软件赚一笔,过年回家也带着笔记本继续开发,颇为努力。然后大年初二喝了很多酒之后,我觉得笔记本(ThinkPad T42)特慢,就启用了一键恢复功能,然后把笔记本恢复至出厂设置,忘记了我的程序啥的都保存在C盘文档目录下。于是心灰意冷,再也不想搞短消息了。

直到前些年玩IOT,接触了SIM900A模块,才勾起一点以前的兴趣,捡回来一点点。
详情可见: 介绍一下SIM900A 和以前做的一个小例子

当时其实还想过做短信群发器,不过当时移动和联通都对外卖端口,量大的话每条只有五六分钱,而用手机卡加群发器则要1-2毛钱每条,遂放弃。那些卖短信的网站也玩过,我记得我有一个网站的用户名密码,那时候还不流行RESTful啥的,不对外提供接口,只能网页登陆,然后在文本框中导入名单和信息并发送。为了方便我写了个小程序,自动登陆网站,这样就可以用程序直接发短信了。玩了一段时间后,没啥意思,也就作罢了。后来这个企业逐步降级名头越来越小,最后被一个大企业把企业资质买走,短信业务也就不了了之。

结论


(这个配图是不是很尴尬)

Brew 和 SMS 是十几年前我熟练掌握的屠龙技,然而BREW已经彻底沉沦,SMS现在也早已沦落到很尴尬的地步,早些年逢年过节大家流行短信拜年,现在短信拜年会不会显得很古董?手机里的短信都是一些流量报告以及催费之类的,很少看了。

为了这两大屠龙(西方恶龙)技,我耗费无数心血啊。然而世间已经无龙(西方恶龙)可屠,呜呼哀哉!


This page is synchronized from the post: 聊聊当年我掌握的屠龙(西方恶龙)技: (一) Brew & SMS

STEEM/STEEMIT 玩法&创意征集

一般操作

大家玩STEEMIT都很久了,但是对于我们来讲,大部分时间我们都在做着这些操作:

  • 发表文章
  • 参与回复
  • 点赞

其它玩法

那么除此之外还有什么玩法呢?

  • 见证人: 需要技术实力,并且需要拉到足够的票
  • 机器人: 各种机器人程序,详情可见: 聊聊机器人🤖 / Robots on STEEMIT
  • 开发者: 技术实力足够的话,可以考虑帮steemit进行开发,有收益哦
  • 第三方网站/应用: 类似busy.org、ChainBB、ESteem等
  • 外网网站/应用: 类似steemwhales、SteemData等等,获得广告收益或者人气等
  • randowhale、minnowbooster等: 我觉得可以划归投资理财类,哈哈
  • 各种挑战赛
  • 其它等等

中文区相关的几个玩法

中文区据我所知现在除了发帖有以下几个略有不同的内容

  • @laodr 老道茶馆, 每期抛出一个话题(茶馆营业),大家进来参与讨论,小二给大家点赞(敬茶)
  • @ace108 发起的美丽星期天
  • @kenchung 发起的数学 x 程式编写比赛

玩法&创意征集

除了上边说到的
你还知道STEEM/STEEMIT有什么新奇好玩的玩法吗?
或者说你有什么新奇好玩的想法或者创意想和大家分享的?

独乐乐不如众乐乐。
在回复中介绍你所知道的好玩的玩法,或者你的创意,大家一起玩吧。

优秀回复将会获得点赞奖励哦


This page is synchronized from the post: STEEM/STEEMIT 玩法&创意征集

Arduino 开发不传之秘: 读取MCU Device ID(设备ID)以及Signature(标识)

在实际应用中,我们可能需要唯一的设备ID用于标识设备或者进行功能加密等操作。
Arduino中并未直接提供此类接口,那么是否可以实现此类功能呢?答案是肯定的。

在AVR的LIBC库中提供了以下定义(boot.h):

Read the Signature Row byte at address. For some MCU types, this function can
also retrieve the factory-stored oscillator calibration bytes.
Parameter address can be 0-0x1f as documented by the datasheet.
Note The values are MCU type dependent.

Datasheet中关于如何在软件中读取Signature的说明:

不同型号MCU的Device ID信息:

根据如上信息,写了个测试程序:
读取手头Arduino板的信息:

  • Arduino UNO R3 (1)

  • Arduino UNO R3 (2)

  • Arduino NANO

对于我们获取的Device ID以及文档中的说明,可知手头的两片Arduino UNO R3以及Arduino NANO 均采用ATMEGA328P.
那个RC Oscillator Calibration Byte没搞明白,先不理会啦。

可以明显看到这些数据分成几组,但是除了(Device ID)以及(Calibration Byte)没有从datasheet中找到其它部分对应的描述。
网上一些帖子说从第十四个字节(从0开始),后连续10个字节亦即MCU的唯一编码。

对程序稍作修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "avr/boot.h"

void setup() {
Serial.begin(9600);
Serial.println("Arduino MCU Signature Reader");
Serial.println("By JoyTag, support@joytag.com\n");
}

void loop() {

// 28.3 Signature Bytes
Serial.print("Device ID:\t");
Serial.print(boot_signature_byte_get(0), HEX);
Serial.print("\t");
Serial.print(boot_signature_byte_get(2), HEX);
Serial.print("\t");
Serial.print(boot_signature_byte_get(4), HEX);

// 28.4 Calibration Byte
Serial.print("\nCalibration Byte:\t");
Serial.println(boot_signature_byte_get(1), HEX);

//23.12.2.14 #define boot_signature_byte_get( addr )
Serial.println("\nRow Bytes:");
for (int i = 0; i <= 0x1F; i++)
{
Serial.print(boot_signature_byte_get(i), HEX);
Serial.print(", ");
}
Serial.println("");


Serial.println("\nUID Bytes:");
for (int i = 14; i < 14 + 10; i++)
{
Serial.print(boot_signature_byte_get(i), HEX);
Serial.print(", ");
}
Serial.println("");

while (1);
}

看来,利用这个方法读取唯一标识还是可行的。

参考资料

补充:
带水印的截图都是本人以前亲自做的,懒得把多个设备拿出来重新跑,直接用老图啦。
文章所述功能属于隐藏技能哦,我周围很多做产品的都不知道这个事那,免费大放送啦。


This page is synchronized from the post: Arduino 开发不传之秘: 读取MCU Device ID(设备ID)以及Signature(标识)

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×