2018年12月23日 星期日

時區問題(by browser)

這次的專案跨了兩個以上的時區
以哪一個國家做基準時間都不合適
解決之道就是.....在資料庫資料的create & modify 時間用System.DateTime.UtcNow取代System.DateTime.Now,
那怎麼在客戶端讓不同時區的人看到「應該」呈現的時間呢?
這時就要靠「Date.getTimezoneOffset」函數了
參考以下的機制
-----------------------------------------------
renderer: function (value, metaData, record, row, col, store, gridView) {
                                        //return Ext.util.Format.date(value, 'Y/m/d h:i:s A');
                                        if (value == null) return "";
                                        let adjDate = Ext.Date.add(new Date(value), Ext.Date.MINUTE, new Date().getTimezoneOffset() * -1);
                                        return Ext.util.Format.date(adjDate, 'd/m/Y h:i:s A');

                                    }
=============================================
 其中的「new Date().getTimezoneOffset()」在我國(台灣)顯示的是-480,也就是我這裡的時間減掉480分鐘就是UTC時間,所以要用-1乘上去加回來(這時候,ExtJs的Date函數就很好用了)
把UTC時間加上getTimezoneOffset就會得到瀏覽器的時區時間了

那瀏覽器的時區什麼時候決定的?實驗(用firefox)的結果是打開時決定的,所以你要執行這函數前一刻改系統時間是看不出效果的

 以上,一起加油吧


2018年11月16日 星期五

Extjs4 ,如何偵測是否點在pop up window 的外面

參考:
https://stackoverflow.com/questions/12424263/how-to-close-modal-window-extjs-when-clicking-on-mask
我個人是比較喜歡寫在"initComponent"之後的寫法
======================
     initComponent: function () {
        ...
         ...
        
        me.callParent(arguments);
        me.mon(Ext.getBody(), 'click', function(el, e){
            alert('click outside!!');
        }, me, { delegate: '.x-mask' });
    }
=====================
大家加油吧

2018年10月31日 星期三

從reporting service(SSRS)產生的pdf報表有空白頁,怎麼刪除啊?

最直覺的方式或許是直接在產生的pdf檔下手,
不過這樣可能會砍到不該砍的頁面
那就換個方式--從report generation下手,
賓果!!
把握一個大原則: (Body Width + Left margin + Right margin) <= (Page width)
這樣就不會出這個也癢,出那個也癢了
參考出處:
https://social.technet.microsoft.com/Forums/en-US/4eca11b3-f646-4245-a930-27a1e27302e1/ssrs-2005-extra-blank-page-problem-after-exporting-to-pdf?forum=sqlreportingservices
大家加油了!!

2018年9月29日 星期六

版本控制軟體 tortoiseSVN 在commit變更時,出現unable to create pristine install stream”如何是好?

在重灌系統,複製了專案及repository目錄,裝完了tortoiseSVN後,試著把異動的檔案做commit時
除了會先遭遇要在repository目錄的db資料夾中,要再次建立「txn-protorevs」及「transactions」資料夾外,還會遭遇「unable to create pristine install stream」,真的是一波三折
重灌就是這樣,好在tortoiseSVN有解了--用clean up就是了:
參考: http://www.cnblogs.com/kukudelaomao/p/7443167.html
三個clean up
clean up working copy status
Vacuum pristine copies
Include externals
都要打勾

P.S. "tortoise"與"turtle"都是龜,差別是「tortoise」是陸龜,而「turtle」是海龜

2018年7月25日 星期三

SQL server 2012/2014複本之發行與訂閱補充事項

這方面的細步很多人討論了,
本次施作參考這裡 : 快速逐步的實作SQL Server之主從複寫機制
 今天不講這些細節,主要是在作業中、後遇到的一兩個狀況:
1.如果是改了主機名稱:
在「新增訂閱」時卻出現找不到SQL server,出現以下訊息:
Replication Error: SQL Server replication requires the actual server name to make a connection to the server  (錯誤:18482:無法連線到伺服器'訂閱者',因'這台SQL'未定義為遠端伺服器!) 的訊息


很怪耶,明明SQL Server Management Studio連得到訂閱者啊,怎麼會出現這問題?
因為我們把主機改了,連帶的sql serve中的相關系統資料也要改才會正確,
怎麼改?
先用「SELECT * FROM sys.servers 」及「SELECT @@SERVERNAME」檢查訂閱者SQL server是不是出現舊的主機名稱
然後用以下的方式改到新的主機名稱
=========================
sp_dropserver '舊主機名稱';
GO
sp_addserver '新主機名稱', local;
GO
=========================
記得下完上述指令後重啟動SQL server的服務,再用「SELECT @@SERVERNAME 」「SELECT * FROM sys.servers」檢查值是否正確,
再回到新增訂閱精靈連看看,就應該可以了
上述相關資訊參考以下連結::
這裡  及 這裡

2.終於把訂閱者做好也同步好了,這次我是用「交易式發行集」,結果訂閱端會出現些現象
  A:沒有pk的table沒被同步過去,. .B.trigger物件沒被同步過去,合理的,因為真的只是要「交易」同步去訂閱者SQL server上,
 如果要把目前(發行者)DB中的trigger找出來呢?
請用以下指令:
======================================
SELECT
    sysobjects.name AS trigger_name
    --,USER_NAME(sysobjects.uid) AS trigger_owner
    --,s.name AS table_schema
    --,OBJECT_NAME(parent_obj) AS table_name
    --,OBJECTPROPERTY( id, 'ExecIsUpdateTrigger') AS isupdate
    --,OBJECTPROPERTY( id, 'ExecIsDeleteTrigger') AS isdelete
    --,OBJECTPROPERTY( id, 'ExecIsInsertTrigger') AS isinsert
    --,OBJECTPROPERTY( id, 'ExecIsAfterTrigger') AS isafter
    --,OBJECTPROPERTY( id, 'ExecIsInsteadOfTrigger') AS isinsteadof
    --,OBJECTPROPERTY(id, 'ExecIsTriggerDisabled') AS [disabled]
FROM sysobjects
/*
INNER JOIN sysusers
    ON sysobjects.uid = sysusers.uid
*/ 
INNER JOIN sys.tables t
    ON sysobjects.parent_obj = t.object_id

INNER JOIN sys.schemas s
    ON t.schema_id = s.schema_id
WHERE sysobjects.type = 'TR'
EXCEPT
SELECT OBJECT_NAME(parent_id) as Table_Name FROM sys.triggers
=====================================
上述的指令參考這裡的討論

------------這次的施作意外收獲真不少--------------

2018年6月12日 星期二

如何在mac book pro之下備份/還原 Raspberry pi的Micro SD card 磁碟映像

如果是用OSX windows下磁碟工具的做整個SD card備份還原的話
對不起,還是會失敗的
所以,還是老老實實地用command line mode去做吧

(註:以下「」之內的才是指令,別copy進去了)

先講備份(沒備份哪來的還原嘛)
1.先用 「diskutil list」 找出那片SD card所在的 device,
2.假設動作1的結果是在"/dev/disk4"的話,用「dd」指令(disk dump)來做備份
  「 sudo dd if=/dev/disk4 of=~/Desktop/raspberrypi.dmg」

就這樣給你征服了.....備份的問題

好,現在回頭來「覆水可收」--還原一下
老樣子,插好了SD卡後,用diskutil list找到sd card所在的device id
不過,要先把它unmount才能做格式化、dd動作:
1. 「diskutil unmountDisk /dev/disk4」
2 「sudo newfs_msdos -F 16 /dev/disk4」
要dd了,這時dd的來源目的對調就是了
3.「sudo dd if=~/Desktop/raspberrypi.dmg of=/dev/disk4」

這樣就等等等了

剛才講的那些,請參考這裡 ,會有更多參數可以試


什麼!?你想看dd的進度!?好吧
請打開osx 桌面中的「活動監視器」,找搜尋「dd」就可以知道它在努力地為你搬東搬西了







2018年5月23日 星期三

老生常談--file upload前的image preview

以前是做過了,可是沒抄錄下才,現在又再找一次,正真是「碼到用時方恨少」
===========================================
           ...
           ....
           ....
                {
                            xtype: 'filefield',
                            anchor: '100%',
                            //colspan: 3,
                            width: 298,
                            name: 'image',
                            readOnly:true,
                            listeners: {
                                change: {
                                    fn: me.onFilefieldChange,
                                    scope: me
                                }
                            }
                        }
......
....
....
    onFilefieldChange: function (filefield, value, eOpts) {
        var me = this;
        var file = filefield.fileInputEl.dom.files[0];
            var reader = new FileReader();
            reader.onload = function (e) {
                me.setPanelImg(e.target.result);
            }
            reader.readAsDataURL(file);
    },
    setPanelImg: function (imgUrl) {
      var me=this;
        var pnlContainImgPnl =me.down('#pnlContainImage');
        pnlContainImgPnl.removeAll();
        var pnl4Img = Ext.create('Ext.panel.Panel',
            {
                autoScroll: true,
                html: '<img src="'+imgUrl+'"/>',
            });
        pnlContainImgPnl.add(pnl4Img);
        pnlContainImgPnl.updateLayout();
    }
===========================================
就將啦

2018年5月21日 星期一

如何把参數帶進 Task之中

example:
======================
int i=0;
 for (;i<10;i++) {
               tasks.Add(Task.Run(() => {
                    Console.WriteLine("i="+i);
             }));
 }
 Task t = Task.WhenAll(tasks.ToArray());
 t.Wait();
==========================
上例,task的run是在t.Wait時才呼叫的
此時 i已經是10,而不是各別的0....10
要怎麼把i用參數的方式帶進task呢?
這時要把Task.Run....改一下,才可以帶参數
=========================
            int i = 0;
            for (; i<files.Count; i+=100) {
                tasks.Add(Task.Factory.StartNew((Object obj) =>{
                   var data = (dynamic)obj;
                   int i2 = (int)data.iX;
                  Console.WriteLine("i="+i2);
               }, new { iX = i}));//{可以串很多個参數,x=i,y=5,z=7.........)
            }
=========================
這樣外面的變數就可以傳入了
更詳細的介紹請參考這裡





2018年4月14日 星期六

parallels desktop之下windows 8.1修改partition (系統硬碟)工具 & windows8.1安全開機模式

我的windows 8.1原來是在bootcamp下執行的,後來因為要用xamarin開發,鮮用windows 開機,就直接用匯入的方式轉入parallels desktop的硬碟格式,這下問題來了,
原本在bootcamp下開機時mac os的系統硬碟還是會被標示佔用點空間,造成在parallels desktop設定中看到的空間使用量遠大於真正可以使用的系統硬碟空間的大小,
而且parallels desktop屢屢說可以釋放空間也釋放失敗,去parallels desktop的組態硬體設定硬碟大小也沒辦法縮小空間,
這時是要做硬碟空間調整的時候了.
1.首先要選對工具
下載「EaseUS Partition Master 」(我那時候是12.9)
用試用版就可以了
改了partition大小後及磁區的起始位址後,它會要你重開機,有時不成功,要兩三次才會調整完partition起始及大小
(AEO牌的就不太行了....)
2.改好了partition,用檔案總管及電腦管理中的硬碟管理比對硬碟調整後大小是否一致,總算省下了些空間,可以去parallels desktop的組態硬體設定硬碟了

一定要注意的地方:
在安裝EaseUS Partition Masterar時,會偷渡些東西要仔細看
像是yahoo的情蒐,就可以say no,但是avast antivirus free就要小心了
不小心裝了,就要他們的官網https://www.avast.com/zh-tw/uninstall-utility 去下載「avastclear」工具,否則無法移除
這工具還有個特點是一定要在安全模式下執行才行
而windows 8.1的安全模式請找「系統設定」程式中有個「開機」的頁籤,下面有個「安全開機」,打勾就可以了

(這就是安裝東西沒仔細看的結果,防毒軟體跟病毒有的比了)
這問題拖了好久才解決了.(畢竟工作還是最優先的嘛)

2018年4月3日 星期二

明明在ultraEditor中比對的長度是一樣的兩個文字檔,有些處理單位會認為是格式錯誤

明明在ultraEditor中比對的長度是一樣的兩個文字檔,有些處理單位上傳後會認為是格式錯誤
這時....儘信ultra editor不如無ultra editor,
原因不是出在文字行的內容,而是出在檔案格式
(只有在另存新檔時,才會看到「編碼」的差異)
如何從UTF-8轉成ANSI?
答案就是一個選項
===============================
System.IO.File.WriteAllLines(filePath, lines.ToArray(),Encoding.Default);
=====================================
這裡的default指的不是平台的locale編碼方式(big5......)
而是.....
取得作業系統目前 ANSI 字碼頁的編碼方式

2018年3月25日 星期日

讓extjs4使用你目前windows資源的一種方式--Cross-Origin Resource Sharing 的應用

在你的windows做一個http listener
========================================
                Thread xThread = new Thread(
                     delegate () {
                     HttpListener httpListener = new HttpListener();
                     httpListener.Prefixes.Add("http://localhost:2048/DoLocalJob/");
                     try {
                         httpListener.Start();
                     } catch (HttpListenerException hlex) {
                         Console.WriteLine(hlex);
                         return;
                     }
                     Console.WriteLine("Now ready to receive traces...");
                     while (true) {
                         var context = httpListener.GetContext(); // get te context
                         var data_text = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd();
                         Console.WriteLine("data_text is " + data_text);
                         var cleaned_data = System.Net.WebUtility.UrlDecode(data_text);
                         Console.WriteLine("clear data is " + cleaned_data);
                         Console.WriteLine("raw is " + context.Request.RawUrl);
                         byte[] buffer = Encoding.UTF8.GetBytes("OK");
                        HttpListenerResponse response = context.Response;
                        response.StatusCode = 200;
                        response.SendChunked = true;
  //如果沒有以下幾個header設定的話,Ext.Ajax.Request所收到的response都是空白的!!
                        response.ContentType = "application/json; charset=utf-8";
                        response.AppendHeader("Access-Control-Allow-Origin", "*");
                        response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                        response.AppendHeader("Access-Control-Allow-Headers", "Content-Type,x-prototype-version,x-requested-with");
                        response.ContentLength64 = buffer.Length;
                        Stream output = response.OutputStream;
                             if (context.Request.RawUrl.Contains("axn=MyAction")) {
                                 doLocalJobProcess();
                                 response.ContentLength64 = buffer.Length;
                                 output.Write(buffer, 0, buffer.Length);
                                 output.Flush();
                                 continue;
                             }
                             buffer= Encoding.ASCII.GetBytes("parameter error!!");
                             output.Write(buffer, 0, buffer.Length);
                             Console.WriteLine("send back " + cleaned_data);
                             output.Flush();
                             output.Close();
                         }
                     });
                xThread.Start();

========================================
local http server起來了,之後就是網頁的事了
=======================================
            Ext.Ajax.request({
                defaultHeaders: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json'
                },
                useDefaultXhrHeader: false,
                cors: true,
                url: 'http://localhost:2048/DoLocalJob/axn=MyAction',
                method: 'POST',
                params: {
                       xxx:yyyy
                },
                timeout: 10240,
                success: function (response) {
                    if (response.responseText == 'OK') {
                         ......
                         ....
                         return;
                    }
                      //....其他錯誤....
                    return;
                },
                failure: function (response) {
                       //....http listener 沒起來,或是剛才說的header沒設好也會跑來這段
                    return;
                }
            });
===============================================

2018年3月24日 星期六

for Macbook OSX ,外接式螢幕找不到你要的解析度?試看看 「option」鍵吧

有時明明外接式螢幕可以撐到1920x1080的解析度
可是OSX只能給你1280x720,
有一個shareware(不是免費的,10天試用期)叫做「SwitchResX」的工具,可以試看看
(URL:http://www.madrau.com/ )
但,別急,如果你沒用過option鍵的話,先試看看,不行再去買switchResX
詳細參考:
https://support.apple.com/kb/PH25175?locale=zh_TW
=======================================
...
...
當您按一下「縮放」時請同時按下 Option 鍵,以顯示其他解析度供第二部顯示器使用。然後,為第二個顯示器選擇一個縮放解析度選項。
....
....
=======================================


別像我再傻傻的拔拔接接了,很難看耶......



2018年3月21日 星期三

VideoFileWriter 在 WriteVideoFrame存放畫面時居然出現「System.ArgumentException!?」

本來想玩openCV做商品辨識能力的智慧型倉儲,不過公司比較想做錄影存證,沒差,都好玩啦
不過在存放webcam的畫面進入mp4時,出現了System.ArgumentException
===========================================
using Accord.Video.FFMPEG;
using Accord.Controls;
using Accord.Video;
using Accord.Video.DirectShow;
.....
....
...
VideoFileWriter fileWriter = new VideoFileWriter();
....
private void Video_NewFrame1(object sender, NewFrameEventArgs eventArgs) {
            video = (Bitmap)eventArgs.Frame.Clone();
            picShowImg.Image = (Bitmap)eventArgs.Frame.Clone();
            if (isRecording) fileWriter.WriteVideoFrame(video);
            
 }
.....
.....
....
void bgnSaveVideo(){
                int h = 1024;
                int w = 768;
                string fileName = "d:\\" + System.DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".mp4";
                fileWriter.Open(fileName, w, h, 24, VideoCodec.MPEG4, 50000000);
                fileWriter.WriteVideoFrame(video);    <------這時發生錯誤!!
}
============================================
查了很久,試了好幾次才知道原因:長寬不是自己高興多少就多少,而是要看當時frame的bitmap長寬多少,才能用WriteVideoFrame
=======以下是正確的寫法========
                 int h = video.Height;
                int w = video.Width;
                string fileName = "d:\\" + System.DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".mp4";
                fileWriter.Open(fileName, w, h, 24, VideoCodec.MPEG4, 50000000);
                fileWriter.WriteVideoFrame(video);    <------這時就過關了!!
=============================
...
...
os:應該沒人犯這樣的錯吧.網路上一直找不到相關的案例....

2018年2月12日 星期一

天啊.....localstorage 爆掉了!!

一口氣在browser 的localstorage 塞了四萬多筆資料
,在chrome遇到「Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of 'seq-22231' exceeded the quota」
在firefox 則遭遇到「 NS_ERROR_DOM_QUOTA_REACHED」這樣的錯誤
可是沒時間改資料來源的架構了,如何是好?

如果你做人成功,可以先請user用firefox的話,那就已經解決了,怎麼說?
請到firefox的網址列輸入「about:config」
找「storage.default_quota」這項,如圖

預設值是5210,不想試了,直接加個0免找了,
問題就解決了
如果你知道chrome有這樣設定怎麼設的話請跟我說一下,謝謝囉

2018年1月30日 星期二

for Extjs4 ,store + ajax proxy,如何在「load」事件中讀取records之外其他傳回來的json值

例, 某個store物件是長這樣的
===============================
  var store=bew Ext.data.JsonStore(
    ...
    ...
    proxy:{
      type:'ajax',
      url: .....
   }
);
  store.load({
      scope:this,
     callback:function(records,option,success){
            ...
            ...
         if(success){
                .....產生grid.....
        }
     }
  });
===============================
server side:
==================
傳回一個json,

  var jason={
      success=....,
      totalCount=....
      rows=......
      msg=...... <---如果有錯誤發生的話
 }
==================
如果是success還好,直接做grid產生的動作
可是人生不如意,十之三四五六七八九,多少會有success=false的時候
可是如果是failed的話,要怎麼接收ms的消息?明明callback 只有三個參數啊
有的人是說用這方式來接收server response的json物件....
=========================
callback: function(records, operation, success) {  

 var jsonStr = Ext.JSON.decode(operation.response.responseText);  

 alert(jsonStr.message); 

}

=======================
很不幸的,上述的程式碼是行不通的(上述的作法應該是3.x的吧?)
會出現 operation.response=null的現象

如何是好?真正的做法是:


=======================

 if (!success) {

            var jsonObj =store.proxy.reader.rawData; 

            Ext.Msg.alert('Server Failed!!', jsonObj.msg,Ext.emptyFn);                                    

           return; 

 }else{ 

   ....產生grid.....

 }

=======================

注意,store.proxy.reader.rawData」已經是json物件了,不是text,不要再自做聰明去用Ext.JSON.decode...了,否則會出現You're trying to decode an invalid JSON String: [object Object]」這樣的訊息,請小心
以上,大家加油了


參考來源