終於用VC/MFC做了一個真正的程序

        花了兩天多的時間做了一個“信使服務”程序,呵呵,以前在網上見到過,居然要花錢註冊的。其實就是用了那個NetMessageBufferSend函數,再用一個NetMessageNameAdd函數把隨便一個名字加進去,就可以把自己的身份隱藏了。以前在學校的時候由於用的是固定IP,經常收到的很多廣告就是用這種方式發送的。有時候在課堂上老師正在講課,突然就冒出這麼一個窗口來,十分氣人,所以我們一般都把Messenger服務給屏蔽掉,嘿嘿,現在我居然做起這個東西來。

  通過命令行方式用net send命令就可以發這種消息,不過會暴露你的計算機名,因爲它沒有選擇名字的參數,而使用NetMessageBufferSend則可以使用你計算機上的任意一個“名字”,那個名字又叫“消息別名”,似乎跟計算機名不一樣,但是默認的“消息別名”就是計算機名。開始的時候以爲可以隨便給NetMessageBufferSend的from參數賦值,網上很多人也這樣說,但我試了總是出錯。後來才發現那個名字必須是計算機上已經有的“消息別名”之一。那我怎麼才能隨便用一個名字呢?於是就必須用到NetMessageNameAdd函數,這個函數可以增加一個隨便起的消息別名,接着就可以把這個名字傳給NetMessageBufferSend來發送了。

  NetMessageBufferSend的原型是:

NET_API_STATUS NetMessageBufferSend(
  LPCWSTR servername,
  LPCWSTR msgname,
  LPCWSTR fromname,
  LPBYTE buf,
  DWORD buflen
);

  開始的時候以爲第一個參數servername就是目標的名字,後來才知道原來是要運行這個函數的服務器的名字,因爲這個函數一般用於局域網管理,有時候需要控制某臺服務器來運行程序。如果在本機上運行,把這個參數設成NULL就可以了。以Net開頭的很多函數都有這個參數。

  第二個參數msgname,在網上看到很多人說這個就是指向要發的消息字符串的指針,跟第4個參數buf是一樣的。我試了很錯次都是失敗的。後來在某個地方看到一個牛人的解釋才知道這個msgname的意思根本就不是“消息字符串的名字”,而是目標機器的“消息別名”!一般就是目標的計算機名了,如果那臺計算機還有其他消息別名的話,這個也可以是其中一個,不過發消息的那臺機器也要知道該別名指的是那臺計算機才行。

  第三個參數最折騰人了,總以爲隨便起一個名字就可以了,後來跟蹤了錯誤信息,說沒有找到這個名字,想起以前用net send玩的時候還用過一個net name,通過net name xxx /add就可以增加一個名字xxx,然後用net send 就可以給xxx發消息了。既然說沒找到這個名字,是不是那個名字還沒通過net name來加進去呢?於是我就用了最古老的一種方法,通過system()函數執行net name命令,把隨意輸入的名字加進去,再用那個名字發消息,哈哈,成功了。不過要彈出那個黑黑的cmd 窗口比較難看。再到MSDN看看,有個NetNameAdd函數,正好可以幹這種事情,呵呵,搞定。

  LPCWSTR與LPBYTE也比較難受。LPCWSTR的意思是“常量寬字符串”,因爲Net系列函數使用的都是UNICODE。那怎麼把CString轉換成這個東西呢?CString本身可以被看作LPCTSTR,即“常量T字符串”,呵呵,T字符就是那種“騎牆”字符,你定義了_UNICODE,它就表示W,寬字符,沒有定義_UNICODE,它就表示一般的8比特字符,爲了同時兼容ASCII版本和UNICODE版本,定義字符串的時候最好都用T字符。那怎麼把CString轉換成寬字符串呢?在網上看到有人說用一些宏就可以了。那些宏是在atlconv.h裏面定義的,包括:

ATL String Conversion Macros

A2BSTROLE2AT2AW2A
A2COLEOLE2BSTRT2BSTRW2BSTR
A2CTOLE2CAT2CAW2CA
A2CWOLE2CTT2COLEW2COLE
A2OLEOLE2CWT2CWW2CT
A2TOLE2TT2OLEW2OLE
A2WOLE2WT2WW2T

  每次使用前,都要在前面加上一句:

USES_CONVERSION;

然後就可以很方便地在這些類型之間轉換了。例如要把CString str轉換成LPCWSTR lpw,只要:

#include <atlconv.h>

...

USES_CONVERSION;

LPCWSTR lpw=T2W(str);

這樣,前三個參數就可以搞定了。

  第四個參數是LPBYTE,這又是一種奇怪的類型,從字面上看是指向BYTE類型的指針。在C裏面是沒有BYTE類型的,跟它最象的就是unsigned char類型了,實際上就是它。那怎麼把CString轉換成這個呢?首先,要把CString轉換成LPCWSTR,因爲Net用的都是UNICODE,裏面的字符串編碼必須是UNICODE;接着,由於LPCWSTR的每個字符是16bit,不符合LPBYTE的要求,所以還必須強制轉換成LPBYTE。這樣,可以寫成:

LPBYTE=(LPBYTE)T2W(CString);

不過還是分步轉換好一點:

LPCWSTR=T2W(CString);

LPBYTE=(LPBYTE)LPCWSTR;

  因爲後面一個參數buflen要用到LPCWSTR的長度。buflen是以字節來計算的buf的長度,通過wcslen(LPCWSTR)可以得到LPCWSTR的字符個數,然後每個字符的長度是sizeof(wchar_t)字節,那麼LPCWSTR的長度就是wcslen(LPCWSTR)*sizeof(wchar_t)字節。

  我想用CString的GetLength()函數來做,但是總是失敗,不知道爲什麼。CString.GetLength()*sizeof(TCHAR)總是長度不夠,後面有一個或幾個字符截斷了。

  到這裏,輸入的東西就搞定了,搞定了這個,後面的羣發、局域網計算機列表就問題不大了。下次再把心得寫出來

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章