2012年9月25日 星期二

移除目錄(包含目錄下所有檔案和資料夾)

各家程式語言都有自己的function可以移除目錄或檔案,像boost C++有remove()和remove_all()可以使用。雖然呼叫function很方便,但若遇到要移除的目錄結構非常龐大時,很有可能會把heap塞爆。在這邊提供一個不一樣的解決方法:「呼叫系統指令 。 」

Windows系統有個指令叫做rmdir,Linux系統則是rm,這兩個指令加上參數就可以做到移除目錄以及目錄下所有檔案和資料夾的功能。

呼叫系統指令的好處是可以忽略例外發生,也不會佔用到程式的heap,簡單的說就是避免程式當掉。不要認為用系統指令的程式水準低,「能簡單解決問題的方法就是好方法!」

C++ - 字串大小寫轉換

字串大小寫轉換是在讀取檔案或使用者輸入文字時,常需要做的處理,沒想到我竟然會在別人的程式碼裡看到一種無言的寫法:
if ( !strcmp(p, ".pdf") || !strcmp(p, ".PDF") )
{
        ...
}
這段程式碼是判斷檔案是否為PDF,p是存放檔案名稱的字元陣列。這種判斷方法是一種很笨的寫法。

C++有strlwr(char * _str)函式可將字元陣列中的英文字母轉成小寫,而strupr(char * _str)函式則是轉成大寫,函式庫是string.h。C語言也有tolower(int c)和toupper(int c)可以使用,不過一次只能轉一個字元,要配合迴圈才能轉換字元陣列。

字串比對時,如果要忽略大小寫,C++有strcmpi(const char * _str1, const char * _str2)函式可以用。

2012年9月10日 星期一

C++ - 存取Windows機碼

作業系統:Windows 7
開發工具:Visual Studio 2010
程式語言:C/C++
程式功能:讀取與修改Windows機碼,範例是關閉Windows 7錯誤回報的顯示。
//HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting
//"DontShowUI"=dword:00000001

#include <stdlib.h>
#include <Windows.h>
#include <atlconv.h>

long reg()
{
    HKEY hKey;
    long errorlevel = 0L;
    char* reg_video_path = "Software\\Microsoft\\Windows\\Windows Error Reporting"; // Registry path
    char* value_name = "DontShowUI"; // The key
    DWORD dwType = 0x00000000, dwSize = 0x00000000;
    DWORD data = 0x00000000;

    USES_CONVERSION;

    // Step 1: open key.
    errorlevel = RegOpenKeyExW(HKEY_CURRENT_USER, A2W(reg_video_path), 0, KEY_ALL_ACCESS, &hKey);
    if(errorlevel != ERROR_SUCCESS) return errorlevel;

    // Step 2: read size. (necessary)
    errorlevel = RegQueryValueEx(hKey, A2W(value_name), NULL, &dwType, NULL, &dwSize);
    if(errorlevel != ERROR_SUCCESS) return errorlevel;

    // Step 3: read value.
    errorlevel = RegQueryValueExW(hKey, A2W(value_name), NULL, &dwType, (LPBYTE)&data, &dwSize);
    if(errorlevel != ERROR_SUCCESS) return errorlevel;

    // TODO: set new data.

    // Step 4: set value.
    errorlevel = RegSetValueExW(hKey, A2W(value_name), 0, REG_DWORD, (const BYTE*)&data, sizeof(DWORD));
    if(errorlevel != ERROR_SUCCESS) return errorlevel;

    // step 5: close key.
    errorlevel = RegCloseKey(hKey);
    if(errorlevel != ERROR_SUCCESS) return errorlevel;

    return 0L;
}

Windows的版本不同,機碼名稱和值也可能不同,所以要針對作業系統的版本去寫。

2012年9月5日 星期三

Python - XML-RPC簡易實作

Python版本:3.2

最近在用XML-RPC實現server與client之間的互動,底下是簡單的訊息互傳範例:

Server端

#Python 2
#import SimpleXMLRPCServer
#Python 3
import xmlrpc.server

host = "127.0.0.1"
port = 1234

def handle(msg):
    #Python 2
    #print "Handle message: " + msg
    #Python 3
    print("Handle message: " + msg)

    ret = "Hello! I have received your message."
    return ret

def main():
    #Python 2
    #server = SimpleXMLRPCServer.SimpleXMLRPCServer((host, port))
    #Python 3
    server = xmlrpc.server.SimpleXMLRPCServer((host, port))

    server.register_function(handle)
    server.serve_forever()

if __name__ == "__main__":
    main()

Client端

#Python 2
#import xmlrpclib
#Python 3
import xmlrpc.client

host = "http://127.0.0.1:1234"

def main():
    #Python 2
    #server = xmlrpclib.ServerProxy(hots)
    #Python 3
    server = xmlrpc.client.ServerProxy(host)

    result = server.handle("Welcome.")

    #Python 2
    #print result
    #Python 3
    print(result)

if __name__ == "__main__":
    main()

有一些地方要注意:
  1. Python 2和Python 3的xmlrpc library不同,範例裡有用註解表示Python 2的寫法。
  2. Python 2和Python 3的print也不同。
  3. SimpleXMLRPCServer()的參數是tuple型態,host要給字串,port要給整數。
  4. server的host設定為127.0.0.1,client就只能連線到127.0.0.1;換句話說,server的host若設定成192.168.1.1,client即使在本機,也不能透過127.0.0.1連線,只能連線到192.168.1.1。
  5. client端呼叫一次server端的handle(),socket連線即結束;要再次呼叫的話,要再執行一次ServerProxy()。
  6. server端可以一次註冊多個function。
  7. serve_forever()要放在最後面呼叫,因為呼叫完即進入server的main routine。

Windows - 工作排程

作業系統:Windows 7

桌面環境下,要設定工作排程可以從「開始」→「附屬應用程式」→「系統工具」→「工作排程器」,也可以從「控制台」→「系統管理工具」→「工作排程器」。

如果想從命令提示字元視窗設定工作排程,命令格式為:
增加:SCHTASKS /Create [參數]
刪除:SCHTASKS /Delete [參數]
 舉例來說,設定每天中午12點自動執行記事本:
SCHTASKS /Create /SC DAILY /TN NewTaskName /TR "%windir%\system32\notepad.exe" /ST 12:00
 刪除工作則是:
SCHTASKS /Delete /TN NewTaskName /F
 要查詢其他參數設定請參考:Windows - Schtasks.exe