Quantcast
Channel: 天空的垃圾場
Viewing all 144 articles
Browse latest View live

Azure - Resource Group

$
0
0

如果有使用Azure新Portal的朋友,可能會發現"同質群組"這個東西不見了,反而出現一個以前從沒看過的新名詞"Resource Group"…

至於Resource Group是不是取代了同質群組,或是同質群組的強化版?,官方沒有明確的說 ( 也或許小弟沒看到.. ,但至少官方的定義不一樣,有可能Resource Group內含了同質群組的效果 ),但不管怎樣,我們先來看看甚麼是Resource Group吧~~

資源邊界

嗯,不是明日邊界,是資源邊界…在官方的官方文件裡面有提到,早期我們管理Azure資源,其實是一件非常麻煩( 其實小弟我覺得還好耶… )的事情…麻煩的原因是因為資源四處飛散;例如一個網站,可能會有DB、Web Site、Storage、AD、Cache等等等。

所以官方為了讓這些資源容易管理,就畫出了一個資源邊界,表示這個邊界內的東西,都屬於同一類;而這東西就稱為Resource Group,也可以稱為這些資源的生命週期;例如說,Study4的Resource Group;當Study4還存活著的時候,裡面的東西(例如DB、WebSIte)幾乎都還會用到;但如果Study4倒了…那要砍的時候,基本上就是全部一起砍了…而Resource Group就可以做到這種事情~故.官方也稱為這是這些資源的生命週期。

建立Resource Group

其實Resource Group不能獨立建立( 至少小弟沒找到… ),要建立Resource Group通常是要建立某個資源的時候,可以選擇使用新的Resource Group,或是使用現有的Resource Group。

例如下圖,我們要建立新的Website的時候,可以選擇使用現有的Resource Group,或是建立新的Resource Group;另外,如果是在以前的Protal建立的東西,其實也會在新的Portal呈現出來他的Resource Group;例如以前我有建立Virtual Network,那他也會自動建一個叫做Default-Networking的Resource Group,只是以前的Portal看不見罷了…

image

瀏覽Resource Group

就像下圖般,我們可以瀏覽目前所有的Resource Group,而且也可以透過Resource Group來查看這個Group底下的一些相關資訊與報告。

image

增加資源與刪除Resource Group

除此之外,我們可以透過下圖的這個按鈕來新增新的資源到這個資源群組裡。

另外,官方也有提到,官方不建議將Azure資源放到Team Project的資源組裡面… ( Visual Studio Online目前預設都會放在另外一個Resource Group )

image

我們也可以透過下圖的位置,直接刪除整個Resource Group。

image

參考資料


Azure - Website Web Hosting Plans

$
0
0

Web hosting plans (WHPs),也是新Portal才出現的名詞 ( 現在是怎樣= =..新Portal一出,一堆名詞通通跑出來… ),但這個觀念,其實以前就有…Web Hosting Plans主要是用在Website上,大家不知道還不記得,Website有個很便宜的特性,那就是你租用一個Website後,其實是可以放500個網站,而只要算一個的錢 ( Cloud Service表示 : …… ),而其實這個背後的概念,就是Web Hosting Plans。

網絡託管計劃(WHPs)其實就是代表一組功能和能力,而這一組(可以想成一台機器)的資源,就可以讓你的網站共享與使用;所以其實Website上的價位,算的就是WHPs的錢~~

所以這樣看完上面的解說,大家應該就通了吧~簡單的說,我們付Website的錢,就是租一台Server ( 嚴格來說,並不一定會等於一台,因為你可以在一個WHPs裡面有多個Instance,只是為了方便解釋,我們用一台來解說 ),而這台Server,官方就用比較好聽一點的名詞,稱為WHPs。

也因此,這個WHPs裏面上的所有Website,基本上都是共享同一個Resource Group、地理位置和你的Azure帳號~

當然,這又就有好處,也有壞處嚕,以壞處來說,就是整個就被綁住… ( 畢竟是同一台Server嘛… )至於好處…如果Web Hosting Plans有設定兩台Instance,那全部的網站,都會支援LB架構… ( 但如果裡面有些網站的Code沒有針對LB撰寫的話…就GG了… )

Resource Group、WHPs、Website

三者的關係就如同下圖,你每一個Website基本上會在WHPs裡面,而WHPs則會在Resource Group裡面。關於Resource Group,可以參考小弟的這篇

Resource Groups and Web Hosting Plans

建立新的Web Hosting Plan

我們可以建立新的Website時,選擇建立新的Web Hosting Plan,或是沿用現有的;而如果選擇現有的,則Resource Group會自動改成現有的Web Hosing Plan所屬的Resource Group。

另外要注意的是,你沒辦法建立空的Web Hosting Plan。

image

Website搬移Web Hosting Plan

Website的搬移,其實也有相關限制。

  • 在不同Resource Group底下的Web Hosting Plan不能搬移
    例如有兩個Resource Group A和Resource Group B,而這兩個Resource Group底下各自有兩個WHP A和WHP B,那屬於WHP A底下的site A是不能搬到WHP B底下的。
  • 同一個Resource Group,但底下的Web Hosting Plan在不同地區,也不能搬移
    例如有WHP A和WHP B,但WHP A在東亞,WHP B在東美,那WHP A底下的site A是不能搬到WHP B底下的。
  • 同一個Resource Group,但底下的Web Hosting Plan在相同區域,則可以搬移

至於未來會不會改,就看MS的規定吧;搬移的方式如下圖。

image

基本上就這樣嚕~@@~

參考資料

Azure - Application Insights

$
0
0

其實寫這篇之前,真的想小小抱怨一下,大家就稍微聽小弟發個牢騷吧QQ…

其實在Visual Studio Online推出Application Insights的時候,小弟就已經把圖片都整理好了,只是內文沒時間寫,後來小小的改版,圖也重新弄了一下,但那時候發現Application Insights Tools有一個Bug;那個Bug就是"如果你在Visual Studio裡面使用Application Insights註冊後,並簽入版控,別人取出來後,可以輕鬆地透過Visual Studio來進入擁有者的Visual Studio,換言之,就是擁有了Visual Studio Online的管理權限;也因此,小弟又把這篇文章給保留了…

直到Visual Studio 2013 Updata 3出了之後,基本上這個問題解決了…但整個部屬給我改到Azure去了…Orz… ( 雖說也是小弟的領域啦… )

但是…圖…整個要重弄了,整個要重弄了,整個要重弄了…

其次,佈署到Azure的Application Insights,和Visual Studio Online裡面的Application Insights是串不起來的!!!!換言之就是說,你可以在Azure看到Application Insights的資訊,但是Visual Studio Online裡面看不到!!

於是,又花了快一個禮拜的時間,斷斷續續地找資料。

結果在MSDN看到這段…

Application Insights is moving! For a while, there will be two versions:

We’re gradually building up features in the new version, and are doing no new development on the old one.

你整個搬家到Azure是沒關係啦…但你至少要在Visual Studio Online上講一下吧QQ….

唉,所以結論,小弟這邊就不介紹Visual Studio Online的部分了,直接看Azure上的Application Insights吧…( 下圖是 Visual Studio Online的畫面,就當作紀念留下吧… )

image

正文開始

上面抱怨完了,正文開始…Application Insights是Visual Studio Online很強的一個力作( 但目前被歸類到Azure上 ),他可以讓我們不用做啥事情(頂多設定),就可以快速的收集Server上的資料、使用者的狀況等資訊,例如:使用者用了哪些瀏覽器、看了那些網頁,這些類似Google分析的事情;但除此之外,他還支援了Server層級的訊息,例如:最長的反應時間、請求與錯誤訊息、還可以設定檢查,檢查網站是否活著!!

安裝與使用 – 在應用程式啟用Application Insights

如果是剛開始建立應用程式的情況,那我們可以直接勾選下圖的位置;但小弟我相信,這個情況通常不高XDD

image

通常我們都是已經有應用程式了;所以這邊,我們只要有安裝Visual Studio Updata 3,那就可以透過下圖的位置,輕易地安裝。

image

接下來,要使用Azure的帳號進行登入,如果這個應用程式已經在Azure上了,那可以選擇現有的Application Insights資源,因為現在建立新的Website,都會自己幫你建立一組…( 還好現在不收錢… )。

但如果還沒有在Azure建立過Website,或是沒打算佈署到Azure,只想使用Azure上的Application Insights,就可以使用新的Application Insights資源。

image

此外,如果要自己定義Resource Group,或是等資訊,可以先在Azure建立好Application Insights,然後再回到Visual Studio裡面進行輸入,也是可以的 ( 如下圖 ),這個步驟,小弟就不做了喔~

image

完成之後,會出現如下的檔案。

image

其實NuGet也自動的幫我們加了一些東西,如果未來不想監控了,也可以移除。

image

完成之後,我們其實啟動偵錯模式,他就會幫我們把訊息送到雲端上了喔!!!

image

這時候我們開啟Azure,其實就可以看到,已經把資料傳上來了,第一次的回應時間真久阿XDD

image

而且,如果Server有執行錯誤,也會被Application Insights吃到!!,只是現在Azure還不支援詳細的錯誤訊息… ( 未來會有,目前寫著Coming Soon… )

image

另外,大家可能會想到一件事情,那我這樣子,不是每次開發的時候,都會把錯誤等資訊往上面丟嗎!!?

其實在ApplicationInsight.config檔案裡面可以進行設定,只要把下面那行改為false,就不會把資訊往上丟了;而真正佈署的時候,再改成true就可以了。

<!--
      DeveloperMode setting controls Application Insights SDK behavior to optimize for local debugging. 
      This setting should be set to false before deploying your application.
    -->
    <DeveloperMode>true</DeveloperMode>

基本上,這樣基礎的功能就完成了,但還有兩個東西需要設定,才會得到更詳細的訊息。

建立Reponse測試

我們這邊可以建立Reponse測試來測試網站是否活著;如下圖。

除了測試名稱外,基本上我們也要給他一個URL;然後選擇要從哪邊發出測試;也可以自己定義成功的條件,還有是否要收到通知等相關項目。

image

加入使用者分析

除此之外,我們也希望能看到使用者的分析(類似Google分析),而要加入使用者分析,就必須加入JS,到你的應用程式裡面了,做法如下圖。

image

是的,就是底下那些JS Code,把它複製到HTML的head裡面就可以了。

image

基本上,就這些嚕

參考資料

Azure - 實作Azure上的AD與MVC進行驗證 - Azure設定篇 ( 二 )

$
0
0

上一篇的文章到現在,大概也整整過了4個月了,終於有時間繼續把這篇補完…上一篇完成了基本的Nuget套件設定、DLL參考、還有Azure的設定,而這篇,我們就著重在Web.config上吧。

首先,我們要在Web.config裡面的configuration底下,加入configSections區段…

<configuration>
  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </configSections>

接下來,我們要在appSettings底下,加入以下資訊,比較需要注意的是,ida:Realm和ida:AudienceUri,後面的value值就是我們前一篇的輸入的應用程式識別碼URL,而ida:ClientID和ida : Password就是我們前一篇要大家記的ID和PW喔!~

<add key="ida:FederationMetadataLocation" value="https://login.windows.net/study4.tw/FederationMetadata/2007-06/FederationMetadata.xml" />
<add key="ida:Realm" value="https://study4.tw/TestAD" />
<add key="ida:AudienceUri" value="https://study4.tw/TestAD" />
<add key="ida:ClientID" value="dce9aa7d-adf3-42dc-ac5e-d5043047adec" />
<add key="ida:Password" value="41O94SwvthtAs99tQIWpHhdRkXBQNjPax0fQ9orOcXc=" />

所以完成的會如下。

<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="ida:FederationMetadataLocation" value="https://login.windows.net/study4.tw/FederationMetadata/2007-06/FederationMetadata.xml" />
    <add key="ida:Realm" value="https://study4.tw/TestAD" />
    <add key="ida:AudienceUri" value="https://study4.tw/TestAD" />
    <add key="ida:ClientID" value="dce9aa7d-adf3-42dc-ac5e-d5043047adec" />
    <add key="ida:Password" value="41O94SwvthtAs99tQIWpHhdRkXBQNjPax0fQ9orOcXc=" />
  </appSettings>

下圖是另外一個範例,用的是Study4IdentityForAD,所以會Key成這樣。

image

接下來,我們要設定驗證區段,這邊,不管哪個目錄,反正要看到網站內容,就要先登入AD…

<location path="Account">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

然後system.web底下要改成如下。

<system.web>
      <authentication mode="None" />
      <authorization>
        <deny users="?" />
      </authorization>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" requestValidationMode="4.5" />

最後,我們要在加上底下的區段,畢竟Web.config一開始有設這個區段阿,所以我們還是要把這個區段補上,這個區段只要在設定identityModel的相關資訊,而這邊比較需要注意的是issuerNameRegistry這邊,後面的type要輸入的是專案名稱加上Utils.DatabaseIssuerNameRegistry,而後面的逗點之後,也要輸入專案的名稱;所以以這邊為案例,就是要輸入WebApplication2.Utils.DatabaseIssuerNameRegistry,WebApplication2。

<system.identityModel>
    <identityConfiguration>
      <issuerNameRegistry type="WebApplication2.Utils.DatabaseIssuerNameRegistry, WebApplication2" />
      <audienceUris>
        <add value="https://study4.tw/TestAD" />
      </audienceUris>
      <securityTokenHandlers>
        <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </securityTokenHandlers>
      <certificateValidation certificateValidationMode="None" />
    </identityConfiguration>
  </system.identityModel>

如下圖,用的是Study4IdentityForAD,所以要輸入Study4IdentityForAD。

image[53]

最後,我們還有system.webServer這個區段要設定,一樣wsFederation裡面,需要設定應用程式識別碼URL。

<system.webServer>
    <modules>
      <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
  </system.webServer>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="true" />
      <wsFederation passiveRedirectEnabled="true" issuer="https://login.windows.net/study4.tw/wsfed" realm="https://study4.tw/TestAD" requireHttps="true" />
    </federationConfiguration>
  </system.identityModel.services>

最後,因為我們這個專案主要是使用SSL,所以別忘了把SSL開啟喔!!~

image

納因為這邊給的PORT是44303,所以我們還要回到Azure那邊去改一下資料。

image

到這邊為止,我們算是設定好了…接下來要開始用一些Code…

參考資料

Azure - 實作Azure上的AD與MVC進行驗證 - Azure設定篇 ( 三 )

$
0
0

持續努力,現在進入第三篇了!!,第三篇我們先以完成為目標,所以小弟先不在這邊講Code的內容了,這部份未來再補上。

image

TenantDbContext.cs的內容為:

using System;
using System.Data.Entity;

namespace WebApplication2.Models
{
    public class TenantDbContext : DbContext
    {
        public TenantDbContext()
            : base("DefaultConnection")
        {
        }

        public DbSet<IssuingAuthorityKey> IssuingAuthorityKeys { get; set; }

        public DbSet<Tenant> Tenants { get; set; }
    }
}

TenantRegistrationModels.cs的內容為:

using System;
using System.Collections.Generic;
using System.Linq;

namespace WebApplication2.Models
{
    public class IssuingAuthorityKey
    {
        public string Id { get; set; }
    }

    public class Tenant
    {
        public string Id { get; set; }
    }
}

接著,我們要建立一個Utils的目錄,然後建立一個DatabaseIssuerNameRegistry.cs檔案。

image

DatabaseIssuerNameRegistry.cs的內容為:

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Hosting;
using System.Xml.Linq;
using WebApplication2.Models;

namespace WebApplication2.Utils
{
    public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
    {
        public static bool ContainsTenant(string tenantId)
        {
            using (TenantDbContext context = new TenantDbContext())
            {
                return context.Tenants
                    .Where(tenant => tenant.Id == tenantId)
                    .Any();
            }
        }

        public static bool ContainsKey(string thumbprint)
        {
            using (TenantDbContext context = new TenantDbContext())
            {
                return context.IssuingAuthorityKeys
                    .Where(key => key.Id == thumbprint)
                    .Any();
            }
        }

        public static void RefreshKeys(string metadataLocation)
        {
            IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);

            bool newKeys = false;
            bool refreshTenant = false;
            foreach (string thumbprint in issuingAuthority.Thumbprints)
            {
                if (!ContainsKey(thumbprint))
                {
                    newKeys = true;
                    refreshTenant = true;
                    break;
                }
            }

            foreach (string issuer in issuingAuthority.Issuers)
            {
                if (!ContainsTenant(GetIssuerId(issuer)))
                {
                    refreshTenant = true;
                    break;
                }
            }

            if (newKeys || refreshTenant)
            {
                using (TenantDbContext context = new TenantDbContext())
                {
                    if (newKeys)
                    {
                        context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
                        foreach (string thumbprint in issuingAuthority.Thumbprints)
                        {
                            context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
                        }
                    }

                    if (refreshTenant)
                    {
                        foreach (string issuer in issuingAuthority.Issuers)
                        {
                            string issuerId = GetIssuerId(issuer);
                            if (!ContainsTenant(issuerId))
                            {
                                context.Tenants.Add(new Tenant { Id = issuerId });
                            }
                        }
                    }
                    context.SaveChanges();
                }
            }
        }

        private static string GetIssuerId(string issuer)
        {
            return issuer.TrimEnd('/').Split('/').Last();
        }

        protected override bool IsThumbprintValid(string thumbprint, string issuer)
        {
            return ContainsTenant(GetIssuerId(issuer))
                && ContainsKey(thumbprint);
        }
    }
}

接下來,我們要在App_Start底下新增IdentityConfig.cs檔案。

image

IdentityConfig.cs的內容為:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Claims;
using System.IdentityModel.Services;
using System.Linq;
using System.Web.Helpers;
using WebApplication2.Utils;

namespace WebApplication2
{
    // 如需 ASP.NET Identity 的詳細資訊,請造訪 http://go.microsoft.com/fwlink/?LinkId=301863
    public static class IdentityConfig
    {
        public static string AudienceUri { get; private set; }
        public static string Realm { get; private set; }

        public static void ConfigureIdentity()
        {
            RefreshValidationSettings();
            // 設定應用程式領域
            Realm = ConfigurationManager.AppSettings["ida:realm"];

            // 設定應用程式 audienceUri
            AudienceUri = ConfigurationManager.AppSettings["ida:AudienceUri"];
            if (!String.IsNullOrEmpty(AudienceUri))
            {
                UpdateAudienceUri();
            }

            AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;
        }

        public static void RefreshValidationSettings()
        {
            string metadataLocation = ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
            DatabaseIssuerNameRegistry.RefreshKeys(metadataLocation);
        }

        public static void UpdateAudienceUri()
        {
            int count = FederatedAuthentication.FederationConfiguration.IdentityConfiguration
                .AudienceRestriction.AllowedAudienceUris.Count(
                    uri => String.Equals(uri.OriginalString, AudienceUri, StringComparison.OrdinalIgnoreCase));
            if (count == 0)
            {
                FederatedAuthentication.FederationConfiguration.IdentityConfiguration
                    .AudienceRestriction.AllowedAudienceUris.Add(new Uri(IdentityConfig.AudienceUri));
            }
        }
    }
}

接下來,我們要在Global.asax裡面加入註冊使用上面的IdentityConfig。

image

加入IdentityConfig.ConfigureIdentity();

void Application_Start(object sender, EventArgs e)
{
    // 應用程式啟動時執行的程式碼
    AreaRegistration.RegisterAllAreas();
    IdentityConfig.ConfigureIdentity();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    RouteConfig.RegisterRoutes(RouteTable.Routes);            
}

最後,我們有用到DB,所以還是要補一下連線字串;這邊小弟我是使用LocalDB,大家也可以建立自己想要的DB位置。

<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-WebApplication1-20140901114034.mdf;Initial Catalog=aspnet-WebApplication1-20140901114034;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

完成之後,你會發現,使用HTTPS時,就會要求先使用Azure來登入帳號了~~

image

以上!!

參考資料

Visual Studio - 安裝Node.js Tools

$
0
0

最近因為某些需求裝了Node.js,而裝了Node.js後,又覺得不使用一下Node.js Tools for Visual Studio感覺很對不起機器上的Visual Studio…於是就誕生出了這篇…( 其實這篇也是安裝的過程中,順便紀錄的… )

首先,我們要先到Node.js的官網,到這 裡下載,Windows版本就有分兩種,一種是msi,另外一個是exe。

如果你是懶人,就選擇msi,他會幫你把環境變數等等相關資訊都弄好,或是選擇純粹的node.exe檔案,但這樣,你的PATH、npm就要自行準備與設定。

這邊小弟使用msi來安裝~~

image

下載完之後,就安裝就對了…

image

安裝完成後,要到這裡下載Node.js Tools for Visual Studio。

image

然後就給他安裝下去就對了= =+,接下來,就可以看到Node.js的專案範本了…

image

完成之後,也可以透過Visual Studio去控管npm

image

另外也可以透過VS工具來執行命令。

image

不過前面還要加一個點,就是了…image

按下執行,就會開始跑了,現在連Hello World都不用寫了XDDD

image

完成之後,就可以進入Node.js的開發人生了!! (疑!?)

參考資料

npm - 為什麼在Windows底下更新npm無效

$
0
0

這篇談論的是在Windows底下,使用Node.js msi檔安裝Node.js後,輸入npm update npm –g 無法更新的原因與解決方案 ( 其實也沒有解決方案啦… )

透過Node.js的msi安裝的npm,是無法透過npm update npm -g來更新npm版本的,按下去是沒有反應的…那是因為用msi安裝的npm,預設是放在Program Files\nodejs\npm底下,然後透過PATH來指定到Program Files\nodejs\npm底下的npm,但真正Global的位置卻是在users\skychang\AppData\Roaming\npm底下,換言之,透過msi安裝的npm不是在Global,也因此透過-g指令,是無法更新的… ( 因為Global裡面本來就沒有npm,而是放在Program Files\nodejs\npm底下 )。

當然,我們可以用npm install npm -g再安裝一次npm到global底下。( 但這也要小心…等下會解釋到…平常沒事,也不建議這樣做… )

或是進入到c:\program files\nodejs,使用npm update npm來裝… ( 但是同上,要小心… )

image

當用npm install npm -g安裝到global,或是進入目錄更新npm,要注意第一件事情;必須使用專用的Node.js command prompt才能優先找到Global的npm,那是因為PATH路徑順序的問題,可以看下圖,下半段是Node.js command prompt PATH,上半段是一般的PATH,可以發現,下半段的順序,會先吃到Users\skychang\AppData\Roaming\npm;但上半段則是會先吃到Program Files\nodesjs。

image_thumb24

另外,要注意的第二件事情,當使用了npm install npm –g 將npm裝到Global後,要重新於安裝npm的目錄下重新設定.npmrc這個檔案,不然你會發現,Globalconfig、prefix的路徑都不是指向原本的AppData\Roaming底下了…( 變成Global是吃C:\Program Files\nodejs\etc\npmrc這個檔案 )

另外…prefix這邊( 可以透過npm config ls –l 列出詳細資訊,詳細資訊請參考下圖 ),對應的是C:\\Program Files\nodejs,也不是AppData\Roaming底下了…

image_thumb2

換言之,就代表,如果你未設定.npmrc,那未來你安裝Global的套件,預設會變成安裝到C:\\Program Files\nodejs底下…這是一件很可怕的事情啊XDD ( 而且整個可能會錯亂掉… )

所以,當更新完npm後,要不就是針對User在C:\Users\skychang\設定.npmrc,要不然就是要在C:\Program Files\nodejs\node_modules\npm底下重新改寫.npmrc,而且要調整一些Config…

所以,在這邊還是建議,沒有特別必要更新npm的話,跟著msi版本就好…,當msi版本更新,在重裝就好…不然改錯、遺忘、或是又在一次更新npm的時候,放在C:\Program Files\nodejs\node_modules\npm底下的東西都會被刪除掉…

最後,底下是沒更新時候,預設的設定檔;我們可以看到prefix已經被overridden了,所以會將Global安裝到Roaming底下…而Globalconfig等參數,也不是指向C:\Program Files\nodejs\,而是指到AppData\Roaming…

image_thumb4

而實際上,因為用msi裝的,所以npm並非Global,所以他是吃自己底下的npmrc檔案,而裡面可以看到,他重新定義了prefix。

image_thumb6

但是因為我們更新了npm,所以上面那些東西在更新後,就全部都不見了XDD,所以都要重新設定…

結論

如果真的要更新…就別忘了去改.npmrc檔案,而這個.npmrc檔案,你可以放在User\xxxx底下 ( 但就不能大家共用 ),或是C:\Program Files\nodejs\node_modules\npm底下.. ( 但更新的時候,就bye bye了… )。

而更新檔的內容,也要調整Global等相關設定、Prefix等相關設定…

所以其實滿吃力不討好的… ( 當然,如果你是神人階級的例外啦XDD )

另外,就是完全不要使用msi安裝包來安裝…而是先下載nodejs.exe檔案,然後npm再從Github抓下來後編譯,也是一個辦法啦…但這就會要自己設定%PATH%等相關路徑… ( 老實說,小弟也很懶得搞這些… )

So…除非必要,不然就不要更新npm吧,真的要更新,就透過msi檔來更新吧…是比較輕鬆的方法嚕…

參考資料

TechDays 2014 遊記

$
0
0

首先,這篇不是筆記,如果要找上課筆記,那可以去全台灣最陽光的黑暗大的家裡,找到筆記喔XDD。

TechDays已經是每年必定參加的年度大拜拜了…從2010年開始,小弟就每年固定參加,到今年,也正式邁入第四年!!而為了參加TechDays,每次到新的工作環境,面試的時候,必定都會問面試官…"請問貴公司,每年是否可以去參加三天的TechDays??",而好家在的是,現在我們公司連問都不用問,是全公司都被"強迫"參加XDDD,我們都笑稱這是公司年度的員工旅遊阿~~( 老實說,這種員工旅遊還不賴說~~ )

Day – 1

第一天一樣起個早,不過從去年開始,因為整個搬到台北來了,所以不用像以前一樣,還要搭很早的高鐵北上~~而在前往會場的路上,其實就陸陸續續看到很像要去參加大會的Developer!!( 有聞到同類的感覺~ )

2014-09-09 08.41.32

每年必拍的看板,目前已經累積到四張看板照片了XDD,這次Study4.TW一樣有參加喔!!

2014-09-09 08.43.53

這是我們的攤位,但今年小弟實在是非常忙碌,所以這攤位到最後就變成了大家的休息區…沒有和twMVC或是背後有超級金主的SQL PASS有豐富的準備…這是我們社群今年要檢討的… ( SQL PASS還有$$可以請工讀生耶.>"<. )

2014-09-09 09.05.43

每年必定參加的KeyNote,今年TechDays也邁入了第20年,而這場,也是塞滿最多人的一場,當時小弟到會場的時候,連位置都找不到了…(哭)

2014-09-09 09.31.43

Eric老大的酷照;當然,重點不是老大他,而是那閃亮的蘋果!!,與其說他在展示跨平台應用,不知為何,更感覺他在Show他的Apple = =…

不過不管怎麼說,以前這種大會,一定只能出現IE、不能出現Apple的條文,現在也逐漸改變了,MS逐漸地走向Open,而Eric老大這邊拿出Apple Demo的意味就不是那麼的單純而是深遠了~

2014-09-09 09.56.09

此外,這次還有請到國外的研發部門來講課,他要Demo的是海量數據的分析。

2014-09-09 10.56.05

他們實作了全球最複雜的倫敦地鐵海量分析,透過這個分析,可以分析出,在哪個時間點,那些電梯、硬體,可能會出現故障!!

2014-09-09 10.59.04

Dev Team、IT Team結束之後,是Office的Team…從排場也可以看出,哪個Team是有賺錢的…Orz…這次Office Team竟然請到了邰智源…果然明星一出場,氣勢,場子的感覺就變了,變得很熱鬧。

2014-09-09 11.30.53

基本上,第一天早上都待在大會堂,下午開始,小弟就準備自己的課程,所以就沒拍照片了…過程中,偷偷的去偵查王寧疆老師的Application Insights ( 因為小弟也有上到… ),然後看黃忠成老師將MVC掛在PI上面… ( 但因為要準備,沒辦法認真地聽… )。

最後一場,就是小弟自己的場次了,以下是進場的照片~~

2014-09-09 16.38.41

講完之後,第一天就結束了~~

Day - 2

進入第二天,又起了一個超級早…因為第二天的第一堂就要去擔任Kent的助手…所以7:30以前就已經到會場討論了…

以下是第二天第一堂的進場畫面… ( 小弟我也只有空拍進場畫面阿XDDD ),然後就開始擔任助手了~~

2014-09-10 08.29.37

結束之後,終於比較有閒,可以到處去晃晃,首站當然是MVP攤位,這是每年都會出現的MVP簽名板;也順便推廣一下,年底有大型的比賽與活動喔,有興趣的朋友到時候可以關注一下…( 絕對不是MVP Group推出了啥Online Game喔.. )

SONY DSC

今年MVP攤位很特別的準備了充電講座,讓主舞台之外,外場還有由專業的MVP來講一些深入的技術。

SONY DSC

這場是由昏睡領域的克拉克前輩,帶來架構上的議題,可惜這次沒有投影機,不然應該會更棒。

SONY DSC

克拉克前輩很認真地講解中,雖然克拉克前輩都說,他講課台下都會睡一片,所以才叫昏睡領域,但實際上,很棒啊!! 大家都很認真地再聽說…

SONY DSC

這時候小弟我也順便偷拍,第二天最後一堂要講課的18王爺XDD,他準備的超認真的,完全無視( 沒發現到 ),我再偷拍他 = =+…

SONY DSC

後來我同事(紫色衣服那位.)也跑進來聽,但沒位置了,所以我就把我的位置讓給他,跑去到處晃晃… ( 絕對不是我不想聽克拉克前輩上課喔!! )

SONY DSC

後來在外面遇到保哥~果然,講課拿他作梗的事情,被他發現了XDDDD,所以這邊補上一張他的照片,來感謝他一下… ( 四年後,又可以拿來做梗XDD )

SONY DSC

後續就顧著攤位,還有去聽Bill叔的課程,但畢竟手機開發的經驗不足,所以整場就沒閒暇可以拍照…( 其實有偷偷的睡著一下…Orz… )

最後一場,18王爺的課程,講的是Cordava,也就是原本的PhoneGap拉出來的東東,可以透過撰寫HTML、JS,來讓你的應用程式跨不同的平台!!

2014-09-10 16.59.23

當然,免不了的Hello World還是要的XDD

2014-09-10 17.13.41

就這樣,第二天結束嚕!!~

Day - 3

第三天的第一場,就跑去贊助Demo哥的網站開發技巧;喔,對了,請大家忘記Demo的中文名子喔~

2014-09-11 08.36.26

Demo流暢的Demo (好繞舌),果然贏得滿堂彩,根據內線情報指出,還有人在會場講說,學到超多東西呢!!

2014-09-11 08.59.55

當然,Demo哥絕對不會忘記置入式行銷的 (菸)… 不過如果書的內容不好,還置入式行銷就不好了,但實際上,這本書真的很值得買~~

2014-09-11 09.51.10

第二場是Dino的場次,講SignalR!!,去年Dino也是負責SignalR喔~

2014-09-11 10.19.20

Dino一開始講,就整場鴉雀無聲…Dino完全Live Coding…把小弟的完全影片Demo打假的XDD。

2014-09-11 10.37.54

早上結束之後,中午休息,就到三樓晃晃,這次三樓的攤位還滿熱鬧的,有送各種不同的徽章,還有可以客製化徽章喔!!

另外Azure Girl養成計畫不知道是誰提的…但不知道為何,看到這幾個字,就讓我想到Franma = =…

SONY DSC

比較酷的是,趕上時尚潮流,這次TechDays竟然搬出了霜淇淋機器…

SONY DSC

會場中,也捕獲了野生Aska XDDD。

SONY DSC

除此之外…msdn攤位,也有很多精美的海報可以拿喔~~

SONY DSC

今年天瓏又搬出了10kg抽獎,這又讓我想到以前的IE 9 Party…

SONY DSC

晃啊晃,後來聽說Bibibi來了,所以又晃回MVP攤位,這時候Bibibi已經在講課了…

SONY DSC

就如FB大家所說的,從來沒看過認真的Bibibi…而他留下的名言就是…除了技術以外,還有很多事情值得去做~~

SONY DSC

結束了中間的行程後,下午繼續支持朋友的場次,這場是Bruce的場次喔!!

2014-09-11 13.28.55

因為他躲在角落,所以只能遠遠的再拍一張…

2014-09-11 14.05.44

老實說,我也好幾年沒寫Web Forms了,沒想到Web Forms現在變化那麼大!!!而Bruce也提到,ASP.NET vNext目前與Web Forms無緣阿…

2014-09-11 14.34.05

聽完之後,又回到攤位顧攤…直到最後一場,由Ruddy師傅與Franma攜手合作的黃金場次。

2014-09-11 16.38.00

祖師爺級就是不同…無論是深度、換場、內容,都無懈可擊阿… ( 記得,想看筆記的話去找陽光的黑大XDD )

2014-09-11 17.07.32

那基本上,聽完這場,三天的TechDays也進入了尾聲…

後記

現在隨著時代的進步,網路上影片、資訊也越來越充足;那到底還要不要花錢去聽TechDay?,老實說,我是覺得還是值得的,雖然價格不低,住在台北以外的朋友可能還要花費住宿,車錢,請假費用…也或許後續可以從網路上看到影片等等…

但只有真的去過後,就會發現,這種成長,並不只是技術上的成長,還有心靈上的成長,會場中,你可以看到不同的技術人員,不同的高手在會場上穿梭,而與那些高手討論交流的過程,跟本不是看影片就可以得到的,所以,如果資金上許可,還是建議大家可以實際的去晃晃,相信會有不同的收穫喔!!

最後,大家明年見嚕!!


TechDays 2014 - 使用 Azure Web Site 打造雲端網站 - 全方位的網站管理、佈署與監控技巧

$
0
0

今年的年度聚會TechDays 2014又結束了,每次TechDays結束,就意味著暑假也結束了,今年夏天又要過了,然後,到了年底,就是趕案子加班的日子了…抖抖…

今年TechDays講的主題是"使用 Azure Web Site 打造雲端網站 - 全方位的網站管理、佈署與監控技巧",那相信有很多朋友在等著錄影檔,所以這邊就先不多說廢話,先供奉上錄影檔在說嚕。

Demo影片下載

PhotoWall的Source Code

接下來,就是Sky的碎碎念與幕後花絮了,有興趣的朋友,再繼續往下看下去吧=v=

準備

如果有拿到光碟的朋友,大概也會看到下面這張圖,這張圖其實是小弟我在準備講這堂課前的手稿…( 嗯..字醜不是重點.. )

2014-09-08 23.07.04

當初規劃這堂課程的時候,心中也有很多疑問,到底要端出怎樣的菜色給大家??

其實這是一個沒有答案的問題,來上課的朋友,有些人可能完全沒碰過Azure,有些人在實務上已經用的很深入,而有些人搞不好連Azure是甚麼都不知道… ( 讓我想到那個徽章…Azure是甚麼?能吃嗎??XDD );那我在Demo的時候,到底是要把一個一個的功能去做展現,還是要把東西串起來,又或者是要從頭開始介紹Azure ??

後來小弟我決定的是,將Azure串起來進行Demo,而不是一個功能一個功能去作呈現;會選擇這個的原因,是因為希望讓台下的朋友們,感受到的是一個整個Azure的整合與應用,而非單獨一個功能一個功能。

所以後來敲定的流程,就是從一個專案的開始,從建立專案,到佈署、開發、監控與各種關於Azure Web Site的功能與使用…

當然,這也造成後續整個講課過程delay …

影片

其實如果可以,小弟我也百萬個不願意用影片Demo QQ…

如果有朋友Follow小弟的FB…其實就可以發現在TechDays前的一兩個月,就已經聽到小弟在FB狂抱怨New Portal… ( 但畢竟人家是Preview…也怨不得人家阿QQ… )

在過程中,第一個遇到的問題就是慢…New Portal的UX真的非常慢…接下來,就是不穩定因素太多…小弟我在實驗過程中所遇到的問題其實滿多的,而且也沒辦法避開… ( 常常這次ok,下次失敗… ),所以最後也只能決定放棄直接Demo,改用影片的方式…畢竟在過程中,實在是沒辦法讓大家看到一直不斷失敗的Demo阿…

所以最終決定的就是錄影片了…

中秋節

不知道大家有沒有發現,TechDays固定是星期2、3、4…然後一定是中秋節過後的那個禮拜!! ( 其實小弟也是今年聽前輩說才發現… ),而今年中秋節整整的三天放假,就努力的在錄那些影片…是的,整整三天都在錄…沒去烤啥肉 ( 電腦是快燒起來了… ),也沒看到月亮 ( 到是有看到檯燈… ),那為什麼短短的幾支影片,就需要耗掉三天!?;其實應該反過來說…就是因為會需要耗掉三天,所以才不敢當場Demo阿!!!!~

但不管怎樣,其實我覺得三天放假都在搞這些,也都還好,畢竟3天對小弟來說是72小時,但如果沒準備好,當天現場出狀況,如果以500人計算,70分鐘乘上500,就不是短短的72小時了;我相信每個講師的心中想法都是一樣的,大家都背負著台下每個人的每分每秒,所以大家通常會抱怨的都是系統不穩XDD,而不會抱怨說沒辦法放假,無法過中秋=V=。

縮小架構

其實在真實上,錄出來的影片 ( 錄失敗的就不說了 ) ,成功的影片不只上面那些,大概整整快多了兩倍…當初初期的規劃,其實還有建置測試的環境;但計算時間的時候,就發現時間不夠用了,所以就把測是那塊的環境建置,全部給砍了…

PhotoWall

這個事情是發生在錄影片之前,也是畫架構圖之前臨時決定的應用程式;其實當初並沒有特別要準備一個應用程式,比較將重心放於Azure的功能面上,後來看到Ruddy師傅、黃忠成老師都準備了一些很棒的Demo,才決定做一個PhotoWall,而後來也將整個Demo串起來…

而當初預期最好的狀況是,Live建置環境,然後Live Coding,最後讓會場的大家可以直接將照片上傳到Azure上去…

image

但後來還是沒辦法成真,其中一個原因就如前面說的…New Portal有一些問題、其次就是時間上的不允許…

所以到最後,就演變成這個範例先準備好,而以這個範例為核心,用類似回顧的方式,來介紹Azure的服務,而Code的撰寫部分,就只能犧牲掉了…

投影片

雖然說砍掉了很多東西,但其實到最後,投影片也累積了97張…如果以現場70min來說,97張投影片,都快要可以變成動畫了…Orz…所以在講課前,其實就已經預測到會延誤下課了= =+。

講課過程

過程中,會緊張嗎?…其實也不是第一次講課了…而且在台上往下看,也真的只能看到第一排XDD,其餘幾乎都只看到探照燈..Orz…所以其實完全不會緊張…

但這次講課的過程中,卻有一些沒處理好的事情,舉例來說,發光碟這件事情…其實當初應該是要把光碟先放在講台前…後來忘記了…Orz…所以在傳遞的過程中也遇到一些小問題…

其次;過程中幾乎都是座著講…其實我自己是比較喜歡站著的,但就如前面說的,在看完投影片後,大概也可以預期一定會延誤下課,所以後來就變成專注於趕課…所以也沒辦法站起來好好講QQ…所以其實嚴格說起來,這次的備課,是有一點缺失的~~想給的東西太多,沒有再好好精簡的結果阿!!~

其次就是影片的撥放,到後期,我也感受到,整個影片其實是很跳動,又很快的…所以這部份也在這邊和學員說聲抱歉>"<…

下圖是剛開放進場的狀況…

2014-09-09 16.38.41

當然,在這過程中,還是要感謝上圖坐在第一排,幫忙當跑退的好友饅頭兄,真的很感謝他義無反顧地幫小弟我發光碟>"<~

後續

目前還沒拿到大家的意見回饋,但除了上面提到的缺失外,影片、Code的提供,其實也可以早一點放到投影片上面給大家拍…這樣大家就不用等著這篇文章的出現…

此外,以前有老師說過,台上一分鐘,台下十年功,其實真的一點也不錯,雖然只有短短的70min,但我相信不管是哪個老師,從頭地收集資料,然後篩選出適合大家的課程內容,再經過不知道幾次的review,調整;其實到上台前一分鐘,大家可能都還在調整投影片,為的就是能讓各位朋友有更多的收穫~~也為的是台下朋友聽完那滿足的表情~~

當然,很多東西小弟也沒做到盡善盡美,也有很多不好之處,這也請大家多多包涵了。

那最後,還是要感謝當天來聽課的朋友,與背後支持的朋友,謝謝大家!~明年TechDays見嚕~

ASP.NET MVC - 真正的Web前端套件管理工具Bower

$
0
0

如果說…Scott Gu發表了Blog文章,那就代表了Azure又一堆東西要更新了…而如果是Scott Hanselman發表文章,那就代表著Microsoft這邊的Web開發又有新玩意了… ( 所以本質上,小弟本人滿討厭他們發文章的XDD )

而這次要探討的就是由Scott Hanselman發表的一篇文章,這篇文章的內文,大致上是講VS 2014將更加地符合現代前端的開發使用者,並且支援NPM、Bower、Gulp這些東西…

啥,完全沒聽過!?…其實沒聽過也是正常的,畢竟這些都屬於前端的玩意,Microsoft陣營的朋友可能都沒聽過,但對於JavaScript的神人,這些東西就等同於我們的NuGet一樣的平凡,而且每天都在用喔!!~~

所以今天來看一下Bower這個玩意…

Bower

是Twitter推出的,管理Web Package的一個工具,是的,他很像NuGet,我們可以透過Bower來進行套件的下載、相依性的管理;那大家的第一個疑問是…那和NuGet有啥兩樣!?…根據Scott的解釋是說…NuGet是Server端的套件管理工具,而Bower是前端的套件管理工具…那為什麼NuGet不能包含前端呢? ( 其實現在也有包含前端 ),Scott是說,因為目前已經有很多很棒的工具了…既然如此,那為何不用人家準備好的工具呢!??

好…基本上政治議題不是我們能關切與參與的…身為Developer,我們只要知道未來有怎樣的改變就好,所以…我們還是來看看Bower吧!!

image

首先,我們要安裝Bower之前…我們要先安裝npm…而npm則需要Node.js…所以大家可以翻翻小弟之前的文章,基本上Node.js很好安裝的;安裝完成之後,我們就擁有了npm,我們就可以輸入以下指令來安裝bower。

image

安裝完成之後,我們就可以隨處的安裝我們要的套件…,如果不知道有那些套件,可以從官網去做搜尋…

image

那接下來要怎樣安裝套件呢??大家可以參考官網的說明,基本上可以用install就可以來安裝套件,後面還可以接Git喔!!

image

那這邊,我有開了一個BowerTest的專案,我打算在這個空的專案底下裝上AngularJS;所以我就可以輸入。

bower install angular

但按下後,就遇到問題了…Orz…那是因為Bower下載需要透過Git…而且要設定PATH… ( 到這邊大家有沒有覺得其實Microsoft以前都幫我們處理得好好的,真的很幸福!? )

image

接下來,大家可以去網路上下載Git,然後再自行設定PATH,或是和小弟一樣,將很懶的個性發揮到極致…

小弟這邊的做法是去GitHub下載GitHub for Windows,這樣就有Git的指令了…但是雖然有Git的指令,但還是沒有設定PATH,而小弟也懶得去設定…所以小弟就直接打開Git Shell…

image

然後再一次,就可以了!!

image

基本上,bower會將下載來的東西放到bower_components底下…

image

大家如果看到上圖,應該會覺得,為啥AngularJS的東西那麼少…其實大家可以去AngularJS的GitHub看到,它們把所需要的東西都拆開了喔~~,如果想要一次下載全部版本,也可以去找angular-latest的這個版本。

image

自訂Package

接下來,我們可以自行定義Package,這邊指的Package有兩種涵義,一種是自己開發的Lib包成Package,放到Bower Server給大家下載;另外一種涵義則是把自行常用的東西包成一個.json檔案,到時候可以快速的一次下載;而這邊講的是後者喔。

首先,我們可以使用

bower init

這個指令,這個指令可以幫助我們建立bower.json檔案,到時候我們就可以把這個檔案Copy到其他專案快速重新下載Lib使用;過程中,會問一些小問題,後面會解釋到。

image

這邊列出了bower.json裡面用到的參數,那基本上也和建立bower.json時所問的問題差不多,相信大家比較一下大概就會清楚了,基本上,如果是自用,大概只需要填名稱,其他全部都選yes就可以了。

  • name (必填): 你的package名稱,如果未來要放到Bower Server上,公開給別人使用,則需要特別注意名稱。
  • version: 版本號。
  • mainstring or array: 你這個Package主要的檔案。
  • ignorearray: 你希望Bower略過的檔案。
  • keywordsarray of string: 如果放到Bower Server上,關於你這個package的關鍵字,這有助於被容易尋找到。
  • dependencieshash: 相依的package,也可以標明版本。
  • devDependencieshash: 開發用的dependencies。
  • privateboolean: 如果設為True,就可以防止被傳到Bower Server上去。

另外上面的選項還有what types of modules  does this package expose?,表示你使用哪一種JS的modules…例如 amd、es6等等…通常沒特別的話,按下enter,略過就可以。

set currently installed components as dependencies? 是否將目前安裝的套建設為依賴。
add commonly ignored files to ignore list?: 是否添加常用忽略的文件列表。

完成之後,就可以看到,再根目錄,出現了bower.json檔案嚕。

image

將新的套件加入到bower.json裡面

另外,我想應該不會有人想要每次加入一個新的套件,就init吧…所以官網有提供以下指令,可以讓大家再加入新套件的時候,順便寫到bower.json檔案裡面去。

image

這邊,我們就加入bootstrap~。

image

完成之後,我們就可以看到,相依了bootstrap了喔!~

image

還原

最後就是要進行還原,我們這邊開了一個新的WebApplication專案;接下來,我們把bower.json拷貝過來。

image

然後輸入bower install,就會立刻還原成功了喔!!!

image

有沒有很簡單勒??…當然,官方還有一些API,大家如果有興趣的話,可以再去看一看喔!!

參考資料

紀錄文 - Windows 10 Technical Preview

$
0
0

年年有大事,這幾天最大的大事,大概就是Windows 10已經可以給大家去做測試與使用這件事吧,所以小弟的年度喇賽紀錄文,就又出現了!!

而這次除了Windows 10的出現,大家最好奇的應該就是9勒!!?..

而各種陰謀論就在網路上流傳了…例如,

  • 因為win 8.1 已經是等於9了,所以就跳過9…
  • 因為MS最近希望用One代表全新產品..例如OneDrive、XBox One、但因為Windows 1.0已經被大老闆Bill用過了,所以只能去到那個點,變成10…
  • 但小弟最喜歡的是這篇阿…因為檢查版號的偷懶,win 95 只檢查到9… ( 那98怎麼辦?.. )

但不管怎樣,反正就是稱為10嚕…

另外,這篇基本上就是個紀錄文,讓小弟未來可以回顧一下歷史上的今天,並不會談論有怎樣的新功能 ( 可能會談一點點啦… ),畢竟無論新功能或是一些細節,很多前輩都po過了,小弟就不多說嚕…

那有興趣下載的朋友,可以到這個網址去下載

基本上,小弟是把Windows 10 安裝到 Macbook的VM上( 使用 Parallels 10 ),有興趣的朋友可以參考這篇

安裝的過程中,就如同以前Win 8一樣,基本上不太可能會遇到甚麼問題;然後從Win 8開始,就可以綁定Microsoft Account,而這次我們也可以繼續使用Microsoft Account來登入~~

螢幕快照 2014-10-04 下午12.54.37

隨便就可以登入是非常可怕的事情,所以這邊會需要驗證,像小弟可能就使用手機簡訊來驗證,所以這邊要先輸入手機的最後四碼,然後他就會發簡訊來了~~

螢幕快照 2014-10-04 下午1.06.12

輸入簡訊上的號碼,就可以繼續,現在簡訊傳送還滿快的~

螢幕快照 2014-10-04 下午1.06.45

接下來,我們可以選擇要重新設定這個PC,或是用之前的設定;我覺得這個做得不錯,現在重灌電腦也越來越簡單了~

螢幕快照 2014-10-04 下午1.07.20

進來後,一眼望去的是新版的藍色畫面~~

螢幕快照 2014-10-04 下午1.10.48

然後下一秒,就瞬間變成Win 8.1的黃色了… ( 因為它會抓你之前電腦的設定…但我這邊想用藍色阿XDD );另外,大家期待的開始列回來了… ( 換小弟不習慣了..QQ ),而且開始列也整合了動態磚,一開始以為會很突兀,但實際上看了一下,覺得整合得還不錯~~也很方便使用。

螢幕快照 2014-10-04 下午1.11.24

到這邊,小弟又換回藍色桌布了XDD,其實如果可以的話,建議大家點一下桌面的使用說明,就可以輕鬆看到這次的Win 10有提供怎樣的新功能喔。

螢幕快照 2014-10-04 下午1.15.17

而在說明文件裡面,有一個小弟一直試驗不出來的功能,就是將開始功能表切回原本的Win 8的Style;後來決定直接進入控制台去做設定…設定方法如下;只要去Taskbar and Start Menu Properties裡面把"Use the Start menu instead the Start screen"取消勾選就可以了… ( 但小心,要重登電腦喔… )

螢幕快照 2014-10-04 下午1.35.13

完成,重新登入之後,就可以看到之前被大家砲轟,但小弟覺得滿好用的Win 8開始列XDD

螢幕快照 2014-10-04 下午1.33.43

當然,其他還有一些功能,例如類似Mac、Linux的Task View,可以幫我們Group工作項目等等新功能,大家有機會都可以玩玩看喔。

那喇賽文就先到這邊嚕~~

Visual Studio - 建置的時候自動產生NuGet Package

$
0
0

最近因為在寫一些Framwork給公司使用,雖然透過DLL直接給大家用也很方便,但畢竟這個時代,已經是NuGet的時代了,所以理想的情況下,還是放在NuGet上,比較方便 ( 當然,給公司用的Framework是自行架立的NuGet私服… )

而建立NuGet Package的過程中,我們可以透過NuGet的指令,或是NuGet Package Exploer,但NuGet指令要準備一堆東西…而NuGet Package Exploer則會遇到相依信套件要自己塞的窘境…而最最最理想的就是透過MSBuild的過程中,自動產生NuGet Package;這樣才符合懶人Sky的形象~~

所以去網路上找了一下,有些人有寫了一些套件,有些人有準備了一些專案,但還是看到這篇最符合小弟…( 原文連結在底下… ),所以就在這邊敘述一下過程。

首先,必須先啟用NuGet套件還原,是的,大家沒看錯,就是套件還原;這邊會使用套件還原的原因是因為,我們透過套件還原這個功能,可以幫我們把參數都給設定好,所以幾乎都不用做甚麼事情了… ( 懶人指數 + 1 )。

image

而套件還原功能開啟之後,還必須先隨便的使用NuGet下載任一套件,並且編輯,小弟這邊下載的是Json.Net。

為什麼要隨便下載一個套件勒!?,原因很簡單,因為你隨便下載一個套件之後,並且重Build,他才會自動的在專案檔下加入必要的參數。

加入的項目如下,基本上裡面的參數都是和套件還原有關的。

image

如下圖,我們可以看到,預設情況下,幫我們增加了NuGet的相關參數。

image

而實際上,到上面為止,都是處於套件還原的功能,所以我們要在專案檔這邊,加入BuildPackage的標籤,並且改為true;沒錯,就是這樣而已,這樣就可以了!!

image

這邊是原始的專案xml,有興趣的大家可以自由貼上。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
    <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
    <ProjectGuid>{42ED14CC-0FAD-452C-966B-B484FE6BEDC2}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ClassLibrary2</RootNamespace>
    <AssemblyName>ClassLibrary2</AssemblyName>
    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
    <RestorePackages>true</RestorePackages>
    <BuildPackage>true</BuildPackage>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>此專案參照此電腦中缺少的  NuGet 套件。啟用「NuGet 套件還原」
      以便下載。如需詳細資訊,請參閱 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的檔案為 {0}。</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
  </Target>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

當加入那行之後,我們重新Build後,就可以在bin底下的debug看到nupkg的檔案產生了!!其中symbols是提供偵錯用途的,裡面包含了source喔~

image

第一步驟就到這邊,就是那麼簡單~~

參考資料

Visual Studio - 使用Nuspec來自動產生NuGet Package

$
0
0

前一篇,我們使用MSBuild來達到Build的時候,自動產生NuGet Package,而當我們使用NuGet Package Explorer打開來看的時候,我們會發現Package metadata的資料也順便的幫我們填上了。

image

為什麼NuGet Package會知道填甚麼值呢?,那是因為它會自動抓AssemblyInfo.cs檔案,如下圖。

image

其中的對應表如下圖,我們可以改以下的對應表來產生不同內容的Package metadata,但要特別注意,AssemblyCulture必須保持為空值,不然會NuGet Package的產生,會有問題。

image

但實際上,AssemblyInfo還是不能涵蓋所有的Package metadata,更理想的狀況還是透過nuspec這個檔案來定義Package metadata;但如果自己要Key nuspec這個檔案也太辛苦了,所以我們可以從nupkg這個檔案,來解壓縮,找到nuspec。

( nupkg其實就是一個zip檔案,大家可以透過7-zip工具,或是直接把nupkg這個副檔名改成zip,就可以順利解壓縮了… )

image

之後,我們只需要把nuspec拷貝到專案的目錄底下去就可以了,但要特別注意,nuspec的檔案名稱,必須和專案的名稱相同喔!!

image

完成之後,重build一下,我們就可以發現,這次完全使用nuspec的內容了。

image

最後,要特別注意,因為我們希望建置NuGet Package的時候,他自動去抓取packages.config這個檔案,來解析相依的問題,所以別忘記把nuspec裡面的相依給移除掉喔。

image

也就是這行裡面的內容。

<dependencies>
  <dependency id="Newtonsoft.Json" version="6.0.6" />
</dependencies>

到這邊,就完成嚕!!~

參考資料

Visual Studio - 自動產生NuGet Package並移除舊版Package

$
0
0

延續前一篇,這篇要談的是一個小小的不方便與問題,畢竟人類的懶惰是沒有極限的。

如果大家有測是下來,可能就會發現如下圖的問題,是的,產生了非常多的nupkg檔案…畢竟每次增加一個版本,就會多兩個nupkg檔案如下圖;當然如果一開始少少的可能還好,但越來越多的時候,就會感覺很髒亂…,所以這篇,我們就來看看如何建立的過程中,順便移除舊版的Package。

image

那要怎麼做呢??,其實每次建立的時候,都是透過NuGet.targets來觸發動作,所以我們要增加一些小東西到NuGet.targets裡面去。

image

首先,我們要先在前面填入以下的Code,這邊我們定義了OutputPackages的內容,是nupkg的路徑。

<ItemGroup>
    <OutputPackages Include="$(TargetDir)*.nupkg" />
</ItemGroup>  

將此Code放到下圖的位置。

image

接下來,我們要定義一個CleanDependsOn的標籤,當條件成立的時候,就會執行此標籤裡面的內容。

<CleanDependsOn Condition="$(BuildPackage) == 'true'">
  $(CleanDependsOn);
  CleanPackages;
</CleanDependsOn>

我們要把此標籤放到底下的位置。

image

最後,這個內容到底要做甚麼事情哩,就是最後面這個標籤的內容了,也就是Delete Files,要刪除的檔案,就是我們一開始定義的路徑。

<Target Name="CleanPackages">
  <Delete Files="@(OutputPackages)"></Delete>
</Target>

我們把此標籤放到以下的位置。

image

完成之後,我們要使用重建的動作,如果只用建置,是沒辦法觸發的。

image

重建之後,我們就可以發現,原本的nupkg檔案全部都被砍掉了,只留下最新版喔!!

image

最後的最後,附上完整的NuGet.targets xml給大家參考~

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <OutputPackages Include="$(TargetDir)*.nupkg" />
  </ItemGroup>  
  <PropertyGroup>
        <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>

        <!-- Enable the restore command to run before builds -->
        <RestorePackages Condition="'$(RestorePackages)' == ''">false</RestorePackages>

        <!-- Property that enables building a package from a project -->
        <BuildPackage Condition="'$(BuildPackage)' == ''">false</BuildPackage>

        <!-- Determines if package restore consent is required to restore packages -->
        <RequireRestoreConsent Condition="'$(RequireRestoreConsent)' != 'false'">true</RequireRestoreConsent>

        <!-- Download NuGet.exe if it does not already exist -->
        <DownloadNuGetExe Condition="'$(DownloadNuGetExe)' == ''">false</DownloadNuGetExe>
    </PropertyGroup>

    <ItemGroup Condition="'$(PackageSources)' == ''">
        <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
        <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
        <!--
            <PackageSource Include="https://www.nuget.org/api/v2/" />
            <PackageSource Include="https://my-nuget-source/nuget/" />
        -->
    </ItemGroup>

    <PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
        <!-- Windows specific commands -->
        <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    </PropertyGroup>

    <PropertyGroup Condition="'$(OS)' != 'Windows_NT'">
        <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
        <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
    </PropertyGroup>

    <PropertyGroup>
        <PackagesProjectConfig Condition="'$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace('', '_')).config</PackagesProjectConfig>
        <PackagesProjectConfig Condition="'$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
    </PropertyGroup>

    <PropertyGroup>
      <PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
      <PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
    </PropertyGroup>
    
    <PropertyGroup>
        <!-- NuGet command -->
        <NuGetExePath Condition="'$(NuGetExePath)' == ''">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
        <PackageSources Condition=" $(PackageSources) == ''">@(PackageSource)</PackageSources>

        <NuGetCommand Condition="'$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
        <NuGetCommand Condition="'$(OS)' != 'Windows_NT'">mono --runtime=v4.0.30319 "$(NuGetExePath)"</NuGetCommand>

        <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>

        <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true'">-RequireConsent</RequireConsentSwitch>
        <NonInteractiveSwitch Condition="'$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT'">-NonInteractive</NonInteractiveSwitch>

        <PaddedSolutionDir Condition="'$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
        <PaddedSolutionDir Condition="'$(OS)' != 'Windows_NT'">"$(SolutionDir)"</PaddedSolutionDir>

        <!-- Commands -->
        <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
        <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>

        <!-- We need to ensure packages are restored prior to assembly resolve -->
        <BuildDependsOn Condition="$(RestorePackages) == 'true'">
            RestorePackages;
            $(BuildDependsOn);
        </BuildDependsOn>

        <!-- Make the build depend on restore packages -->
        <BuildDependsOn Condition="$(BuildPackage) == 'true'">
            $(BuildDependsOn);
            BuildPackage;
        </BuildDependsOn>
      
        <CleanDependsOn Condition="$(BuildPackage) == 'true'">
          $(CleanDependsOn);
          CleanPackages;
        </CleanDependsOn>
    </PropertyGroup>

    <Target Name="CheckPrerequisites">
        <!-- Raise an error if we're unable to locate nuget.exe  -->
        <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
        <!--
        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
        This effectively acts as a lock that makes sure that the download operation will only happen once and all
        parallel builds will have to wait for it to complete.
        -->
        <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
    </Target>

    <Target Name="_DownloadNuGet">
        <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition="'$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
    </Target>

    <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">        
        <Exec Command="$(RestoreCommand)"
              Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />

        <Exec Command="$(RestoreCommand)"
              LogStandardErrorAsError="true"
              Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
    </Target>

    <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
        <Exec Command="$(BuildCommand)"
              Condition="'$(OS)' != 'Windows_NT'" />

        <Exec Command="$(BuildCommand)"
              LogStandardErrorAsError="true"
              Condition="'$(OS)' == 'Windows_NT'" />
    </Target>

    <Target Name="CleanPackages">
      <Delete Files="@(OutputPackages)"></Delete>
    </Target>

    <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
        <ParameterGroup>
            <OutputFilename ParameterType="System.String" Required="true" />
        </ParameterGroup>
        <Task>
            <Reference Include="System.Core" />
            <Using Namespace="System" />
            <Using Namespace="System.IO" />
            <Using Namespace="System.Net" />
            <Using Namespace="Microsoft.Build.Framework" />
            <Using Namespace="Microsoft.Build.Utilities" />
            <Code Type="Fragment" Language="cs">
                <![CDATA[
                try {
                    OutputFilename = Path.GetFullPath(OutputFilename);

                    Log.LogMessage("Downloading latest version of NuGet.exe...");
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);

                    return true;
                }
                catch (Exception ex) {
                    Log.LogErrorFromException(ex);
                    return false;
                }
            ]]>
            </Code>
        </Task>
    </UsingTask>
</Project>

基本上,到這邊,就完成嚕!!

參考資料

JavaScript - 使用gulp來建置JS

$
0
0

這篇的來源,是從這裡來的,後來看到一半,發現已經有JS神人翻成中文了..Orz..但已經弄到一半,就還是留下來記錄一下…有興趣的朋友,可以直接去看中文版的,寫的很詳細也很棒喔!!

最近因為某些因素,也開始看看JS的建置方案,至於為什麼要建置,有很多的原因,舉例來說,我們希望把JS給min化,又或許是把多個JS給綑綁成一個,又或許是為了要測試;總之,近代的JS已經沒有以前那樣的單純,所以也需要個建置流程,來處理這些事情~

而除了今天要聊的gulp外,其餘還有grunt等方案,但小弟選的是gulp,其實也沒為什麼,就覺得他的設定過程滿好的XDDD,也容易理解,就選擇了gulp~

開始前,我們必須先透過npm進行安裝,不知道甚麼是npm的朋友,可以看一下這篇

裝完npm後,我們就可以透過npm install gulp -g進行第一次的全域安裝。

image

接下來,我們就進入我們要的專案底下,針對此專案,再安裝一次gulp。

image

完成之後,我們要持續的透過npm進行gulp的套件安裝;這邊有非常多的套件,因為神人那篇已經寫的很詳細了,小弟這邊就不多加敘述了。

  • gulp-uglify - 將JS醜化…( 就類似程式碼混淆器的功能 )
  • gulp-rename - 重新命名JS檔案
  • gulp-clean - 清除目標路徑
  • gulp-concat - 合併多個JS檔案
  • gulp-notify - 通知,完成後通知功能

image

接下來,我們要在專案下,建立一個gulpfile.js的檔案。

image

檔案的內容大致如下,簡單的說,前面是針對套件的載入,接下來使用pipe來讓套件一個一個的循序漸進的工作,而gulp.dest表示目標的路徑,這邊指的是當合併成main.js或是使用uglify後,要將js檔案放到哪個路徑…最後我們再使用gulp.start來啟動Task。

以下面的案例來說,我們先使用src讀取所有的js位置,並且透過concat合併成main.js並且輸出到assets/js的路徑下,接下來,我們將此檔案新建立一個.min的檔案並且混淆裡面內容後輸出到dist/assets/js底下,完成後,使用Scripts task complete來通知我們。

var gulp = require('gulp'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    notify = require('gulp-notify');

gulp.task('scripts', function () {
    return gulp.src('src/scripts/**/*.js')
      .pipe(concat('main.js'))
      .pipe(gulp.dest('dist/assets/js'))
      .pipe(rename({ suffix: '.min' }))
      .pipe(uglify())
      .pipe(gulp.dest('dist/assets/js'))
      .pipe(notify({ message: 'Scripts task complete' }));
});

gulp.task('clean', function () {
    return gulp.src(['dist/assets/css', 'dist/assets/js', 'dist/assets/img'], { read: false })
      .pipe(clean());
});

// 預設任務
gulp.task('default', ['clean'], function () {
    gulp.start('scripts');
});

完成之後,我們只要進入指令模式,打入gulp,就可以呼叫建置。

image

基本上就先到這邊,其實原文的部分,還有包含CSS、瀏覽器自動更新等功能,如果迫不急待的朋友們,可以看看參考資料,那邊寫的非常詳細喔!~

未來小弟這篇,會再慢慢的補充上去。

另外,目前Visual Studio 2013已經有提供IDE的套件,至於未來的Visual Studio 2015,則會內建,未來也會持續更新。

參考資料


Visual Studio - 使用NuGet Packager來打包NuGet Package

$
0
0

前面幾篇都談到使用原生的Build來建立Package,但有些情況下,NuGet Package裡面包含的東西,卻不一定是Build出來的dll…...,所以這邊再提供一個方法,來打包NuGet Package;那就是NuGet Packager。

NuGet Packager

此功能必須先從Visual Studio的擴充功能和更新的地方進行下載。

image

安裝完成後,就可以從新增專案的地方,新增一個NuGet Packager專案。

image

這種做法和之前的作法,最大的差異在於,他是以專案為基礎。

他的目錄結構如下,正常情況下,如果要放置dll的話,只需要把dll放置到lib的目錄底下;而如果要放一些.cs檔案之類的,就可以放到content底下。

image

此工具也提供了自動佈署的功能;當我們使用Release Build的時候,他就會自動的將打包好的東西佈署到NuGet Server;而第一次使用的時候,必須手動的加上NuGet Server API Key,未來才能佈署成功。

image

最後,如果要更改NuGet Server的位置,可以修改NuGet.config這個檔案來定義新的NuGet Server位置。

image

基本上就這樣,其餘的功能,都等同於NuGet Packae封裝的原則;雖然我們也可以用下指令的方式來封裝,但實務上,要管的東西還是太多了,所以提供一個比較簡潔的做法給大家參考。

參考資料

Azure - 在Web Site上進行線上編輯

$
0
0

好久沒寫文章了,今天剛好有朋友問到小弟我這個問題,就隨手紀錄一下。

如果大家還記得,在以前的Portal上,我們可以直接透過Monaco來對Web Site上的檔案進行線上編輯,但New Portal勒!!!?怎麼看不到這個選項了!!?

原來是因為在New Portal上,預設是不會安裝這個Extensions的,所以我們要自己手動安裝Extensions。

image

然後選擇裝Visual Studio Online。

image

裝完之後,我們直接選擇瀏覽。

image

可愛的Monaco就回來嚕!!!~

image

大體上這樣,給有需要的人吧~~

2015 軟體研發高峰會

$
0
0

從Visual Studio 2005開始,這套軟體就活在小弟的電腦裡面,雖然當時還不是很會用…(抖抖),但因為學校上課的關係,就讓他一直存活者。

而到了Visual Studio 2010,Visual Studio整個煥然一新,更是讓人覺得Visual Studio進入了另外了一個里程碑!!而這個時期,也正是小弟第一次來台北參加恩師Ruddy老師與百敬老師的研討會 ( 當時一整個覺得百敬老師外表像流氓一樣..但內心實際上根本就是個活佛…... ),而直到現在,Visual Studio也準備進入2015了,歷經了10年的時間,看著Visual Studio的版號,就等同看著自己的成長阿…

阿,廢話那麼多,那這場軟體高峰會為什麼會吸引小弟去哩??又為何講古講了一堆Visual Studio勒!?因為這場Microsoft請到了 全球資深副總裁 潘正磊女士 Julia,大家會想說他是誰!?他就是鼎鼎大名的Visual Studio Team的超高級長官!! 有多高級哩??..連 C#之父Anders Hejlsberg都是他底下的人…( 現在Scrum的創辦人之一Ken Schwaber,應該也是在他底下,只是這次沒有證實… ) 所以,大家這樣應該就可以猜到,他底下負責的產品,就是Visual Studio、.Net、TFS、Visual Studio Online、TypeScript!!

既然那麼重量級的人物出現,小弟我又怎麼可能不去晃晃哩!!?

這次是舉辦在高級的寒舍艾麗裡面,時間還沒到,其實就已經有很多人開始報到了~~

IMG_2871

這次的會場其實非常漂亮=v=,我們也可以看到DX Team的團隊已經在準備了。

IMG_2872

這次當然還是由我們台灣區偉大的Dann哥來負責主持與總指揮啦XDD,快要開始前,Dann哥已經躍躍欲試了XDD。

IMG_2873

正式開始!!,當然就是由Dann哥主持啦!!

IMG_2874

接下來,有那麼大的人物來台灣,當然就是由台灣區的微軟總經理 紹光華開場嚕。

IMG_2875

總經理首先針對微軟的政策,特別述說了Mobile-first與Cloud-first,所以可以看出,行動與雲端依然是微軟主要的策略。

IMG_2876

接下來,提到了MS的開宗始祖Bill Gates,在1975年說的那句名言,而40年後的今天,現任的微軟執行長Satya Nadella,也依據雲,提出了相同的論點。

IMG_2877

接下來的重頭戲,就是Julia上台了!!~基本上他是中國人,所以全程是用中文來講,完全不用擔心聽不懂,在開頭的自我介紹中,Julia說他從Visual Studio第一版,就開始參與,而且是裡面的開發工程師,所以可以看出,她也有深厚的技術實力;也可以看到微軟的制度,就算是高層的總裁,技術實力也依樣的深厚。

IMG_2880

Julia一開始就提到,微軟未來的三大方向,就是更開發,更創新和更加的敏捷,而對於她來說每一個企業,都是一個軟件公司,因為每家企業,未來都會持續的開發屬於自己的系統,也因此未來軟體的開發會極為重要;另外因為雲端和手持裝置的崛起,流量可能會是以前的百倍,而透過Mobile與Cloud來收集資料與分析,更是未來的趨勢。

IMG_2881

更開放的部分,微軟用更開放的態度,和其他公司合作,例如在Azure上面放上Oracle的VM,甚至是最近的大新聞,Google的AngularJS 2.0 將使用TypeScript、又或是在iOS裝置上提供Office等等,這些都是以前微軟沒有做到的事情;而如今,連.Net都Open Source了!!

IMG_2882

更創新的部分,則提供更多的方案,來讓不同的使用者滿足,例如Visual Studio 2015就開始內建使用JavaScript的Cordova來建立Mobile,但可能還是有很多人使用C#阿,所以也提供了以C#為基底的Xamarin;當然,使用C++的朋友們,也有提供以C++為主的跨平台方案~ ( 這次的Office轉移,就是使用C++的跨平台方案 )。

其次,雲端的開發上,提供了新版的.Net Core,讓Web Site的開發更小;而透過雲端的應用Load Test也更方便測試。

處此之外,在生產力方面,也持續的讓C++ 速度的提升等等,效能的提升,讓大家能更加的感受到改進。

最終,Julia提出了她的願景,就是希望幫助每一個開發人員,無論你是哪個平台,哪個語言。

IMG_2883

接下來談到了Visual Studio的開發歷程,改成每2~4個月更新一次;那這個原因當然是因為現在Visual Studio 開發Team已經完全啟用敏捷,所以更新與回饋的速度就更快了,這也是因應現在的潮流;所以我們可以看到Visual Studio 2012和Visual Studio 2013的推出間隔其實是很短的,而過程中,也不斷的發佈新的更新包。

IMG_2884

接下來提到,以前的Visual Studio開發,參與人數高達4700人。

IMG_2885

當然,也是跨全球的一個研發團隊。

IMG_2886

接下來,就提到,以前Visual Studio的開發就是使用瀑布流的方式 ( 所以台灣其實沒有落後很多,基本上台灣遇到的問題,微軟也遇到過了XDDD )。

他們的週期大概是兩年到三年一輪,所以一開始會花很多的時間,決定未來兩年後的趨勢。

IMG_2887

而這個過程中,測試花的時間,其實會遠比寫Code的好幾倍,而早期會花費很多的測試時間和測試人員;Julia有提到,那是因為早期的時候,都是要透過店鋪購買盒裝的軟體,而如果裡面出現嚴重的bug,那回收回來的成本是很可觀的;而現在則可以透過網際網路快速的更新,所以著重的反而是能快速反應使用者的需求… ( 題外話..其實家用電玩也是一樣,記得之前看過FF13的報導,日本Square Enix 之前也是花費了大量的測試人員進行測試與封閉型的開發,現在也逐漸轉變成敏捷的方式了。 )

IMG_2888

而早期的專案結構,會有PM、Development和Testing,如果有讀過微軟出的測試一書的朋友,就會對於底下的這張圖很熟悉~~,當然,現在就不是這樣的結構了。

IMG_2890

那現在變成怎樣子勒,現在約18的月發行一次大版本,例如 xx 2015 xx 2017之類的,而每六個月會評估一次,目前的方向和方案是否與市場狀況相同,團隊則以3週為一個Sprint,而且人數也沒以前那麼多了,目前不到2000人。

IMG_2891

而現在的內部開發人員,會非常的重視白箱測試,也就是會撰寫Unit Test ( 那黑箱測試,不會就落到我這白老鼠的身上了吧= =+.. 總之會場沒特別提到黑箱怎樣做了… ),並且多聽使用者的反饋,而不是以前的蠻幹。

另外,工程師也開始進行數據收集與分析的工作 ( 這點台灣倒是還沒有開始… ),透過數據收集與分析,來決定未來的方向;所以也不是以前,完全靠有經驗的大師們指揮,就算是大師們,也必須透過數據。

另外,工程師也要開始直接與客戶交流 ( 這點台灣最難辦到吧XDD 我們都是宅宅阿~~抖抖 ) 透過與客戶的交流,來更了解客戶的需求。

IMG_2892

組織結構也改成如下圖了,移除了Testing,但並不代表不用測試,而是由開發人員自行來測試,也就是說,整合了開發人員與測試人員;整合的過程中也滿有意思的,Julia有提到,先讓兩邊人馬互相交換做事情,而過程中,也發現到,原來兩邊人馬有非常多的重工。

但不管怎樣,目前還是依據功能來區分;並且每個Team都有非常高的自主性管理。

IMG_2893

Team Room 的結構,不再是以前一個一個獨立的房間,而是把大家聚在一起,更加的Open,從一開始只有一棟的試驗,現在已經有四棟的大樓,都是採用此模式了。 ( 其實小弟的Team目前也是用此模式,溝通更快了,間隙更小了 )

IMG_2894

接下來,提到Sprint,基本上是三周一次,而三周內,還有一周會進行佈署,所以時程其實是非常緊迫的;而Julia也有提到,初期改成Scrum的時候,內部也是有很多人反對,例如…我是寫編譯器核心的,我兩周根本沒辦法Demo!!但後來實際run後,的確還是可行的,畢竟不可能兩周完全沒做事情吧,有做多少東西,就Demo多少東西~~

IMG_2895

最後,再重新回顧的時候,有提到Visual Studio 2015 CTP的Codava 第一代的安裝包,就是因為沒有WIN 7的版本,所以一堆Win 7的使用者,都發生了錯誤;其次,當進行Codava安裝的時候,很多都要透過第三方的下載的中心,進行下載,但有時,第三方的下載中心可能會出問題,或是擅自的更改位置,這些都會讓安裝過程遇到問題,但這些都是和功能無關,MS還是會想辦法解決,這就是注重需求與體驗,也就是未來微軟的方向。 ( 從這邊也可以看到,現在的整合,真的是難上加難阿… )

IMG_2900

另外,有提到一件事情,是別的國家問的問題,你們微軟是跑真正的sprint嗎?

Julia也解釋說,如果是真正的Sprint,Bug單是不會大起大落的,因為真正的Sprint,在每次交付的時候,都會有許多的bug單回饋回來;而如果是假的Sprint,那會到最後的時候,才會看到大量的Bug單提交…

IMG_2902

所以~Microsoft是真的Srpint ( 笑 )

IMG_2903

最後,現場留了一些時間來Q&A,而Q&A的問題如雪片般的飛來 ( 可見大家還是非常想知道大公司內部是怎樣運作的… )

以下是Q&A的內容,當然,內容是小弟憑印象Key的~

Q : 短期的開發是否認定客戶為白老鼠
A : 我們希望客戶可以參與到,並且確認的確是客戶所需要的,而事實證明,客戶也很樂意的反饋,並且告訴我們,這東西做的是對還是不對;最終,我們會修正成客戶真正想要的。

Q : 可否敘述清楚,關於3、6、18這些數字。
A : 以去年年初 ( 一、二月為案例 ) ,我們決定要制定跨平台開發,過程中,我們不新增人,而是調度人員,透過調度人員,讓大家能做到不同的事情;六個月後出版,再來看看,做出來的東西,是否和現在的市場符合;過程則使用為期3周一次的進入Sprint 來開始開發;而在進行Codova的部分,我們也發現,原本的核心應該可以更好,所以抽了一部份的人,去改Codova核心,這也是回饋Open Source的一個方法。

Q : 可否敘述文件是怎樣寫的。
A : 我們的文檔多半是Word寫的,我們沒有使用沉重的工具,因為每天都在改..所以不需要沈重的文件,其實Code就是最好的文件了;但有些時候,我們會希望透過Word,來寫一些當初的想法或是當初比較特殊的思維;但不管怎樣,這是由每個Team自行決定;最後,交流才是最重要的,只要Code清晰的表達,文件只要能共享就可以了。

Q : 人員流失(離職)怎麼辦勒??
A : 我們會定期Code Review的機制來解決這個問題。 ( 看來未來有人問到小弟這個問題,小弟有一個極好的案例可以拿來解釋了~~ )

IMG_2905

過程中,其實大家都聽得很認真也很High,這邊也謝謝Julia女士的經驗分享,也謝謝她帶領的團隊,能提供一個那麼好用的ide工具。

IMG_2906

接著,就是由Dann哥所率領的DX Demo Team,來進行VS 2015的功能Demo。

IMG_2907

他們以一個企業叫車的案例,來串所有的Demo內容,所以我們可以看到跨平台開發還有新的ASP.NET 5。

IMG_2909

比較好玩的梗,雙Scott都變成叫車司機XDD,希望哪一天我可以搭到這兩位的車 ( 抖抖 ),另外,果然還是Scott Gu第一名阿XDDD。

IMG_2911

另外一個主題是當紅的物聯網,這邊拿電梯監控和倫敦地鐵為案例。

IMG_2916

其實倫敦地鐵去年TechDay就已經出現過了..QQ..,但也可以看出,其實微軟這方面,很早就已經開始準備與琢磨。

IMG_2917

比較有意思的是這個架構圖,透過Azure服務來達到IoT ( 未來有機會,小弟來實作一下看看好了=V= )

IMG_2928

另外一個大主題就是大數據,這也是近期出現在FB當紅的題目 如果搭上了鐵達尼號,有機會生還嗎?

IMG_2929

這是依據那些搭上鐵達尼號的名單,來進行分析;後來,發現只要是女生,生還比率最高= =+。

最後,就是由小白來進行5min的壓力測試與佈署的Demo,雖然只有短短的五分鐘,但我知道,這個東西是要準備很久的,so,小白辛苦了XDD

總之,雖然只有半天的研討會,和短短的Demo,但聽到了官方開發Visual Studio的經驗,還是非常可貴的,而透過這半天的研討會,也讓小弟深深的開始省思,一個軟體的成功,並不是只是單單的開發出來就好,尤其現在這個快速改變的時代,整個思維也必須敏捷與改變才行。

總之,還是要謝謝 Visual Studio Team 與 Julia的帶領,讓我們能一直不斷的使用這麼好的開發軟體。

Azure上的Ubuntu與遠端桌面管理 VNC

$
0
0

大家應該都很清楚,透過Azure可以輕鬆的建立Windows的VM,但實際上,要建立Linux的VM也一樣容易,
而本篇,就由小弟來為大家介紹Ubuntu in Azure。

建立Ubuntu VM 與 登入

建立Linux VM的方式基本上與建立Windows沒兩樣,這邊小弟選擇了Linux裡面大家很常使用的Ubuntu來作為教學。

而這邊要特別注意,我們選擇的是Ubuntu 14.10的版本,而後面開啟遠端設定的版本,也是針對14.10,如果您使用了別的版本,那可能會照成設定失敗的狀況。

enter image description here

接下來,我們選擇 Ubuntu 14.10的版本,其餘的設定和建立一般的Windows Server差不多,一樣可以選擇地區或是資源群組。

enter image description here

完成之後,我們沒辦法和 Windows 一樣,直接下載 RDP 的檔案來連線,我們必須透過 SSH 來進行連線。
這邊要注意一下,我們要在後面加上 -l 的參數,並且帶入帳號,不然他預設會用我們目前終端機的帳號,第一次登入的時候,會要求將金鑰寫入,所以這邊一定要按下 yes ,然後就可以輸入帳號密碼了~

enter image description here

VNC 開始之前

基本上,到上面那邊的操作,就已經可以順利登入了,但小弟畢竟是懶惰的,如果遠端登入也有 UI 那不是更棒嗎!!而目前,Ubuntu已經預設提供了 VNC 外,也提供透過Microsoft Remote Desktop ( RDP )的方式來遠端登入,( 其實底層還是 VNC 只是中間透過xRDP 來進行命令的轉換 ),基本上透過 RDP 的速度會比較快,但是目前 Ubuntu 預設的桌面和 xRDP 有一些衝突,所以要另外安裝其他的桌面環境,而這邊為了初步體驗順利,我們就直接來看看,透過 VNC 的方式來進行遠端登入。

但開始前,小弟先提醒大家,目前小弟測試使用 VNC 登入,效果不是很好,滿慢的,所以有這個需求的朋友,可能要先有心理準備…

更新 Ubuntu 與 安裝 Ubuntu Desktop

裝完 Ubuntu 後,第一步當然就是更新…所以我們要下

sudo apt-get update

來更新。

enter image description here

接下來,我們就可以裝預設的桌面環境了。

sudo apt-get install ubuntu-desktop

這邊裝的過程有點久,大家可能要耐心等待一下。

enter image description here

安裝 x11vnc 與 設定

接下來,我們要安裝 x11vnc 來當作我們的 VNC Server
sudo apt-get install x11vnc

enter image description here

安裝完成之後,要設定遠端的登入密碼。
sudo x11vnc -storepasswd /etc/x11vnc.pass

最後,我們要到/etc/init/的目錄下,新增加x11vnc.conf這個檔案

小弟這邊直接使用 vi 來進行編輯。

sudo vi /etc/init/x11vnc.conf

內容如下,但要小心/usr/bin/x11vnc 等一長串,其實是”同一行”!!

start on login-session-start
script
/usr/bin/x11vnc -xkb -auth /var/run/lightdm/root/:0 -noxrecord -noxfixes -noxdamage -rfbauth /etc/x11vnc.pass -forever -bg -rfbport 5900 -o /var/log/x11vnc.log
end script

enter image description here

存擋完成之後,我們就可以重新開啟Ubuntu

sudo reboot

enter image description here

設定 Azure 端點

當然,最重要的,也別忘記設定 Azure 的端點。

enter image description here

連線

接下來,就可以透過 VNC 的軟體進行登入嚕!! ( 小弟這邊是直接使用 OSX 內建的 VNC 軟體 )
只要在 Safari 裡面輸入 VNC://網址,就可以進行登入

enter image description here

接下來輸入密碼

enter image description here

然後就可以成功進去了!!(這邊的登入密碼,就是建立 VM 時所 Key 的密碼,但有時候會因為網路的延遲,造成大小寫轉換失效,所以如果進不去,可以多試驗幾次)

enter image description here

總結

基本上,這樣就可以輕鬆的登入到 Ubuntu 的遠端畫面,但小弟建議,還是用終端機吧…真的快很多….

參考資料

在Ubuntu運行Docker

$
0
0

首先,在開始前,小弟一定要推薦一下這個網站和這個網站,這個兩個網站寫了很多,而且由淺入深的教學,而這篇文章,一開始會先練習這個網站的前篇教學,並且搭配此網站網站的說明,下一篇,則會使用 Microsoft 提供的 ASP.NET 5 Preview Docker Image 來完成 ASP.NET MVC 應用程式。

安裝 Docker

基本上,Ubuntu 已經有內建了 Docker,或是使用 apt-get 來安裝也是可以的,但是既然神人大大推薦用 curl 的方式取得,那我們這邊就使用 curl 來取得 Docker吧!!

curl -sSL https://get.docker.com/ubuntu/ | sudo sh

enter image description here

完成之後,我們就可以啟動 Docker了!!

sudo service docker start

enter image description here

Hello Docker

接下來,我們先採用另外一位神人大的教學,來簡單的輸出一下 Hello Docker.

sudo docker run ubuntu:12.04 echo ‘Hello Docker’

enter image description here

是的,就是這樣簡單,我們就可以看到Hello Docker!!,但是大家可能會想,啥?不就是只是輸出一個 Hello Docker 啊…這和虛擬化,容器技術有啥關係。

沒錯,別懷疑,這個 Hello Docker 其實是從虛擬化出來的 Ubuntu 12.04 版本 echo 出來的!!!

也就是說,那短短的幾秒鐘時間,Docker 就已經把虛擬的 OS 準備完成,並且執行,且輸出了!!

所以,上面那行指令的意思,就是說,我們要 Run 一個 ubuntu:12.04 版本,並且 run 完成之後,於 Sehll 執行 echo ‘Hello Docker’ . 而在執行的過程中,他就會自動地把 ubuntu 12.04 的 image 載下來,結果如下圖。

enter image description here

完成後,我們就可以透過以下指令,來看看目前這台機器有多少個 image,從下圖就可以看到 Ubuntu 已經安裝上去了。

sudo docker images

enter image description here

登入終端機

但是,我們不可能每次都把一整串的字串,串到 run 後面吧…我們需要可以登入,登入!!登入啊啊啊!!

當然,這也可以做到,我們可以下以下的指令,這個指令的意思就是,建立容器的時候,順便建立一個終端機( -t ),並且建立與容器標準輸入的互動進行連結 ( -i ),這樣你就可以在裡面下指令操作了~~

sudo docker run -t -i ubuntu:12.04

但是,請注意,雖然我們從終端機離開,並不會關掉容器,但如果我們把容器 Kill 或是 移除,那你裡面做的所有事情都會不見…如果你在裡面做了些事情,而希望把裡面的東西存下來,就必須使用 commit 指令,其中7ce430e7c072是表示目前的容器ID ( 可以透過 docker ps 來查看目前執行的容器 ),而aspmvc/text:ver1 代表的是容器的名稱和Tag名稱。
(此指令要在容器外面下喔!)

sudo docker commit -m=’簽入描述’ -a=’簽入者’ 7ce430e7c072 aspmvc/test:ver1

重新登入容器

另外,如果你登出了,想要在登入進去那一個容器,我們可以先用

sudo docker ps -a 來查到所有目前執行的容器。

然後再用以下指令登入( 後面是id ),下面兩個的差異,一個是直接回到容器裡,另外一個則會開另外一個終端機,目前建議使用第二種方式。

sudo docker attach 665b4a1e17b6

sudo docker exec -i -t a66289aeefa6 bash

停止與刪除背景執行的容器

若有執行中的容器,想要停止,可以透過底下的指令來完成。

sudo docker ps -a

sudo docker stop 9162a162f840

停止後,就可以用 rm 指令來移除容器。 ( 或是直接用 rm -f 來強制停止)

sudo docker rm 9162a162f840

如果有太多容器,想要一次全部移除,可以下以下指令

sudo docker rm $(sudo docker ps -a)

enter image description here

基本上,初步就到這篇,下一篇我們會透過 Microsoft 提供的容器,來建立 ASP.NET MVC 應用程式。

參考資料

Viewing all 144 articles
Browse latest View live