"C#" の一覧

ASP.NET3.5にて文字化け

秀丸などで、文字のエンコーディングをShift-JISなどからUTF-8へ*.aspxファイルを変更するとそれまで正常に表示できていたページも文字化けする。

原因は、BOMデータが無くなる為。Diffを見ると先頭行で相違が出る。テキストエディタがBOM対応していると違いが判らないのでちょっとハマった。

UTF8Trouble

解決方法は、メモ帳で開いて上書き保存するだけ。

CEでもWeb参照設定はできる!

そんな気合い入れたタイトルにする必要は無いんだけど、個人的にサポートされていないという思い込みから驚いたので。

CEでWeb参照ができるということで、何ができるかというとクラスライブラリなどをWebサービス化(Web参照として利用できる形態に)する事で、

  • Webアプリ
  • Windowsクライアント用アプリ
  • CE用アプリ
  • たぶんSliverlightも

あたりで、共有できる為です。具体的なメリットは?というと、COMなどを利用しなければ実現できない処理をWebサービス化する事で外部アプリから制御できるようになります。

さらに噛み砕いて言うと、プリンタ制御用のCOMや三菱のシーケンサ制御用のCOMをWebサービス化すると、プリンタ制御用ライブラリをインストールする端末をWebサービスを提供するサーバーだけにする事ができます。

今頃気付くな!という話かもしれませんが、ようやくVS2003からVS2008に移行したところなので(汗)

VS2005で作成したサービスをWindows7ではInstallutilでセットアップできない

Windows7上でVS2005を使って作成したサービスプログラムをInstallUtilでインストールしようとしたところ、

D:\SVN\ServiceTest\ServiceTest\bin\Debug>installutil ServiceTest.exe
Microsoft(R) .NET Framework Installation utility Version 2.0.50727.4927
Copyright(C) Microsoft Corporation.  All rights reserved.

トランザクションのインストールを実行中です。

インストール段階を開始しています。
D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe アセンブリの進行状態については、ロ
グ ファイルの内容を参照してください。
ファイルは D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.InstallLog にあります。
アセンブリ ‘D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe’ をインストールしていま
す。
該当するパラメータ:
   logtoconsole =
   assemblypath = D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe
   logfile = D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.InstallLog

インストール段階で例外が発生しました。
System.ComponentModel.Win32Exception: アクセスが拒否されました。

インストールのロールバックを開始しています。
D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe アセンブリの進行状態については、ログ ファイルの内容を参照してください。
ファイルは D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.InstallLog にあります。

アセンブリ ‘D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe’ をロール バックしています。
該当するパラメータ:
   logtoconsole =
   assemblypath = D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.exe
   logfile = D:\SVN\ServiceTest\ServiceTest\bin\Debug\ServiceTest.InstallLog
System.ServiceProcess.ServiceProcessInstaller インストーラのロールバック段階で例外が発生しました。
System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。
インストールのロールバック段階で例外が発生しました。この例外は無視され、ロールバックは続行します。ただし、ロールバック完了後、コンピュータは完全に元の状態に戻らない可能性があります。

ロールバックの段階が正常に完了しました。

トランザクション インストールが完了しました。
インストールが失敗し、ロールバックが実行されました。

というエラーが発生。この状態で

net  start ServiceTest

22としても「無効なサービス名です」とのこと。試しにWindowsXPで同じ作業をすると正しく動作した。

Cookieを利用した自動ログイン処理(C#)

今までVisualStudio2003で1つのWebプロジェクトだったものを、VisualStudio2005へ手動でアップグレードすると共に2つのプロジェクトへ分割してみた。

すると、それまで気になっていなかった認証処理が各プロジェクト内で必要になり、仕方なくCookieを使う事に。またCookieがあれば自動でログインするにはどうすればいいか考えた結果、Login用のWebページのPage_LoadイベントにてFormsAuthentication.RedirectFromLoginPageを使えば問題ないみたい。

Loginコントロールを使っていたので、Authenticateイベントをコールバックしないといけない?と思ったが不要だった。

Login.aspx

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Login.aspx.cs" Inherits="Login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>ログイン</title>
</head>
<body>
    <form id="login" method="post" runat="server">
        <asp:Login ID="Login1" runat="server" BackColor="#F7F6F3" BorderColor="#E6E2D8" BorderPadding="4"
            BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"
            ForeColor="#333333" DisplayRememberMe="False" OnAuthenticate="Login1_Authenticate">
            <TextBoxStyle Font-Size="0.8em" />
            <LoginButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px"
                Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284775" />
            <InstructionTextStyle Font-Italic="True" ForeColor="Black" />
            <TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" Font-Size="0.9em" ForeColor="White" />
        </asp:Login>
    </form>
</body>
</html>

Login.aspx.cs

using System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Login : System.Web.UI.Page
{

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // 初回表示時の処理
            
            [ここでCookieをチェック。]
            if ([Cookieが有効であれば])
            {
                FormsAuthentication.RedirectFromLoginPage([Cookieに格納されているユーザー名], false);
            }

        }

    }

    private void InitializeComponent()
    {

    }

    protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
    {
        e.Authenticated = false;

        if ([カスタム認証処理])
        {
            // Cookieの発行
            HttpCookie co = new HttpCookie([Cookieの格納名]);
            [Cookieへユーザー名の格納]
            Response.Cookies.Add(co);
            e.Authenticated = true;
        }

    }
}

しかし、昔のソースはいつも書き直したくなってしまい妥協点を見出して作業に取り掛かるまで時間がかかる。

i5(AS400)の特殊文字を含むカラム名の取扱い

i5(AS400)に対してODBC経由でSELECTはもちろん、INSERT,UPDATEなどのクエリも問題なく処理できるのですがプログラムのインストールとは別にIBM iSeries Access for WindowsをインストールしODBCの接続設定をしないと動作しません。しかもODBCの接続設定名も間違っていてはいけません。

そのためiSeries Access for Windowsに含まれるIBM.Data.DB2.iSeries(.Netプログラミングサポート時にインストールされる)を利用してクエリを実行するにはどうすればよいか悩んでました。

というのも、@@TESTというカラムが存在していた場合にODBCなら[@@TEST]と記述すれば問題なかったが、iSeries Access for Windowsで同じように記述するとエラーとなる。

結局、"(ダブルクォテーション)を使えばうまく行くことがわかった。実際には"@@TEST"となる。"(ダブルクォテーション)はC#上でも特殊文字なので記述が面倒だけど。

public void UpdateTest(string sValue)
{
    const string CRLF = @"\r\n";
    StringBuilder sbSql = new StringBuilder();

    sbSql.Append("UPDATE" + CRLF);
    sbSql.Append("    TESTLIB.TEST0407" + CRLF);
    sbSql.Append("SET" + CRLF);
    sbSql.Append("    \"@@TEST2\" = @TEST2" + CRLF);
    sbSql.Append("WHERE" + CRLF);
    sbSql.Append("    \"@@TEST1\"= @TEST1" + CRLF);

    try
    {
        using (iDB2Connection cn = new iDB2Connection(DataSource=192.168.xxx.xxx;USERID=(ユーザー名);PASSWORD=(パスワード);))
        {
            cn.Open();
            using (iDB2Command cmd = cn.CreateCommand())
            {
                sbSql = sbSql.Replace(CRLF, " ");
                cmd.CommandText = sbSql.ToString();
                
                Debug.WriteLine(sbSql.ToString());

                cmd.Parameters.Add("@TEST1", iDB2DbType.iDB2Char);
                cmd.Parameters.Add("@TEST2", iDB2DbType.iDB2Char);

                cmd.Parameters["@TEST1"].Value = "(更新対象レコードのキー)";
                cmd.Parameters["@TEST2"].Value = sValue;

                cmd.ExecuteNonQuery();
            }
            cn.Close();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

※AppendLineを使用していないのは、WindowsCEとソースを共有している為です。あと\は実際には円マークです。

SqlClientPermissionエラー回避方法?

型 ‘System.Data.SqlClient.SqlClientPermission, System.Data,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=
b77a5c561934e089′ のアクセス許可の要求に失敗しました。

というエラーがDataGridViewを貼りつけただけのフォームで発生した。しかも、特定の開発用PCのみ。

        private void Form1_Load(object sender, EventArgs e)
        {
#if DEBUG
            string connStr = "Server=xxx.xxx.xxx.xxx;database=master;User ID=sa;Password=xxxxx;";
#else
            string connStr = "Data Source=XXXX;Initial Catalog=master;Integrated Security=SSPI";
#endif

            string sql = "SELECT * FROM XXTBL";
            SqlConnection conn = new SqlConnection(connStr);

            SqlCommand comm = new SqlCommand(sql, conn);
            SqlDataAdapter dataadapter = new SqlDataAdapter(comm);

            DataSet ds = new DataSet();

            conn.Open();

            dataadapter.Fill(ds, "Test");

            conn.Close();
            dataGridView1.DataSource = ds;

            dataGridView1.DataMember = "Test";
        }

    }

まさかと思いながらもWindows Updateを実施すると何事も無かったように接続できるようになった。

特定のPCというのが、半年ほど休眠していたPCだったので、内部コンポーネントの組み合わせによって発生したという事で無理やり納得したつもりになる。

C#でi5(AS400)

C# 2005にて、i5(AS400)のDB2へ接続すると、アプリケーション終了時に
(名前空間 IBM.Data.DB2.iSeries を使用)
————————————————————————-
System.ObjectDisposedException はハンドルされませんでした。
Message=”セーフ ハンドルは閉じられています。”
Source=”mscorlib”
ObjectName=””
StackTrace:
場所 System.Runtime.InteropServices.SafeHandle.DangerousRelease()
場所 System.Threading.RegisteredWaitHandleSafe.Finalize()
————————————————————————-
というエラーが出る。

リソース解放漏れも絶対無いような、単純なソースにしても上記のエラーが発生した場合はiSeries Access自体にパッチが必要。最新のサービスパックは下記から。
http://www-03.ibm.com/systems/i/software/access/windows/sphist.html
サービスパックのダウンロード元がわかりにくい・・・

VC++でデバッグモードでコンパイルできなくなる

VC++2005での話。久しぶりにDebugモードでコンパイルするとこんなエラーが発生。

警告 1 warning LNK4098: defaultlib ‘LIBCMT’ は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。 Ip4Tool
エラー 2 error LNK2001: 外部シンボル “__CrtDbgReportW” は未解決です。 libcpmtd.lib

調べた結果、プロジェクトのプロパティにて

構成プロパティ>C/C++>コード生成>ランタイムライブラリ

を【マルチスレッド(/MT)】にした為らしい。
【マルチスレッド デバッグ(/MTd)】に変更する事で回避。

なんで、この箇所を変更したかというと実行時にMSVCR80.DLLが必要と言われるのを避ける為に設定しました。

プロトコル違反?

XMLを読み込むWindowsアプリケーションにて
「サーバーによってプロトコル違反が発生しました.
Section=ResponseHeader Detail=CR の後には LF を指定しなければなりません。」
というエラーが発生した。WebアプリケーションではApp.Configに

<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing=”true” />
</settings>
</system.net>

と追記すればよいらしいが、Windowsアプリケーションなので

using System.Net.Configuration;

HttpWebRequestElement hElement = new HttpWebRequestElement();
hElement.UseUnsafeHeaderParsing = true;

とした。

致命的なエラー C1902

VC++で作業を始めようとしたら、「致命的なエラー C1902」と表示されて全プロジェクトがコンパイルできない(;´Д`)
検索しても「プログラム データベース マネージャが・・・」とか意味不明。
VC++自体の修復インストールするが、変化なし。
そこでふと・・・昨日link.exeとかdumpbin.exeを実行する為にmspdb80.dllをコピーした事を思い出し、削除してみた。・・・直った。2時間返せと誰かに言いたい(´Д⊂)