上色

Code Block

2018年7月9日 星期一

[.Net] 以string,Join串接array of array(jagged array)

大家都知道使用string.Join可以串接陣列或清單中字串,像是下面這樣的形式
string[] source = new string[]{"one", "two", "three"};
string result = string.Join(",", source);

但是當陣列中還有陣列(jagged array, e.g. array of array)的時候怎麼辦呢?
這時候LINQ的Select語法就派上用場了,一層一層的串上去就對了
string[][][] source = new string[][][]{
 new string[][]{
  new string[]{"1", "2", "3"},
  new string[]{"one", "two", "three"}
 },
 new string[][]{
  new string[]{"4", "5", "6"},
  new string[]{"five", "six", "seven"}
 }
};

string result = string.Join(",", source.Select(m => string.Join(",", m.Select(n => string.Join(",", n)))));

如此一來就可以成功串接每一層陣列中的字串了。

Reference:
https://stackoverflow.com/questions/35102320/c-sharp-copying-jagged-arrays-to-strings


2018年7月4日 星期三

[.Net] Office interop runtime無法執行

紀錄一下最近遇到的問題,使用C#於MS Office 2013的環境上開發了一個程式,於MS Office 2010的機器上運作正常,但拿到MS Office 2007的機器上運作就會報錯。

首先,PIAs(Primary Interop Assemblies)必須與想要支援的最低版本相容,亦即想要支援Office 2007的話就必須使用v12的PIAs。
所以必須在Project的reference中加入v12版本的office PIAs(可以使用NuGet直接找到v12版本的PIA,亦即Microsoft.Office.Interop(v12)加入);但是光這樣是不夠的,因為當你的機器上有安裝更新版Office(如Office 2013)的時候,編譯時候會自動redirect到新版的PIAs,也就是在本機的GAC(global assembly cache)中所安裝的版本。

要修正這個問題,必須停止所謂的assembly binding redirection,可依照下列步驟進行:

1. 打開C:\Windows\Assembly\GAC或C:\Windows\Assembly\GAC_MSIL資料夾(根據你的windows版本而定)。
2. 找到對應的PIA,如我要使用Word的PIA,就找到Policy.12.0.Microsoft.Office.Interop.Word這樣的資料夾。
3. 在資料夾中找到設定的xml檔案,將下面這段註解掉
<bindingredirect newversion="14.0.0.0" oldversion="12.0.0.0"></bindingredirect>
變成
<!--<bindingredirect newversion="14.0.0.0" oldversion="12.0.0.0"></bindingredirect>-->
如此一來就會不會在redirect到新版本的PIAs,可以達到在不同機器上的相容性。

Reference:
https://stackoverflow.com/questions/6984733/office-2007-pia

2018年6月28日 星期四

[.Net] Embedded dll into exe

1. Add dll to resources, set the build action to "embedded resources" 2. Add following code to "Program.cs"
static void Main()
{
 //load resource dll
 AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

 Application.EnableVisualStyles();
 Application.SetCompatibleTextRenderingDefault(false);
 Application.Run(new frmTDSCreator());
}

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
 string resourceName = "TDSCreator.Resources." + new AssemblyName(args.Name).Name + ".dll";
 using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
 {
  byte[] assemblyData = new byte[stream.Length];
  stream.Read(assemblyData, 0, assemblyData.Length);
  return Assembly.Load(assemblyData);
 }
}