2012年12月19日水曜日

Azure へ移動かも

最近、実験を兼ねて、Azure で遊んでます。
Blogも
http://kattoshi.azurewebsites.net/へ移動するかも

2012年1月29日日曜日

TextBlock にClipboardへのコピー機能を追加する(改訂版)

前回投稿した「TextBlock にClipboardへのコピー機能を追加する」ですが、
あのコードだと、メモリーは消費するわ、メモリーリークしまくるわで使えないことがわかりました。
ここに、改良版を投稿します
  1. メモリーリークの問題
    右クリックで表示しているContextMenuですが、その右クリックを監視している ContextMenuService自体がメモリーリークを起こしているみたいで、OwnerのTextblockが破棄されれもContextMenuServiceに設定されたContextMenuは残っているみたいです。
  2. メモリーの消費
    コードを読めばわかると思いますが、TextBlockの配下にContextMenuServiceとContextMenu、その下にMenuItemが作成されます。これらの生成されたインスタンス「TextBlockClipBoardService.ID=""」によって、すべてのTextBlockの子となるので、メモリーの消費量がタダモンではありません。

    (実際、設定されたTextBlockをDataGridのCellTempleteに設定したらスクロールが耐えられないほどカクカク)

対応策として

  1. なるべく生成するインスタンスを少なくする
    ContextMenuService は諦め、シングルトンのPopupオブジェクトを表示する
  2. メモリーリークをなくす
    循環参照を撲滅する。
観点に再作成しました。

2012年1月27日金曜日

TextBlock に Clipboard へのコピー機能を追加する

2011/01/29 追記
この方法は、不具合がありました。改訂版は「TextBlock に Clipboard へのコピー機能を追加する(改訂版)」で紹介してます。

とあるお客さんで 「TextBlock に表示している文字列を他のアプリへコピーしたいんだけど...」と要求がありました。
Silverlightで作成したプログラムはすでに完成間近。

手間がかからず、短期間で実装したコードを紹介する。

操作は、TextBlockのテキストを右クリックすると、コンテキストメニューが表示され、メニューを選択すると、クリップボードへコピーする。

参考URL:Silverlight で ContextMenu を使ってみる



  1. TextBlockで右クリック
  2. 選択すると

2011年10月22日土曜日

Silverlight4で分離ストレージへ保存

Silverlight4で分離ストレージに保存する。
データモデルをまるごと、AESの暗号化をして保存する

using System.Xml;
using System.Xml.Serialization;
using System.Security.Cryptography;
using System.Text;

/// <summary>
    /// 保存ストレージ保存用ユーザプロファイル
    /// </summary>
    [XmlRoot("UserProfile")]
    public class UserProfileDataModel
    {
        /// <summary>
        /// ログインユーザ
        /// </summary>
        [XmlElement("LoginUserID")]
        public string LoginUserID 
        {
            get;
            set;
        }
        /// <summary>
        /// 最終操作日時
        /// </summary>
        [XmlElement("LastUpdateDateTime")]
        public DateTime LastUpdateDateTime
        {
            get;
            set;
        }
        /// <summary>
        /// 自動ログインタイムアウト
        /// </summary>
        [XmlElement("TimeoutHour")]
        public int TimeoutHour
        {
            get;
            set;
        }

        // パスワード
        private const string PASSWORD = "Password_Present";
        // ファイル名
        private const string FILENAME = "UserProfile.xml";
        
        /// <summary>
        ///  分離ストレージへ保存
        /// </summary>
        public void SaveProfile()
        {
            var isoStorage = IsolatedStorageFile.GetUserStoreForSite();
            using (isoStorage)
            {
                var isoStream = new IsolatedStorageFileStream(FILENAME
                                                                , FileMode.Create
                                                                , FileAccess.Write
                                                                , isoStorage);
                using (isoStream)
                {
                    var serializer = new XmlSerializer(typeof(UserProfileDataModel));
                    XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();

                    var aesManage = new AesManaged();

                    using (aesManage)
                    {
                        GenerateKeyFromPassword(PASSWORD, aesManage);

                        CryptoStream cryStream = new CryptoStream(isoStream, aesManage.CreateEncryptor(), CryptoStreamMode.Write);
                        using (cryStream)
                        {
                            namespaces.Add(string.Empty, string.Empty);
                            serializer.Serialize(cryStream, this, namespaces);
                        }
                    }
                }
            } 
        }
        /// <summary>
        /// 分離ストレージから読み込み
        /// </summary>
        /// <returns>null以外:読み込んだユーザプロファイル</returns>
        public static UserProfileDataModel LoadProfile()
        {
            UserProfileDataModel loadUserProfile = default(UserProfileDataModel);

            IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForSite();
            using (isoStorage)
            {
                if (!isoStorage.FileExists(FILENAME))
                {
                    //ファイルが存在しない時
                    return default(UserProfileDataModel);
                }

                var isoStream = new IsolatedStorageFileStream(FILENAME
                                                            , FileMode.Open
                                                            , FileAccess.Read
                                                            , isoStorage);
                using (isoStream)
                {
                    // AES 作成
                    var aesManage = new AesManaged();
                    using (aesManage)
                    {
                        // キーとIVを設定する
                        GenerateKeyFromPassword(PASSWORD, aesManage);

                        CryptoStream cryStream = new CryptoStream(isoStream, aesManage.CreateDecryptor(), CryptoStreamMode.Read);
                        using (cryStream)
                        {
                            try
                            {
                                var serializer = new XmlSerializer(typeof(UserProfileDataModel));
                                loadUserProfile = (UserProfileDataModel)serializer.Deserialize(cryStream);
                            }
                            catch (CryptographicException)
                            {
                                //復号化失敗
                                return loadUserProfile;
                            }
                        }
                    }
                }
            }
            return loadUserProfile;
        }

        /// <summary>
        /// パスワードから共有キーと初期化ベクタを生成する
        /// </summary>
        /// <param name="password">基になるパスワード</param>
        /// <param name="aesManaged">対象のAES</param>
        private static void GenerateKeyFromPassword(string password, AesManaged aesManaged)
        {
            //パスワードから共有キーと初期化ベクタを作成する
            byte[] salt = System.Text.Encoding.UTF8.GetBytes("PasswordSalt:More_Than_8_Bytes");
            var deriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt);
            deriveBytes.IterationCount = 1000;

            //共有キーと初期化ベクタを生成する
            aesManaged.Key = deriveBytes.GetBytes(aesManaged.KeySize / 8);
            aesManaged.IV = deriveBytes.GetBytes(aesManaged.BlockSize / 8);
        }
    }

2011年10月13日木曜日

Dell Vostro200 にWindows2003 Server R2 セットアップ

Dell Vostro200 に Windows2003 Server R2 インストールのメモ
普通にセットアップ
ドライバーは、Dellサイトから XPのドライバーをダウンロード

  1. チップセット
  2. Intelのサウンドドライバ゛ー
  3. RealtekのAudioドライバー

以上をゴニョゴニョしてセットアップでOK

2011年9月29日木曜日

TFS2010 で Silverlightのビルドができない

TFS2010でSilverlight4のプロジェクトをビルドすると次のエラーになる

C:\Program Files (x86)\MSBuild\Microsoft\Silverlight\v4.0\Microsoft.Silverlight.Common.targets (104): Silverlight 4 SDK がインストールされていません。

検索したところ次のURLに解決策
http://blog.benday.com/archive/2010/04/20/23272.aspx

ビルドを編集して
ビルドの編集

MSBuildプラットフォームを「Auto」→「X86」へ変更すればOK

2011年5月24日火曜日

プロジェクトリソースの画像ファイルをBitmapへ読み込み

WPF
画像ファイルをプロジェクトに追加する
ビルドアクションは「Resource」
出力ディレクトリーにコピー「コピーしない」



StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("(サブフォルダ)/画像ファイル名"UriKind.Relative));
backGround = (Bitmap)Bitmap.FromStream(streamInfo.Stream);

2011年1月30日日曜日

VisualStudio 2010 でコピーや貼り付け操作を行うとメモリー不足

VisualStudio 2010 でコピーや貼り付け操作を行うとメモリー不足が発生する場合があるので、その対策パッチのURLを次に示す。
http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=29729

VisualStudio Blog
http://blogs.msdn.com/b/visualstudio/archive/2010/06/25/patch-available-for-cut-or-copy-displaying-insufficient-memory-error-in-vs-2010.aspx

VS2010のセットアップする毎に探しまくっているので、ここに記す。

2011年1月12日水曜日

WinMargeをTFSのツールとして使用する場合のコマンドライン

VisualStudio 2010 の TFSで外部ツールとして「WinMarge」を使用する方法


設定場所
[ツール]-[オプション]
[ソース管理]-[Visual Studio Team Foundation Server]を選択後
「ユーザツールの構成」
  1. 比較ツール
    コマンドには「WinMargeU.exe」を選択
    引数「/wl /dl %6 /dr %7 %1 %2」
  2. マージツール
    コマンドには「WinMargeU.exe」を選択
    引数「/wl /dl %6 /dr %7 %1 %2 /o %4」
------------------------------------
(2011/12/01変更)
比較ツールのコマンドラインは次のように変更したほうが、比較中に右ソースの内容を
変更できていいと思います。

「/wl/wr/dl %6 /dr %7 %1 %2」

「/wl /dl %6 /dr %7 %1 %2」

2010年12月14日火曜日

.NET/C# 定義したFile名やメソッド名

C++でいうところの __FILENAME__

System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();


System.Diagnostics.StackFrame sf = st.GetFrame(0);

MessageBox.Show( string.Format("{0}:{1}",sf.GetMethod().DeclaringType.FullName, sf.GetMethod().Name));