因為有了Mono讓原本習慣開發Windows程式的人也可以輕鬆的寫出跨平台的程式,轉移的痛苦度也降低了很多,在此分享幾個.Net Framework透過Mono跨平台的技巧。
讓SharpDevelop支援Mono
要開發跨平台的程式,當然要讓開發工具支援跨平台的功臣Mono啦。
1. 在 Project >> Project Options 中選擇「Debug」頁籤。
2. 設定Start Action,設定編譯後的執行模式,預設為Start project,亦即使用預設的Debug環境執行,若要以Mono執行,則必須更改為「Start external program」,並指定Mono for Windows的Console執行檔路徑。
3. 設定啟動參數為「"${TargetPath}"」,此代表編譯好的.Net程式執行檔路徑
4. 設定工作目錄為「"${TargetDir}"」,此代表編譯好的.Net程式執行檔所在目錄。
設定好之後按下F5編譯並執行,即會以Mono執行程式了,設定如下圖:
判斷目前正執行的平台
雖然跨平台程式應該與平台無關,但如果在程式中針對平台特性加以優化將會使軟體的功能更加貼近各種平台。
判斷跨平台的程式碼如下:
string SysString = Environment.OSVersion.Platform.ToString();
string SysId = ((int)Environment.OSVersion.Platform).ToString();
switch(Environment.OSVersion.Platform)
{
case PlatformID.Unix:
MessageBox.Show("目前執行在 Unix-Like平台");
break;
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
MessageBox.Show("目前執行在 Windows 平台");
break;
}
MessageBox.Show("目前的平台是:" + SysString + " , 平台ID:" + SysId);
針對目前執行系統取得文字檔的換行字元
由於Unix-Like的作業系統文字檔的換行是\n,而Windows則是\r\n,因此可以透過
System.Environment.NewLine 來取得目前系統的換行字元
如果非要呼叫系統API
有些時候,如果非得使用Windows API來達成在Windows下的某些特殊功能,如果使用內嵌的方式呼叫Windows API,在Linux底下根本無法透過mono執行,因為內嵌式的呼叫在程式載入時就會一併載入所需的.dll,此時可以將這些功能寫成一個DLL,再利用前面所提到的方法判斷目前作業系統,如果是在Windows底下,就利用動態調用DLL的方式來呼叫這些API,反之如果不是在Window底下,則進行另外的處理。
以下示範將Window API包裝在DLL裡面,並依據目前執行的作業系統決定是否載入外部DLL並利用其提供的方法,呼叫Windows API來達成所需的功能。
將以下編譯成.dll檔
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ClassLibrary
{
public class MyClass
{
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern int ShellExecute( IntPtr hwnd, String lpOperation, String lpFile, String lpParameters, String lpDirectory, int nShowCmd);
public MyClass()
{
//其他處理
}
//用一個方法成員包裝某個Windows API
public void WinApiShellExecute(Form caller,string filePath)
{
ShellExecute(caller.Handle,"open",filePath,null,null,5);
}
}
}
呼叫時,使用以下方式:
using System.Reflection;
if(Environment.OSVersion.Platform != PlatformID.Unix)
{ // Windows系統,載入DLL,並藉由DLL裡面的方法呼叫Windows API
string dllPath = "ClassLibrary.dll";//DLL路徑
Assembly assLib = Assembly.LoadFrom(dllPath);//動態載入DLL
//取得Namespace為ClassLibrary的MyClass Type
Type clsType = assLib.GetType("ClassLibrary.MyClass");
Object MyClass = Activator.CreateInstance(clsType,new object[]{});//建立Class實體
MethodInfo mApiInfo=type.GetMethod("WinApiShellExecute");//取得Method成員
mApiInfo.Invoke(MyClass,new object[]{this,"notepad.exe"});//呼叫包裝API的方法成員
}
else
{ //Unix系統
//進行其他處理....
}
PS. 這只是範例,如果只是要呼叫外部程式,.Net Framework有更好的作法,不需呼叫Windows API。





