2013年7月1日月曜日

[Symfoware]遅延

Windows から Symfoware サーバに接続するにあたり、Symfoware クライアントとして、Symfoware .NET Data Provider を使っている。

サーバー側が複数あり、ほとんどが接続出来ない状態だと、接続出来るところが遅延する現象が発生した。

テストプロを作って調査したところ、接続待ちの処理があった場合、別スレッドで接続出来るところへ接続を試みると、待たされているようだ。マルチスレッドに対応していないのか?

試しにODBCで接続してみると、全く遅延せずに接続出来てしまった。

完全に SNDP の不具合だな。


[WPF]デザイナエラー


突然、Visual Studio の XAML のデザイナを開くと描画されなくて、下記エラーが出るようになった。

エラー 1 CLR 名前空間が定義されていません。'clr-namespace' URI が、アセンブリに含まれていない名前空間 'XXXXX' を参照しています。

なんか変えちゃったかな―。
プロジェクトのプロパティを見ると、プラットフォームが「Any CPU」から「x86」に変わっていて、選択項目に「Any CPU」が表示されない。
どうもこれが原因ぽい。

・ソリューションのプロパティを開き、構成プロパティ選択->構成マネージャを開く。
・対象のプロジェクトをのプラットフォームを新規作成にして、Any CPUを選ぶ。
 ⇒ふつうここで行けるっぽいけど、私の環境では
 「同じ名前のプラットフォームが既に存在するため、このプラットフォームを作成できませんでした。」
 と表示されたので、「x64」を新規作成した。
・プロジェクトのプロパティを開いて、プラットフォームを Any CPU(もしくはx64)、プラットフォームターゲットを「Any CPU」に変更。

したら表示されるようになった。

なんだったんだろーか。なんかプロジェクトが壊れている気がするけど、とりあえずなおったので放置。(問題の先送り)

Windows 7 の同時接続数


XPでは同時に接続できる数が10に制限されていたが、Vista/2008Serverからは無制限になった。

■Notable Changes in Windows Server 2008 SP2 and Windows Vista SP2
http://technet.microsoft.com/en-us/library/dd335036%28WS.10%29.aspx?ppud=4

「SP2 removes the limit of 10 half open outbound TCP connections. By default, SP2 has no limit on the number of half open outbound TCP connections.」

Windows 7 の情報がないけど、多分そうなんだろうね。
試してみないと。

2013年5月19日日曜日

VMWARE FUSION 5

MBA上の Windows7は VMWARE FUSION 4で動いてるんだけど、RHELの6が動かんのでそのうち買おうと思ってた5が、act2で買うと4900円だけど amazonで3800円くらいだったからポチっと。


大体2日くらいで届く。早いねー。


インストーラはCDだけど、USBも付いててそれでインストール出来る。
ドライブがないMBAには実にありがたい。

製品登録してて気づいたけど、Act2にユーザ登録してたらもしかしたら無償でアップグレード出来たかも。まあいいか。いい製品への投資と考えて。

2013年5月11日土曜日

[Silverlight]CSV出力

Silverlight で CSV データを保存しよう。
たぶん、やり方は2つ。



Silverlight アプリケーションでデータを生成し、ローカル保存するのが1つ目。


    string csvData = "";

    // カンマ区切りの文字列を csvData に設定


    SaveFileDialog dialog = new SaveFileDialog();
    dialog.DefaultExt = ".csv";
    dialog.Filter = "データ | *.csv";
    dialog.DefaultFileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv";
    if (dialog.ShowDialog() == true)
    {
        using (var stream = dialog.OpenFile())
        {
            using (var writer = new StreamWriter(stream, Encoding.UTF8))
            {
                writer.Write(csvData);
                writer.Flush();
            }
        }
    }



CSVファイルの文字コードは shift-jis じゃないと Excel で開いたときに文字化けしてしまう。普通にファイル出力してしまうと、UTF-8 で出力される。とはいえ、Silverlight には標準で shift-jis にサクッと変換するすべは無い。だが、Excel も UTF-8 をサポートしているはずなので、調べてみたところ BOM(Byte Order Mark) が付与されているものであれば、UTF-8 でも開けるとのこと。

BOM を付与するには、StreamWriter の第二パラメータにちゃんと UTF8 ですよってつけてあげればおk。

DefaultFileName を未設定だと、保存ダイアログのファイル名のところが空になってしまい、設定しちゃうと、保存ダイアログ表示前に勝手に確認ダイアログが出るのが気に入らない。
UTF-8 じゃなくて shift-jis で出したい場合は、ちょっと手間だけど次の方法。



サーバーサイドで作ってダウンロードさせる。これが2つ目。

aspx 作って POST で返すのもいいけど、今回はジェネリックハンドラを使う。
まずはサーバーサイド。



    /// <summary>
    /// CsvDownload の概要の説明
    /// </summary>
    public class CsvDownload : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            string csvData = "";

            // カンマ区切りの文字列を csvData に設定

            context.Response.ContentType = "text/csv";
            context.Response.AddHeader("Content-Disposition", "attachment;filename=" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv");
            context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("shift-jis");
            context.Response.Write(csvData);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }



これで、CsvDownload.ashx をクライアント側から呼び出すだけでおk。

呼び出し方はいくつかあって、Silverlight アプリケーションから直接呼び出す場合は、WebClient クラスを使ってバイトデータを読み出したあとに、1つ目と同じ方法で保存する。

javascript 側からリクエストする方法もいくつかある。
流れはjsにリクエストさせる為のメソッドを用意して、Silverlight側からCALLする。


☆js側

    <script type="text/javascript">
        function getCsv() {
        }
    </script>


☆SL側

            HtmlPage.Window.Invoke("getCsv");






getCsv の中でHTTPリクエストをやるんだけど、まずは一番かっちょわるいやりかた。
新規Window作ってそこからリクエストする。


            var w = window.open("CsvDownload.ashx", "csv", "width=1,height=1", null);
            w.onload = function () {
                w.close();
            };
            self.focus();

Windowが見えるのはやだよね。
これを回避する為には隠しiframeを使う。

            var iframe = document.createElement("iframe");
            if (iframe != null) {
                iframe.style.display = "none";
                iframe.onload = function () {
                    document.body.removeChild(iframe);
                }
                document.body.appendChild(iframe);
                iframe.src = "CsvDownload.ashx";
            }


ほかにも jQuery の ajax 使うのとか色々ありそうだけど、キリが無いので今日はここまで。

2013年3月22日金曜日

[Silverlight]XAMLにデータをXMLとして記述する

XML スキーマに合わせてカスタムコントロールを用意すればある程度出来るが、つまづいたのは List<T> 型。XAML からの定義がうまくいかなかったりする。回避するには List<T> を継承したクラスでワンクッション置く必要がある。

以下に数値キーに対するイメージのカスタムコントロールを記述する。


    public class SampleContentControl : ContentControl
    {
        public ImageList ImageList
        {
            get { return (ImageList)GetValue(ImageListProperty); }
            set { SetValue(ImageListProperty, value); }
        }

        public static readonly DependencyProperty ImageListProperty =
            DependencyProperty.Register("ImageList", typeof(ImageList), typeof(SampleContentControl), new PropertyMetadata(new ImageList()));
    }

    public class ImageList : List<ImageInfo>
    {
    }

    public class ImageInfo
    {
        public int Key { get; set; }
        public ImageSource Value { get; set; }
    }




XAML 側の定義はこうなる。(ResourceDicitonary内ね)


    <local:ImageList x:Key="imageList">
        <local:ImageInfo Key="1" Value="{StaticResource aaa}"/>
        <local:ImageInfo Key="2" Value="{StaticResource bbb}"/>
        <local:ImageInfo Key="3" Value="{StaticResource ccc}"/>
    </local:ImageList>




[C#]画像の印刷ダイアログをプロセス起動する

Windows 7 の場合、画像ファイルを指定してプロセス起動すると、Windows フォトビューアーが起動する(はず)。


            Process.Start(@"D:\penguins.jpg");


でも出したいのは印刷プレビュー画面。画像ファイルを右クリック->印刷で選んだ時のダイアログ。こんなやつ。



レジストリとか色々調べてしまったが(それはそれで勉強になった)、プロセス起動時にVerbプロパティに print を指定してあげるといい。

            ProcessStartInfo info = new ProcessStartInfo(@"D:\penguins.jpg");
            info.Verb = "print";
            Process.Start(info);