2009年6月16日 星期二

Python 與 Windows ShortCut

在Windows下,有機會要處理ShortCut,也就是捷徑。
試了幾天,有幾種做法:

(1)利用windows 內建 vb script 執行引擎。先建立一個 .vbs 檔
Set WSHShell = WScript.CreateObject("WScript.Shell")
Set Shortcut1 = WSHShell.CreateShortcut(shortcut_name & ".lnk")
Shortcut1.TargetPath = WScript.Arguments.Item(0)
Shortcut1.WorkingDirectory = WScript.Arguments.Item(1)
Shortcut1.Arguments = WScript.Arguments.Item(2)
Shortcut1.Save
再利用 python 的 os.system 來執行這個 vbs。
執行的時候可以帶參數,例:
os.system('createShortCut.vbs 1 2 3')
在 vbs 裡取得參數的方法為 WScript.Arguments.Item(0)

(2)安裝 win32com,按照文件 win32com.shell and Windows Shell Links 來做。
from win32com.shell import shell
import pythoncom
shortcut = pythoncom.CoCreateInstance( shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink )
# load short cut
shortcut.QueryInterface( pythoncom.IID_IPersistFile ).Load( filename )
# save short cut
shortcut.QueryInterface( pythoncom.IID_IPersistFile ).Save( filename, 0 )
但是,要怎麼去改捷徑內容呢?我沒研究出來。據說可以去研究http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/sdkdoc/shellcc/shell/ifaces/ishelllink/ishelllink.htm

(3)利用 win32com 取得 WScript.Shell 的 python 物件。這很酷喔,只要兩行
import win32com.client
shell = win32com.client.Dispatch('WScript.Shell')
好了,接下來,shell 要怎麼用,去看 windows 的 vb script 怎麼用就行了,文件非常好查,也就是說,照第(1)個方法去寫就行了。
shortcut = shell.CreateShortCut('test.lnk') 
shortcut.Targetpath = 'C:\\test.exe'
shortcut.WorkingDirectory = 'C:\\'
shortcut.Arguments = '1'
shortcut.save()

(4)使用 winshell 來處理,前人將 shell 包好成一個物件來使用
http://timgolden.me.uk/python/winshell.html
import os, sys
import winshell

winshell.CreateShortcut (
Path=os.path.join (winshell.desktop (), "shortcut.lnk"),
Target=r"c:\Program Files\Mozilla Firefox\firefox.exe",
Arguments="http://localhost",
Description="Open http://localhost with Firefox"
)

由這個例子,體會一下,python 當膠水的能力。
把別的語言的工具,拿來自己用的能力。我最佩服第(3)種寫法。
感謝前人很辛苦的寫了 win32com ,否則才沒這麼簡單哩。

2009年6月5日 星期五

被 C# 搞死了 編譯器錯誤 CS0165

http://msdn.microsoft.com/zh-tw/library/4y7h161d.aspx
C# 編譯器不允許使用未初始化的變數。

我猜想這個是為了讓寫程式的人永遠記得,變數一定要初始化。
這原意很好。
但是有時候,會依據條件,使用不同的 constructor。以下的寫法就會出問題。
=============
TcpClient tcp;
if (ip ==""){
  tcp = new TcpClient();
}
else{
  tcp = new TcpClient(ip, port);
}
Console.WriteLine(tcp.connected);
=============
因為放進條件式,編譯器就以為沒有初始化了,於是就發生這樣子的問題。這樣真的太小氣了。我真的不能這樣寫嗎?
我也不曉得該怎麼辦,只好用個最笨的方法,一開始設成 null,讓編譯器不出問題。
TcpClient tcp = null;
既然如此,何不一開始,編譯器永遠都是開頭設成 null 就好了?
為什麼不的原因我實在想不出來。