- PR -

【ASP.NET】自己解凍書庫の作成について

投稿者投稿内容
ひろれい
ぬし
会議室デビュー日: 2006/03/02
投稿数: 486
お住まい・勤務地: 万博開催地
投稿日時: 2006-04-10 13:44
引用:

ぽぴ王子さんの書き込み (2006-04-10 13:21) より:
こんにちは。ぽぴ王子といいます。

すこし気になったのですが、Unlha.dllに渡すコマンドラインに間違いはないでしょうか。
ls_Commandの文字列を解釈すると
a "inFile" "outFile" *.*
になると思うのですが(便宜上inFileとoutFileはそのまま使っています)、これですと
a "D:\\test_in\\Archive" "D:\\test_out\\" *.*
のようなコマンドラインになり、Unlha.dllとしても解釈に困るような気がします。
意図したとおりに渡すには、以下のような感じではないかと。
a "inFile" "outFile*.*"
展開すると
a "D:\\test_in\\Archive" "D:\\test_out\\*.*"
このような感じで。
で、それをコードに直すと
ls_Command = "a " & Chr(34) & inFile & Chr(34) & " " & Chr(34) & outFile & "*.*" & Chr(34)
という感じになると思います。

一度試してみてください。


ぽぴ王子さん、お返事ありがとうございます。

試してみましたが、ダメでしたm(_ _)m
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2006-04-10 15:18
こんにちは。
私のほうでも少し調べてみました。
宣言部の表記にMarshalAs〜は不要かも、というかそのせいでうまくいかないのかも、という結論に達しました。
(いや、これも間違ってる可能性はありますけど)
C#しかわからない人間なのでC#で書いていますが、VBでも同じような感じだと思います。

コード:
宣言部
    [DllImport("unlha32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    private static extern int Unlha(
      int hWnd,
      String szCmdLine,
      IntPtr szOutput,
      uint dwSize
      );

実行部
      String commandline = "a -gw4 -xr1 -gm1 \\"" + inFile + "\\" \\"" + outFile + "*.*\\"";
      Unlha(0, commandline, IntPtr.Zero, 0);



ちなみに固まってしまうのは、szOutputがNothing(上の場合はIntPtr.Zero)を渡しているので、出力結果がバッファに
入らず画面上にメッセージボックスで出てしまっているのだと思います。
(サーバーサイドなので、メッセージボックスが出たりすると固まってしまいますよね?)
こちらでWindowsアプリとして作成したときは「書庫ファイルが指定されていません」というメッセージボックスが表示
されていました。

バッファを活かすようにするとしたら次のような感じでしょうか。

コード:
宣言部
    [DllImport("unlha32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    private static extern int Unlha(
      int hWnd,
      String szCmdLine,
      StringBuilder szOutput,
      uint dwSize
      );

実行部
    StringBuilder sb = new StringBuilder(300);
    String commandline = "a -gw4 -xr1 -gm1 \\"" + inFile + "\\" \\"" + outFile + "*.*\\"";
    Unlha(0, commandline, sb, (uint)sb.Capacity);



試してみてください。
ひろれい
ぬし
会議室デビュー日: 2006/03/02
投稿数: 486
お住まい・勤務地: 万博開催地
投稿日時: 2006-04-10 15:24
1箇所、間違いを見つけました。

(誤)<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)>

(正)<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)>

が、やはり結果はダメでした(;_;)

あと、先程のソースでは「inFile」と「outFile」の位置が逆でした。
修正しましたが、ダメでした。

Unlha への引数を Integer型から Long型 に変更してみましたがダメです。
クラスへの記述をやめ、イベント内で Unlha を呼んでもダメでした。

やはり権限なのかと思いましたが、「ASPNET」「IUSR_マシン名」以外に、「everyone」にもフルコントロール権限を与えましたが、やはりダメでした。

ちなみに、DllImport すると、どこに検索しにいくんでしょうか?
ひろれい
ぬし
会議室デビュー日: 2006/03/02
投稿数: 486
お住まい・勤務地: 万博開催地
投稿日時: 2006-04-10 15:45
引用:

ぽぴ王子さんの書き込み (2006-04-10 15:18) より:

こんにちは。
私のほうでも少し調べてみました。
宣言部の表記にMarshalAs〜は不要かも、というかそのせいでうまくいかないのかも、という結論に達しました。
(いや、これも間違ってる可能性はありますけど)


ぽぴ王子さん、ありがとうございます。すれ違いで申し訳ありません。
私もその点は考え、はずしてみたこともあるのですが、ダメでした。
<現在、はずしています>

引用:

ちなみに固まってしまうのは、szOutputがNothing(上の場合はIntPtr.Zero)を渡しているので、出力結果がバッファに
入らず画面上にメッセージボックスで出てしまっているのだと思います。
(サーバーサイドなので、メッセージボックスが出たりすると固まってしまいますよね?)
こちらでWindowsアプリとして作成したときは「書庫ファイルが指定されていません」というメッセージボックスが表示
されていました。

バッファを活かすようにするとしたら次のような感じでしょうか。


「書庫ファイルが指定されていません」というエラーは、私の先程のソースで「inFile」と「outFile」が逆だからだと思います。すいませんでした。

ログ出力すると、出力先にも権限設定が必要になると思いますがどこに設定すれば良いか分かりますでしょうか?
エラーの内容が分かりさえすれば、対処の仕方はあると思うのですが・・・

追記:現状、以下のようになっています。
コード:

<DllImport("UNLHA32.DLL", CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function Unlha(ByVal ll_hWnd As Long, _
ByVal ls_CmdLine As String, _
ByVal ls_OutPut As String, _
ByVal ll_Size As Long) As Integer
End Function

Dim ls_Command As String
Dim li_Return As Integer
Dim inFile As String = "D:\test_in\"
Dim outFile As String = "D:\test_out\Archive"
Dim sb As New System.Text.StringBuilder(300)

ls_Command = "a " & Chr(34) & outFile & Chr(34) & " " & Chr(34) & inFile & "*.xls" & Chr(34)
li_Return = Unlha(0, ls_Command, sb.ToString, sb.Capacity)



[ メッセージ編集済み 編集者: ひろれい 編集日時 2006-04-10 15:49 ]

[ メッセージ編集済み 編集者: ひろれい 編集日時 2006-04-10 15:50 ]
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2006-04-10 16:06
こんにちは。
私も乗りかかった船なので、もう少し調べてみます

追記された部分ですが、宣言のls_OutputをStringからStringBuilderに、
実行時のsb.ToString()をsbに変えてみてください。
ls_OutputをStringBuilderにするのは、Unlhaの出力内容をls_Outputに
保存するためで、そのためにはStringではなくStringBuilderに保存してもらう
必要があるためです(この辺の話はもっと詳しい方にしてもらった方が
いいかもしれません←あっ、逃げた)。
そうすればエラーがあったときも、sbにエラー内容が出力されるので、それ
を見ればなんとかなりそうな気がします。
…っと思ったのですが、応答が無くなるんでしたっけ。

引用:

「書庫ファイルが指定されていません」というエラーは、私の先程のソースで「inFile」と「outFile」が逆だからだと思います。すいませんでした。


「書庫ファイルが指定されていません」のエラーはMarshalAs〜を付けていた
ときに表示されたものです。たぶんUnlhaにコマンドラインがうまくわたって
いなかったのだと思われます。

サーバーサイドでは何かと原因がつかみにくいかと思いますので、一度Windows
アプリとしてミニマムコードで作成してみて、そこでUnlha32.dllの問題なのか
コーディングの問題なのか、それとも権限の問題なのかを調べてからにした方が
良いかもしれませんね。
ひろれい
ぬし
会議室デビュー日: 2006/03/02
投稿数: 486
お住まい・勤務地: 万博開催地
投稿日時: 2006-04-10 16:35
引用:

ぽぴ王子さんの書き込み (2006-04-10 16:06) より:

こんにちは。
私も乗りかかった船なので、もう少し調べてみます


ありがとうございます(^o^)

引用:

追記された部分ですが、宣言のls_OutputをStringからStringBuilderに、
実行時のsb.ToString()をsbに変えてみてください。

サーバーサイドでは何かと原因がつかみにくいかと思いますので、一度Windows
アプリとしてミニマムコードで作成してみて、そこでUnlha32.dllの問題なのか
コーディングの問題なのか、それとも権限の問題なのかを調べてからにした方が
良いかもしれませんね。


早速、Windowsアプリで試してみました。すると、エラーが出ました。

「UNLHA32 エラー報告(on UnlhaMain) コマンド指定が間違っています:'<NULL>'」

キャッチした例外には、
「オブジェクト参照がオブジェクトインスタンスに設定されていません」
とのメッセージ(ex.Message)が出ます。
これは、UNLHA32.DLL がうまく参照できていないということでしょうか。
Dllimport 以外に何かやる作業があるのでしょうか?

コード:
    <DllImport("UNLHA32.DLL", CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Function Unlha(ByVal ll_hWnd As Long, _
        ByVal ls_CmdLine As String, _
        ByVal ls_OutPut As System.Text.StringBuilder, _
        ByVal ll_Size As Long) As Integer
    End Function

        Dim ls_Command As String
        Dim li_Return As Integer
        Dim inFile As String = "D:\test_in\"
        Dim outFile As String = "D:\test_out\Archive"
        Dim sb As New System.Text.StringBuilder(300)

        Try
            ls_Command = "a " & Chr(34) & outFile & Chr(34) & " " & Chr(34) & inFile & "*.xls" & Chr(34)
            li_Return = Unlha(0, ls_Command, sb, sb.Capacity)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2006-04-10 16:48
「UNLHA32 エラー報告(on UnlhaMain) コマンド指定が間違っています:'<NULL>'」

これは画面上に表示されたメッセージでしょうか。
キャッチした例外には…ということは、上記のメッセージが表示されていて、
なおかつExceptionが発生しているのでしょうか。

とりあえずはll_hWndをLongからIntegerに戻してみてください。上記のメッ
セージはそれが原因のような気がします。

あとはうまくいったらsb.ToString()の内容も見てみるといいかもしれません。
ひろれい
ぬし
会議室デビュー日: 2006/03/02
投稿数: 486
お住まい・勤務地: 万博開催地
投稿日時: 2006-04-10 17:06
引用:

ぽぴ王子さんの書き込み (2006-04-10 16:48) より:

「UNLHA32 エラー報告(on UnlhaMain) コマンド指定が間違っています:'<NULL>'」

これは画面上に表示されたメッセージでしょうか。
キャッチした例外には…ということは、上記のメッセージが表示されていて、
なおかつExceptionが発生しているのでしょうか。

とりあえずはll_hWndをLongからIntegerに戻してみてください。上記のメッ
セージはそれが原因のような気がします。

あとはうまくいったらsb.ToString()の内容も見てみるといいかもしれません。


ぽぴ王子さん、ビンゴ! でした。
Long型から Integer型に直したところ、正常に圧縮できました。
sb.ToString() には、圧縮時の内容が書き込まれていました。

で、同じように ASP.NET(VB.NET)で修正し、実行したところ、正常に動作しました!!
ありがとうございます。本当にありがとうございます。助かりました。

原因は、ぽぴ王子さんがおっしゃられていた通り、MarshalAs の指定が必要無かったのと、HWND の型を Long型にしていたところですね。
私は、MarshalAs の指定をはずすと同時に、Integer型から Long型への変更をしてしまったため、原因が埋もれてしまっていました。

的確なご指摘で、早期解決に至りました。ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)