none
画像にユーザーがアクセスできないようにするには。 RRS feed

  • 質問

  • アプリケーションと同じ階層に何種類かの画像を置いて、アプリケーションから使用しています。

    ユーザーからは、アプリケーションを起動していない時など、アクセスできないようにしたいのですが、

    そういったことは可能なのでしょうか?

    2008年9月19日 7:59

回答

  •  acslearner さんからの引用

    Azuleanさんからの引用

    ★MemoryStreamを経由して保存する

    ・MemoryStreamを作る。

    MemoryStreamを使ってBitmapをSaveする。

    ・MemoryStreamからCryptoStreamに書き写す。

     

    ★MemoryStreamを経由して読み出す。

    ・MemroyStreamを作る。

    ・CryptoStreamからMemoryStreamに書き写す。

    ・MemoryStreamの現在位置をSeekで先頭に戻す。

    ・BitmapコンストラクタにMemoryStreamを渡す。

     

    青字のところでいきなりつまづきました。

    青文字のところはできていて、その次のCryptoStreamへの書き写しが引っかかっているように見えました。

     

     acslearner さんからの引用

    Azuleanさんからの引用

    ※ソース中にcs2とfs2の取り違えがある点はご注意ください。

     

    どの部分がどの様に間違っているかはっきりわかりませんでした。

    cs2を通して読み込まないといけないのに、new Bitmapに渡しているのがfs2になっている点です。

     

     acslearner さんからの引用

    わからないなりにしぼりだしたコードが下記です。

    添削よろしくおねがいいたします。

    1回、さっくりと書きますので、どういったことを行っているか考えてみてもらえませんか?

     

    お願い:コードをコピペして済まさないでください。

    サンプルを見て、知識なり考え方なり、何らかの形で自分の力にしてください。

     

    Code Snippet

    using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    {
        byte[] desKey = des.Key;
        byte[] desIV = des.IV;

        // 暗号化して保存
        using (Bitmap fileBitmap = new Bitmap("Test.png"))
        {
            using (FileStream writeFileStream =
                new FileStream("Encrypted.png", FileMode.Create, FileAccess.Write))
            using (CryptoStream cryptStream =new CryptoStream(writeFileStream,
                des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write))
            {
                using (MemoryStream writeMemoryStream = new MemoryStream())
                {
                    // MemoryStreamに保存
                    fileBitmap.Save(writeMemoryStream, ImageFormat.Png);
                    // MemoryStream→CryptoStream→FileStream
                    writeMemoryStream.WriteTo(cryptStream);
                }
            }
        }

        // 復号して読み込み
        using (FileStream readFileStream =
            new FileStream("Encrypted.png", FileMode.Open, FileAccess.Read))
        using (CryptoStream decryptStream = new CryptoStream(readFileStream,
            des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read))
        using (BinaryReader readBinaryReader = new BinaryReader(decryptStream))
        using (MemoryStream temporaryMemoryStream = new MemoryStream())
        {
            // FileStream→CryptoStream→MemoryStream
            byte[] buffer;
            while((buffer = readBinaryReader.ReadBytes(1024)) != null)
            {
                if (buffer.Length == 0) break;
                temporaryMemoryStream.Write(buffer, 0, buffer.Length);
            }

            // MemoryStreamから読み込み (Seekしておかないとまずいはず)
            temporaryMemoryStream.Seek(0, SeekOrigin.Begin);                   
            using (Bitmap savedBitmap = new Bitmap(temporaryMemoryStream))
            {
                // 読み込んだ結果を確認するために保存
                savedBitmap.Save("Restored.png", ImageFormat.Png);
            }
        }
    }

     


     

     

    2008年10月3日 14:34
    モデレータ

すべての返信

  •  acslearner さんからの引用

    アプリケーションと同じ階層に何種類かの画像を置いて、アプリケーションから使用しています。

    ユーザーからは、アプリケーションを起動していない時など、アクセスできないようにしたいのですが、

    そういったことは可能なのでしょうか?

    普通の画像ファイルであれば無理でしょう。

    アプリケーションが起動していないときにファイルへのアクセスを制御する術はありません。

     

    アプリケーションのリソースとして必要な画像を持っておけば、簡単には開けなくなります。

    (参考:http://dobon.net/vb/dotnet/programing/bitmapresource.html

     

    アプリケーションの外にファイルを置くのであれば、ファイルを暗号化しておき、必要なときに復号して画面に表示するといったところでしょうか。

    (参考:http://dobon.net/vb/dotnet/string/encryptfile.html

     

     

    ※厳密にはそれなりの知識を持って時間をかければ、リソースから取り出したり、復号したりは可能です。

    ※ファイルシステムのセキュリティ設定は実行ユーザを設定する等の施策が必要なので、多分回答にならないかなと判断しています。
    2008年9月19日 15:14
    モデレータ
  • Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    namespace testAppli2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            Bitmap bmp;
            private void Form1_Load(object sender, EventArgs e)
            {
                System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                bmp =new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
               
                Invalidate();
            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {
               
                e.Graphics.DrawImage(bmp, new Point(0, 0));
            }
        }
    }

     

     

    上記のようにコーディングしたところ、下のようなエラーが出てしまいました。どうすればよいでしょうか。

    エラー
    エラー 1 'testAppli2.Form1.Dispose(bool)': オーバーライドする適切なメソッドが見つかりませんでした。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli2\testAppli2\Form1.Designer.cs 14 33 testAppli2

     

     


    2008年9月20日 12:42
  •  acslearner さんからの引用

    上記のようにコーディングしたところ、下のようなエラーが出てしまいました。どうすればよいでしょうか。

     
    エラー
    エラー 1 'testAppli2.Form1.Dispose(bool)': オーバーライドする適切なメソッドが見つかりませんでした。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli2\testAppli2\Form1.Designer.cs 14 33 testAppli2

     

     

    とりあえず、Form1.Designer.csを確認してみては?

    載せられているコードはForm1.csだけなので、エラー内容から原因を教えてくれというのは無理があります。

     

    ※恐らくは、Form1.Designer.csに書かれているForm1がFormの派生クラスになっていないとみられますが、現状の情報じゃ何とも言えません。

    2008年9月20日 13:06
    モデレータ
  •  acslearner さんからの引用

    Code Snippet

            private void Form1_Load(object sender, EventArgs e)
            {
                System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                bmp =new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
               
                Invalidate();
            }

     

    あと、LoadイベントでInvalidateを呼ぶのは辞めた方が良いでしょう。

    まだ、Formは表示されていない状態ですから。

    2008年9月20日 13:09
    モデレータ
  • Form1.Designer.cs

    namespace testAppli2
    {
        partial class Form1
        {
            /// <summary>
            /// 必要なデザイナ変数です。
            /// </summary>
            private System.ComponentModel.IContainer components = null;

            /// <summary>
            /// 使用中のリソースをすべてクリーンアップします。
            /// </summary>
            /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }

            #region Windows フォーム デザイナで生成されたコード

            /// <summary>
            /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
            /// コード エディタで変更しないでください。
            /// </summary>
            private void InitializeComponent()
            {
                this.SuspendLayout();
                //
                // Form1
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(284, 263);
                this.Name = "Form1";
                this.Text = "Form1";
                this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
                this.Load += new System.EventHandler(this.Form1_Load);
                this.ResumeLayout(false);

            }

            #endregion
        }
    }

     

    Form1.Designer.csは上記の通りです。

     

    2008年9月21日 10:10
  •  acslearner さんからの引用

    Form1.Designer.csは上記の通りです。

    新規作成したプロジェクトからForm1.cs、Form1.Designer.csの中身を置き換えてみましたが、再現できませんでした。

    何か、別の要因でForm1がおかしな状態になっているのではないかと推測します。

     

    そのプロジェクトについてもう少し説明して下さい。

    (プロジェクトを新規に作成してからどのような手順を踏んだのか)

    2008年9月21日 13:30
    モデレータ
  • testAppli3を新たに作ったところ(Form1.Designer.csの中身は同じ)おかしな状態は再現できませんでした。

    しかし、testAppli2のForm1.csのビルドアクションが"なし"になっていたので"コンパイル"にしたところ"ビルド正常"と表示されました。

    ただしエラー一覧に

    エラー

    警告 1 ファイル内にデザインできるクラスがないため、このファイルのデザイナを表示できませんでした。ファイルの以下のクラスがデザイナで見つかりました:

     Form1 --- 基本クラス 'System.Object' をデザインできません。  0 0 

     

    が残りました。

     

    何か変なことをしてしまったようなのですが、思い出せません。testAppli3では再現しなかったのでこの問題は置いておいてtestAppli3で話を進めていきたいと思います。すみません。

    2008年9月22日 7:26
  • Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    namespace testAppli3
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;

            private void Form1_Load(object sender, EventArgs e)
            {
                System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                bmp = new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
               

            }

            private void Form1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                Invalidate();
            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                e.Graphics.DrawImage(bmp, new Point(0, 0));
            }
        }
    }

    Azuleanさんからの引用

    アプリケーションのリソースとして必要な画像を持っておけば、簡単には開けなくなります。

    (参考:http://dobon.net/vb/dotnet/programing/bitmapresource.html

     

    に従って、Map.pngを追加しました。Map.pngのビルドアクションは"埋め込まれたリソース"に設定しました。

    上記のコードで、デバッグしましたが、例外「'null' の値は 'stream' に対して有効ではありません。」がでて失敗しました。

    2008年9月22日 7:35
  • "Map.png" じゃなくて "testAppli3.Map.png" じゃないですか?

    http://msdn.microsoft.com/ja-jp/library/yf17tthe.aspx

     

    Assembly.GetManifestResourceNames メソッド で確認してください。

    http://msdn.microsoft.com/ja-jp/library/system.reflection.assembly.getmanifestresourcenames(VS.80).aspx
    2008年9月22日 8:51
  • えムナウさんご指摘ありがとうございます。"testAppli3.Map.png"で成功しました。

    2008年9月22日 11:32
  • Azuleanさんからの引用

    アプリケーションの外にファイルを置くのであれば、ファイルを暗号化しておき、必要なときに復号して画面に表示するといったところでしょうか。

    (参考:http://dobon.net/vb/dotnet/string/encryptfile.html

     

    Bitmap bmp=new Bitmap("Map2.png");

    Bitmap tBmp;

    のあと

    ①bmpを暗号化しファイル出力して保存する。

    ②保存したファイルを読み込んで復号化して、tBmpに格納する。

     

    以上をできるだけシンプルに行いたいのですが、力不足で、色々調べたのですが自分ではコーディングできませんでした。

    どうかよろしくお願いします。

     

    2008年9月24日 10:36
  •  acslearner さんからの引用

    Bitmap bmp=new Bitmap("Map2.png");

    Bitmap tBmp;

    のあと

    ①bmpを暗号化しファイル出力して保存する。

    ②保存したファイルを読み込んで複合化して、tBmpに格納する。

    以上をできるだけシンプルに行いたいのですが、力不足で、色々調べたのですが自分ではコーディングできませんでした。

    どうかよろしくお願いします。

    何をお願いしているのか明確ではありませんが、少なくとも私はコードを代理で書く人ではありませんので、ご自身の手でコードを書いて下さい。

    私の時間も限られており、あまり余裕がないので、要点だけ書いておきます。

     

    ・書き込み

    FileStreamを作る。

    暗号化Streamを作って、先のFileStreamと関連づける。

    暗号化StreamをBitmap.Saveメソッドに渡す。

    保存されたファイルは暗号化された状態。

     

    ・読み込み

    FileStreamを作る。

    復号Streamを作って、先のFileStreamと関連づける。

    復号StreamをBitmapのコンストラクタに渡す。

    復号を行ってBitmapのインスタンスが作成される。

     

    先に示したどぼんさんのサンプルから暗号化・復号の基本的な流れを理解し、Bitmap.Save(Stream)メソッドやBitmap(Stream)コンストラクタをうまく組み合わせる応用ができれば、既存のクラスの組み合わせで実現できるはずです。

    (実際にうまくできるかは確かめていません。間違っていることに気づかれた方はご指摘をお願いします)

     

    http://msdn.microsoft.com/ja-jp/library/ms142147.aspx

    http://msdn.microsoft.com/ja-jp/library/ms142147.aspx

     

    2008年9月24日 16:31
    モデレータ
  • http://www.microsoft.com/japan/msdn/thisweek/300x10/phase2/encrypt/cs.aspx

    http://support.microsoft.com/kb/307010/ja

    上記の参照も見つけました。まだコーディングには成功していません。格闘中です。

    時間のある方はご協力お願いいたします。

    2008年9月25日 11:33
  • Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            public bool isClick = false;
            private byte[] DesKey;
            private byte[] DesIV;
            private byte[] cryptData;

            private void Form1_Load(object sender, EventArgs e)
            {
                byte[] source = Encoding.Unicode.GetBytes("Map2.png");

                // Triple DES のサービス プロバイダを生成します
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

                // 入出力用のストリームを生成します
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DesKey, DesIV),
                                                                    CryptoStreamMode.Write);

                // ストリームに暗号化されたデータを書き込みます
                cs.Write(cryptData, 0, cryptData.Length);
                bmp.Save(cs);
                cs.Close();

                tBmp(ms);
                ms.Close();

               }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {
                if (isClick == false) isClick = true;
                else isClick = false;

                Invalidate();
            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                if (isClick == true) e.Graphics.DrawImage(bmp, new Point(0, 0));
                else if (isClick == false) e.Graphics.DrawImage(tBmp, new Point(0, 0));
            }
        }
    }

     

    エラ-
    エラー 1 'System.Drawing.Image.Save(string)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 42 13 testAppli4
    エラー 2 引数 '1': 'System.Security.Cryptography.CryptoStream' から 'string' に変換できません。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 42 22 testAppli4
    エラー 3 'testAppli4.Form1.tBmp' は 'フィールド' ですが、'メソッド' のように使用されています。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 45 13 testAppli4

     

     

    もともとまったく自信がありませんでしたが、失敗してしまいました(T-T)

    2008年9月25日 12:17
  • もう少し初歩的なところから固めた方が良いのではないかと不安を感じます。

    その場限りの答えを示すことはできますが、力になるのかどうか疑問を抱いているため、コードを書いていません。あしからずご了承ください。

    (答えがあればそれからどのように間違えていたかを含めて、仕組みを理解できるというのであればその旨レスをください)

     

     acslearner さんからの引用

    Code Snippet

            private void Form1_Load(object sender, EventArgs e)
            {

    // 略

                bmp.Save(cs);
                cs.Close();

                tBmp(ms);
                ms.Close();

               }

    }

     

    (私が言うのも難ですが…、)私の書き間違えそのまま鵜呑みにしないでください。

    そして、エラー内容とヘルプを見比べて下さい。

     

    ・Streamを1個だけ渡すSaveメソッドは存在しません。適切な引数を与えて下さい。

    ・コンストラクタの呼び方についてもう少し初歩から考えてみて下さい。tBmp(ms)はC#の構文上、何がやりたいのか見えない形になっています。

    ・コンパイルが通っても、実行時にArgumentNullExceptionが置きます。今のコードは何をしているか考えてみて下さい。

     

    暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。

    それができてから、暗号化ストリームと組み合わせましょう。

    2008年9月25日 14:23
    モデレータ
  • Azuleanさんからの引用

    暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。

     

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Drawing.Imaging;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            private void Form1_Load(object sender, EventArgs e)
            {
                FileStream fs;
                fs = new FileStream("Map2.png", FileMode.Open, FileAccess.Read);
                bmp = new Bitmap(fs);
                bmp.Save(fs, ImageFormat.Png);
                fs.Close();


            }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {

            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {

            }
        }
    }

     

    やってみましたが、失敗しました(TДT)確かに初歩的なことが分かっていません。

    例外

     

    Just-In-Time (JIT) デバッグを呼び出すための詳細については、
    ダイアログ ボックスではなく、このメッセージの最後を参照してください。

    ************** 例外テキスト **************
    System.Runtime.InteropServices.ExternalException: GDI+ で汎用エラーが発生しました。
       場所 System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
       場所 System.Drawing.Image.Save(Stream stream, ImageFormat format)
       場所 testAppli4.Form1.Form1_Load(Object sender, EventArgs e) 場所 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs:行 29
       場所 System.Windows.Forms.Form.OnLoad(EventArgs e)
       場所 System.Windows.Forms.Form.OnCreateControl()
       場所 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       場所 System.Windows.Forms.Control.CreateControl()
       場所 System.Windows.Forms.Control.WmShowWindow(Message& m)
       場所 System.Windows.Forms.Control.WndProc(Message& m)
       場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       場所 System.Windows.Forms.ContainerControl.WndProc(Message& m)
       場所 System.Windows.Forms.Form.WmShowWindow(Message& m)
       場所 System.Windows.Forms.Form.WndProc(Message& m)
       場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       場所 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


    ************** 読み込まれたアセンブリ **************
    mscorlib
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
    ----------------------------------------
    testAppli4
        アセンブリ バージョン: 1.0.0.0
        Win32 バージョン: 1.0.0.0
        コードベース: file:///C:/Users/Y/Documents/Visual%20Studio%202005/Projects/testAppli4/testAppli4/bin/Release/testAppli4.exe
    ----------------------------------------
    System.Windows.Forms
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
    ----------------------------------------
    System
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
    ----------------------------------------
    System.Drawing
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
    ----------------------------------------
    mscorlib.resources
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
    ----------------------------------------
    System.Drawing.resources
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing.resources/2.0.0.0_ja_b03f5f7f11d50a3a/System.Drawing.resources.dll
    ----------------------------------------
    System.Windows.Forms.resources
        アセンブリ バージョン: 2.0.0.0
        Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
        コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_ja_b77a5c561934e089/System.Windows.Forms.resources.dll
    ----------------------------------------

    ************** JIT デバッグ **************
    Just-In-Time (JIT) デバッグを有効にするには、このアプリケーション、
    またはコンピュータ (machine.config) の構成ファイルの jitDebugging
    値を system.windows.forms セクションで設定しなければなりません。
    アプリケーションはまた、デバッグを有効にしてコンパイルされなければ
    なりません。

    例:

    <configuration>
        <system.windows.forms jitDebugging="true" />
    </configuration>

    JIT デバッグが有効なときは、このダイアログ ボックスで処理するよりも、
    ハンドルされていない例外はすべてコンピュータに登録された
    JIT デバッガに設定されなければなりません。

     

    http://blog.kaburk.com/lang/csharp-filestream-save.html

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=15772&forum=7&6

    以上を参考にしました。

     

    2008年9月26日 12:16
  •  acslearner さんからの引用

     

    Code Snippet

            private void Form1_Load(object sender, EventArgs e)
            {
                FileStream fs;
                fs = new FileStream("Map2.png", FileMode.Open, FileAccess.Read);
                bmp = new Bitmap(fs);
                bmp.Save(fs, ImageFormat.Png);
                fs.Close();


            }

    Readという読み取りで開いたFileStreamにSaveという書き込みはできませんよね。

    FileStreamクラスのコンストラクタやFileAccess列挙体のヘルプは読みましたか?

    新しい要素を使う前には、そのヘルプを一度読み込むぐらいでないと、応用が利かなくなってきますよ。

     

    ありがちなトラブル:

    ・ファイルを開いたままもう1個開こうとして失敗する。

    ・読み書きアクセスして、末尾に新しいデータを書き込んだため、サイズが2倍ぐらいにふくれあがる。または壊れるか意図した書き換えが行えない。

    ・最初に書き込みアクセスしてBitmapクラスのコンストラクタで読み込めない。

     

     

    ところで、掲示板でやりとりして進めている間は、私の時間的な都合もあるため、1日1レスポンス分しか進みません。

    片手間の趣味というのであれば良いのですが、会社の研修であるならば上司か研修担当者に、学術的なものならば周りの詳しい人に相談することをお薦めします。(期限は待ってくれないので)

    趣味であっても、これまでに体系的に学べているかどうかで、今後の応用力が変わるので、教本を手に取り直すか、もっと別の本に手を出してみるのも良いかもしれません。
    2008年9月26日 14:22
    モデレータ
  • ★ファイルの保存の流れ

    1.ファイルを読み込むか、自分で作るかしてBitmapインスタンスを用意する。

    2.FileStreamインスタンスを書き込みで作成する。

    3.Saveメソッドに2で作ったインスタンスを渡す。

    4.2で作ったインスタンスを閉じる。

     

    ★ファイル読み出しの流れ

    1.FileStreamインスタンスを読み込みで作成する。

    2.Bitmapのコンストラクタに1で作ったインスタンスを渡す。

     

    ★暗号化・復号と組み合わせることを考える

    ・BitmapコンストラクタやSaveメソッドはStreamクラスのインスタンスを引数に取る。

    ・FileStreamもCryptoStreamもStreamクラスの派生クラスなので、Streamクラスのインスタンスの代わりとして渡すことができる。

    ・FileStreamで保存・読み込みが実現できればもう一歩。

    ・FileStreamを使ってCryptoStreamを作り、CryptoStreamをSaveやコンストラクタに渡せれば暗号化しつつ書き込み、復号しつつ読み込みをやってくれる。

    2008年9月26日 14:32
    モデレータ
  • Azuleanさんからの引用
    暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。

     

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Drawing.Imaging;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            private void Form1_Load(object sender, EventArgs e)
            {
                bmp = new Bitmap("Map2.png");
               
                FileStream fs;
                fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
                bmp.Save(fs, ImageFormat.Png);
                fs.Close();
                FileStream fs2;
                fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
                tBmp = new Bitmap(fs2);
                fs2.Close();
                //確認のため
                tBmp.Save("x.png");
              

     


            }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {

            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {

            }
        }
    }

     

     

    一段階ですがやっとできました。

    2008年9月29日 9:04
  • Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Drawing.Imaging;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            private byte[] DesKey;
            private byte[] DesIV;

            private void Form1_Load(object sender, EventArgs e)
            {
                FileStream fs;
                bmp = new Bitmap("Map2.png");

                fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);


               
               
                bmp.Save(cs, ImageFormat.Png);
                fs.Close();
                cs.Close();

                FileStream fs2;
                fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
                CryptoStream cs2 = new CryptoStream(fs2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
               
                tBmp = new Bitmap(fs2);
                fs2.Close();
                cs2.Close();
                //確認のため
                tBmp.Save("x.png");
              

     


            }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {

            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {

            }
        }
    }

     

     

    エラー

    警告 1 フィールド 'testAppli4.Form1.DesKey' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 24 24 testAppli4
    警告 2 フィールド 'testAppli4.Form1.DesIV' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 25 24 testAppli4

     

     

    書いてみたのですが、エラーがでてしまいました。アドバイスよろしくお願いいたします。
    2008年10月1日 13:32
  •  acslearner さんからの引用
    エラー

    警告 1 フィールド 'testAppli4.Form1.DesKey' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 24 24 testAppli4
    警告 2 フィールド 'testAppli4.Form1.DesIV' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 25 24 testAppli4

     

     

    書いてみたのですが、エラーがでてしまいました。アドバイスよろしくお願いいたします。

    それはエラーではなく、警告です。

    しかし、実行時に例外がスローされて、実行が中断されると思います。

     

    DesKeyやDesIVは暗号化・復号の際に使用されます。

    何を設定するかは開発者次第ですが、適切な値を与えてあげないと暗号化・復号はできません。

    2008年10月1日 15:38
    モデレータ
  • デバッグすると、「GDI+ で汎用エラーが発生しました。」になってしまいました。

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Drawing.Imaging;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            private byte[] DesKey;

            private byte[] DesIV;

            private void Form1_Load(object sender, EventArgs e)
            {
                FileStream fs;
             
            
                bmp = new Bitmap("Map2.png");

                fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                DesKey = des.Key;
                DesIV = des.IV;
                CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);


                
                bmp.Save(cs, ImageFormat.Png);
                fs.Close();
                cs.Close();

                FileStream fs2;
                fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
                CryptoStream cs2 = new CryptoStream(fs2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
               
                tBmp = new Bitmap(fs2);
                fs2.Close();
                cs2.Close();
                //確認のため
                tBmp.Save("x.png");
              

     


            }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {

            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {

            }
        }
    }

     

     

    2008年10月2日 13:42
  •  acslearner さんからの引用

    デバッグすると、「GDI+ で汎用エラーが発生しました。」になってしまいました。

    PNGはCanSeek = falseなStream(CryptoStreamがそうなっている)には書けないようです。

    JPEGだとうまくいくかと思います。

    参考: http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=13363&forum=7

     

    ※ソース中にcs2とfs2の取り違えがある点はご注意ください。

     

    PNGフォーマットを暗号化・復号する形で実現したい場合は、一度MemoryStreamか、テンポラリファイルを経由することになりそうです。

     

    ★MemoryStreamを経由して保存する

    ・MemoryStreamを作る。

    ・MemoryStreamを使ってBitmapをSaveする。

    ・MemoryStreamからCryptoStreamに書き写す。

     

    ★MemoryStreamを経由して読み出す。

    ・MemroyStreamを作る。

    ・CryptoStreamからMemoryStreamに書き写す。

    ・MemoryStreamの現在位置をSeekで先頭に戻す。

    ・BitmapコンストラクタにMemoryStreamを渡す。

    2008年10月2日 14:24
    モデレータ
  • 暗号化のキーがコードに埋め込まれていると、ディスアセンブルで見えちゃうんですよね。

    単純なものでよければ、こんな方法も。

    • あきらめる。
      期間の多少はあれ、ほぼ必ずクラックされるので、クラックされるものにリソースをかけるのは無駄かと思います。
    • 拡張子を変更する。
      単に .bmp を .oresama にするだけでも、ダブルクリックで開けないなどの効果はある。
    • スタンプを変更する。
      .bmp など、先頭にフォーマット形式を示すコードがあるものについて、そのコードを書き換えておけば、開けなくはなる。
      上との組み合わせが効果的?
    • base64 エンコードする。
      気休めでしかないけど。

     

    2008年10月3日 0:06
  • Azuleanさんからの引用

    ★MemoryStreamを経由して保存する

    ・MemoryStreamを作る。

    MemoryStreamを使ってBitmapをSaveする。

    ・MemoryStreamからCryptoStreamに書き写す。

     

    ★MemoryStreamを経由して読み出す。

    ・MemroyStreamを作る。

    ・CryptoStreamからMemoryStreamに書き写す。

    ・MemoryStreamの現在位置をSeekで先頭に戻す。

    ・BitmapコンストラクタにMemoryStreamを渡す。

     

    青字のところでいきなりつまづきました。

     

    Azuleanさんからの引用

    ※ソース中にcs2とfs2の取り違えがある点はご注意ください。

     

    どの部分がどの様に間違っているかはっきりわかりませんでした。

     

    わからないなりにしぼりだしたコードが下記です。

    「GDI+ で汎用エラーが発生しました。」は解消されていません。

    添削よろしくおねがいいたします。

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Drawing.Imaging;


    namespace testAppli4
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public Bitmap bmp;
            public Bitmap tBmp;
            private byte[] DesKey;
            private byte[] DesIV;

            private void Form1_Load(object sender, EventArgs e)
            {
                MemoryStream ms;
                bmp = new Bitmap("Map2.png");

                ms = new MemoryStream();
                bmp.Save(ms, ImageFormat.Png);
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                DesKey = des.Key;
                DesIV = des.IV;
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);


               
               
                bmp.Save(cs, ImageFormat.Png);
                ms.Close();
                cs.Close();

                MemoryStream ms2;
                ms2 = new MemoryStream();
                CryptoStream cs2 = new CryptoStream(ms2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
               
                tBmp = new Bitmap(ms2);
                ms2.Close();
                cs2.Close();
                //確認のため
                tBmp.Save("x.png");
              

     


            }

            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {

            }

            private void Form1_Paint(object sender, PaintEventArgs e)
            {

            }
        }
    }

     

     

    2008年10月3日 13:55
  •  acslearner さんからの引用

    Azuleanさんからの引用

    ★MemoryStreamを経由して保存する

    ・MemoryStreamを作る。

    MemoryStreamを使ってBitmapをSaveする。

    ・MemoryStreamからCryptoStreamに書き写す。

     

    ★MemoryStreamを経由して読み出す。

    ・MemroyStreamを作る。

    ・CryptoStreamからMemoryStreamに書き写す。

    ・MemoryStreamの現在位置をSeekで先頭に戻す。

    ・BitmapコンストラクタにMemoryStreamを渡す。

     

    青字のところでいきなりつまづきました。

    青文字のところはできていて、その次のCryptoStreamへの書き写しが引っかかっているように見えました。

     

     acslearner さんからの引用

    Azuleanさんからの引用

    ※ソース中にcs2とfs2の取り違えがある点はご注意ください。

     

    どの部分がどの様に間違っているかはっきりわかりませんでした。

    cs2を通して読み込まないといけないのに、new Bitmapに渡しているのがfs2になっている点です。

     

     acslearner さんからの引用

    わからないなりにしぼりだしたコードが下記です。

    添削よろしくおねがいいたします。

    1回、さっくりと書きますので、どういったことを行っているか考えてみてもらえませんか?

     

    お願い:コードをコピペして済まさないでください。

    サンプルを見て、知識なり考え方なり、何らかの形で自分の力にしてください。

     

    Code Snippet

    using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    {
        byte[] desKey = des.Key;
        byte[] desIV = des.IV;

        // 暗号化して保存
        using (Bitmap fileBitmap = new Bitmap("Test.png"))
        {
            using (FileStream writeFileStream =
                new FileStream("Encrypted.png", FileMode.Create, FileAccess.Write))
            using (CryptoStream cryptStream =new CryptoStream(writeFileStream,
                des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write))
            {
                using (MemoryStream writeMemoryStream = new MemoryStream())
                {
                    // MemoryStreamに保存
                    fileBitmap.Save(writeMemoryStream, ImageFormat.Png);
                    // MemoryStream→CryptoStream→FileStream
                    writeMemoryStream.WriteTo(cryptStream);
                }
            }
        }

        // 復号して読み込み
        using (FileStream readFileStream =
            new FileStream("Encrypted.png", FileMode.Open, FileAccess.Read))
        using (CryptoStream decryptStream = new CryptoStream(readFileStream,
            des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read))
        using (BinaryReader readBinaryReader = new BinaryReader(decryptStream))
        using (MemoryStream temporaryMemoryStream = new MemoryStream())
        {
            // FileStream→CryptoStream→MemoryStream
            byte[] buffer;
            while((buffer = readBinaryReader.ReadBytes(1024)) != null)
            {
                if (buffer.Length == 0) break;
                temporaryMemoryStream.Write(buffer, 0, buffer.Length);
            }

            // MemoryStreamから読み込み (Seekしておかないとまずいはず)
            temporaryMemoryStream.Seek(0, SeekOrigin.Begin);                   
            using (Bitmap savedBitmap = new Bitmap(temporaryMemoryStream))
            {
                // 読み込んだ結果を確認するために保存
                savedBitmap.Save("Restored.png", ImageFormat.Png);
            }
        }
    }

     


     

     

    2008年10月3日 14:34
    モデレータ
  • コードは見事成功していました。心から感謝申し上げますm(__)m

    質問させていただきたいのですが、この1024という数字は、これより大きなファイルをあつかう時も有効なのでしょうか?

    Code Snippet

    while((buffer = readBinaryReader.ReadBytes(1024)) != null)

     

     

    http://msdn.microsoft.com/ja-jp/library/system.io.binaryreader.readbytes(VS.71).aspx
    2008年10月4日 10:45
  •  acslearner さんからの引用

    質問させていただきたいのですが、この1024という数字は、これより大きなファイルをあつかう時も有効なのでしょうか?

    提示したものは1024バイトずつ、ファイルの終端まで繰り返し読み込むといったコードになっています。

    繰り返しますので、1024バイトを越えるファイルでも特に問題ありませんが、1024バイトずつだと遅いとかはあり得るかもしれません。

     

     

    ところで、このページはVS 2003(.NET Framework 1.1)相当です。

    Visual Studio 2005や2008であればページ右上にあるリンクから、Visual Studio 2005(.NET Framework 2.0)やVisual Studio 2008(.NET Framework 3.5)向けのページを読むようにした方が良いのかもしれません。

    2008年10月4日 13:53
    モデレータ
  • 質問に答えて頂いた上、アドバイスを頂き有難うございました。サンプルを見ながら、勉強をして、「自分の力」になるよう努力していきたいと思います。本当にありがとうございました。

    ひとまず「回答済み」にさせていただきます。

    2008年10月5日 10:16