星期三, 1月 21, 2009

ClickOnce 必要條件 - 從相同位置下載必要條件

搞死人了
怎麼樣都無法設定好
在老板的淫威逼迫下 總算把這搞定了

狀況
為了讓使用者不必透過網路下載「必要條件」
所以在ClickOnce「必要條件」設定「從應用程式的相同位置下載必要條件」
但都會發生類似以下令人抓狂的錯誤:
1.錯誤 無法發行,因為無法建置專案錯誤。
2.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\instmsia.exe'。如需詳細資訊,請參閱 [說明]。
3. 錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\WindowsInstaller-KB893803-v2-x86.exe'。如需詳細資訊,請參閱 [說明]。
4.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\dotnetfx.exe'。如需詳細資訊,請參閱 [說明]。
5.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\langpack.exe'。如需詳細資訊,請參閱 [說明]。


問題點:需下載相關的檔案,並放到對的位置,問題就在這位置不知要放哪,且依SDK不同放的位置也不同,而且3.5還需設定xml檔


針對不同版本的Framework會有不同的解決方法
A.必要條件.Net Framework 2.0版
Step1 環境確認
IDE:C# 2008 Express

Step2 下載必要檔案
需要4個檔案,click鏈結可以直接下載檔案,如果鍵結斷了,可以直接search關鍵字
1.instmsia.exe
2.WindowsInstaller-KB893803-v2-x86.exe
3.dotnetfx.exe
4.langpack.exe

Step 3 放至指定資料夾
將全部的檔案丟到
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\DotNetFX
在錯誤訊息中指出,這個資料夾缺了這四個,但即使將這四個檔放進這資料夾,還是會出現潮少langpack.exe,也就是說錯誤訊息剩下2個
1.錯誤 無法發行,因為無法建置專案錯誤。
2.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\langpack.exe'。如需詳細資訊,請參閱 [說明]。

明明都寫這位置了,卻還是不行,看了一下該資料夾下還有個「zh-CHT」
就順手把 langpack.exe 丟進去,結果就成功了
大家試試吧

References:
VB2005 Express 部署問題
VS bootstrapper packages for .NET Framework 2.0 SP2 and 3.0 SP2 available for download

B.必要條件.Net Framework 3.5 SP2
照著網誌的做法就可以成功了
ClickOnce 發佈時,一起發佈 Framework 套件
ClickOnce 暨 Framework 3.5 發佈失敗的問題

星期日, 1月 18, 2009

如何維持.net程式單一執行個體應用程式

VB專案可以很開心的依以下路徑設定 就完成這限制
「專案=>屬性=>應用程式=>建立單一執行個體應用程式 」

不過其他的如C#等語言 就得自己寫程式
C#裡
/*
Code Snippet
Just add that piece of code (here in C#) in your main method (you need to
include the System.Diagnostic namespace) :
*/
Process currentProcess = Process.GetCurrentProcess();

Process [] allProcesses =
Process.GetProcessesByName(currentProcess.ProcessN ame);

if (allProcesses.Length > 1)
{
MessageBox.Show(currentProcess.ProcessName + " is already running !",
currentProcess.ProcessName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
//do your stuff here
}

VB
/*
Code Snippet
In the VB.NET application:
*/
Dim m As Mutex = _
New Mutex(False, "{11C92606-65D9-4df2-9AEA-B6A4DA91BCE2}")
If m.WaitOne(10, False) Then
Application.Run(New Form1())
m.ReleaseMutex()
Else
MessageBox.Show("Application already running!")
End If


Reference:
[VB 2005]如何避免程式(.exe)連開兩個以上

後記
除了維持單一執行應用程式外
應該不只是關閉新開的程式,而且要喚起即有的程式視窗
據說一般是利用hook達成... 等研究出來再補上

ClickOnce加入桌面Shortcut

ClickOnce本身沒支援
不過還是有人硬寫出來了

/// <summary>
/// This will create a Application Reference file on the users desktop
/// if they do not already have one when the program is loaded.
// If not debugging in visual studio check for Application Reference
// #if (!debug)
// CheckForShortcut();
// #endif
/// </summary>
void CheckForShortcut()
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
if (ad.IsFirstRun)
{
Assembly code = Assembly.GetExecutingAssembly();
string company = string.Empty;
string description = string.Empty;
if (Attribute.IsDefined(code, typeof(AssemblyCompanyAttribute)))
{
AssemblyCompanyAttribute ascompany = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(code,typeof(AssemblyCompanyAttribute));
company = ascompany.Company;

}
if (Attribute.IsDefined(code, typeof(AssemblyDescriptionAttribute)))
{
AssemblyDescriptionAttribute asdescription = (AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(code, typeof(AssemblyDescriptionAttribute));
description = asdescription.Description;
}
if (company != string.Empty && description != string.Empty)
{
string desktopPath = string.Empty;
desktopPath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "\\", description, ".appref-ms");
string shortcutName = string.Empty;
shortcutName = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "\\", company, "\\", description, ".appref-ms");
System.IO.File.Copy(shortcutName, desktopPath, true);
}
}
}


remark
1.clickonce利用company name在「開始/程式集」中建立路徑,而description為「捷徑檔的名稱」
所以記得在clicknoce中設置company及description,否則上面的程式會找不到
2.另外clickonce的「發行/選項」的「產品名稱」及「應用程式/組件資訊」的「描述」,兩者要一致,不然會找不到
說明:
「發行/選項」的「產品名稱」是clickonce部署後,在程式集命名捷徑的命稱
「應用程式/組件資訊」的「描述」是上述程式asdescription.Description所取得的,所以這一項要跟產品名稱相同,才找的到clickonce設的捷徑

References:
How to add Desktop Shortcut to ClickOnce Deployment Application

星期四, 1月 15, 2009

強迫退出程序

不知何時手賤加了什麼東西
利用Application.Exit()要將程式碼退出
就會發生「無法使用已經從其基礎 RCW 分離的 COM 物件」
不知是不是加了NotifyIcon的關係
總之... 給他強迫退出 Environment.Exit(0);
就開心的解決了

p.s 強迫退出後,NotifyIcon的圖示還會留著,所以要exit前,先將NotifyIcon.dispose();

Reference:
强制退出WinForm程序之Application.Exit和Environment.Eixt

星期三, 1月 14, 2009

JavaScript Regular Expression - 驗證

如何使用Regular Expression
//驗證email格式
var pattern = new RegExp();  
pattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (!pattern .test(email)) {
return false; //"email格式不對"
}
其實也不用特別再new RegExp,直接給pattern就可以了
javascript是這樣啦,其他的語言應該不行

  • 驗證email格式 *一定要有@
    pattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
  • 驗證密碼
    *至少有一個數字
    *至少有一個小寫英文字母
    *至少有一個大寫英文字母
    *字串長度在 6 ~ 16 個字母之間
    var pattern = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,16}$/;
    
    //簡單點,不考慮英文大小寫
    var pattern = /^(?=.*[a-zA-Z]+)(?=.*\d+).{6,16}$/;
Reference:
使用 Regular Expression 驗證密碼  

星期一, 1月 12, 2009

browser間的支援度

iframe問題
iframe doesn't work in IE7
原本利用屬性width及height設為100%,在ie7就會掛了
查了一下,利用style來設定就搞定
< IFRAME SRC='gnagna.htm' STYLE='width:100%;'>< /IFRAME>

星期四, 1月 08, 2009

利用PrintDocument列印

.net提供PrintDocument 的列印功能
以下是主要提供的功能
  • PrintDialog 顯示標準列印對話方塊,供使用者選擇印表機與變更印表機選項
  • PrintPreviewDialog 在預覽視窗中顯示報告內容
  • PrintPreviewControl 將第一頁報告內容顯示於可納入表單中的控制項
  • PageSetupDialog 顯示標準頁面設定對話方塊,讓使用者可選擇直向或橫向列印,以及變更邊界設定


new PrintDocument的物件
要自己handle PrintPageEvent
再用Print()來觸發PrintPageEvent
remark: 當利用PrintPreviewDialog時,ShowDialog即等同於Print()
也就是說會觸發PrintPageEvent

詳細內容可見reference

Reference:
列印的極限能力 有詳細的說明