2

プロジェクトの一環としてファイルを暗号化および復号化するプログラムに取り組んでいます。プログラムは単独では正常に動作していますが、進行状況バーを追加して暗号化/復号化プロセスの進行状況を表示しようとすると、問題が発生します。プログレス バーは 85 ~ 90% までかなり順調に進み、その後、値が上限を超えたというエラーがスローされます。また、バーの進行が遅すぎます。16KB のファイルを暗号化していても、エラー状態になるまでに約 15 ~ 20 秒かかります。プログレス バーなしで完了すると、ほとんど時間がかかりません。バックグラウンドワーカーを使用してプログレスバーを実装しようとしました。私のプログラムでプログレスバーを動作させる方法を誰か教えてもらえますか?

暗号化プロセスのコードは次のとおりです。

public void EncryptFile()
    {

        try
        {
            OpenFileDialog od = new OpenFileDialog();
            od.Title = "Select File To Encrypt";
            od.Filter = "All files (*.*)|*.*";
            string ifile = "";
            if (od.ShowDialog() == DialogResult.OK)
            {
                ifile = od.InitialDirectory + od.FileName;
            }
            else
            {
                MessageBox.Show("No file selected!!");
                goto b;
            }

            if (Path.GetExtension(ifile) == ".arv")
            {
                MessageBox.Show("Error!!File already Encrypted.");
                return;
            }
            string ofile = ifile + ".arv";

        a: string password = Prompt.ShowDialog();
            if (password == "")
            {
                MessageBox.Show("Password Field cannot be blank!!");
                goto a;
            }
            else if (password == null)
            {
                goto b;
            }
            int ph = password.GetHashCode();
            byte[] ia = BitConverter.GetBytes(ph);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(ia);
            byte[] phb = ia;

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] salt = new byte[] { 10, 20, 30, 40, 50, 60, 70, 80 };
            Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(password, salt);

            string cryptFile = ofile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            AesManaged AMCrypto = new AesManaged();
            AMCrypto.Key = k.GetBytes(32);
            AMCrypto.IV = k.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsCrypt, AMCrypto.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(phb, 0, 4);
            FileStream fsIn = new FileStream(ifile, FileMode.Open);

            int data;
            while ((data = fsIn.ReadByte()) != -1)
                cs.WriteByte((byte)data);

            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
            File.Delete(ifile);
            MessageBox.Show("File Encrypted!!");
        b: ;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
        }

Prompt は、ユーザーにパスワードの入力を求める動的フォームを生成するために作成した別のクラスです。パスワードを入力して確認するための 2 つのフィールドと、パスワードを表示するチェックボックスを備えた、通常のパスワード プロンプトとほとんど同じように見えます。ifile は入力ファイルであり、ofile は出力ファイルです。

更新:バックグラウンドワーカーで試したコードは次のとおりです。プログレス バーは機能しているように見えますが、暗号化速度が大幅に低下し、プログレス バーがいっぱいになる前に暗号化プロセスが完了します。つまり、プログレス バーがいっぱいになる前に「暗号化完了」メッセージが表示されます。また、復号化のために同じことをしようとすると、暗号ストリームがシークをサポートしていないという例外が発生します。何か案は?

public Form1()
    {
        InitializeComponent();
        Shown += new EventHandler(Form1_Shown);


        backgroundWorker1.WorkerReportsProgress = true;

        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    }
    void Form1_Shown(object sender, EventArgs e)
    {

        backgroundWorker1.RunWorkerAsync();
    }
    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {

            string ifile = @"F:\abc.mp4";
            int i = 0;
            if (Path.GetExtension(ifile) == ".arv")
            {
                MessageBox.Show("Error!!File already Encrypted.");
                return;
            }
            string ofile = ifile + ".arv";

        a: string password = Prompt.ShowDialog();
            if (password == "")
            {
                MessageBox.Show("Password Field cannot be blank!!");
                goto a;
            }
            else if (password == null)
            {
                goto b;
            }
            int ph = password.GetHashCode();
            byte[] ia = BitConverter.GetBytes(ph);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(ia);
            byte[] phb = ia;

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] salt = new byte[] { 10, 20, 30, 40, 50, 60, 70, 80 };
            Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(password, salt);

            string cryptFile = ofile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            AesManaged AMCrypto = new AesManaged();
            AMCrypto.Key = k.GetBytes(32);
            AMCrypto.IV = k.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsCrypt, AMCrypto.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(phb, 0, 4);
            FileStream fsIn = new FileStream(ifile, FileMode.Open);

            int data;
            double counter = 1;
            while ((data = fsIn.ReadByte()) != -1)
            {
                cs.WriteByte((byte)data);
                backgroundWorker1.ReportProgress((int)((counter / fsIn.Length) * 100));
                counter++;
            }

            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
            File.Delete(ifile);
            MessageBox.Show("File Encrypted!!");
        b: ;
        }
        catch (Exception f)
        {
            MessageBox.Show(f.ToString());
        }
4

1 に答える 1