ラベル .NET Framework の投稿を表示しています。 すべての投稿を表示
ラベル .NET Framework の投稿を表示しています。 すべての投稿を表示

2014年4月2日水曜日

ClickOnce アプリのデバッグと、セキュリティの警告

「現在のプロジェクト設定は、プロジェクトが特定のセキュリティのアクセス許可でデバッグされることを指定しています。このモードでは、コマンドライン引数は実行可能ファイルに渡されません。デバッグを続行しますか?」


ーーー

コマンドライン引数を確かめますと、確かに指定しています。


ーーー

解決するには、XXX.csproj.userファイル中、

<EnableSecurityDebugging>false</EnableSecurityDebugging>

こちらをfalseに設定します。

ーーー

「特定のセキュリティのアクセス許可」とやらは提供されなくなりますが、そういう複雑なプロジェクトを組んでいらっしゃる方は、普通、入口を切り分けると思いますので。。。

            if (ApplicationDeployment.IsNetworkDeployed) {
// ClickOnce 起動時は、こちら
// 追加の処理…
}
else {
// それ以外 (exe ファイルの直接起動時、デバッグ時など)
// 追加の処理…
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
return;

ーーー

画面の設定手順としましては:

プロジェクトのプロパティ
→「セキュリティ」タブ
→「詳細設定」ボタン
→「このアプリケーションを選択されたアクセス許可のセットでデバッグする」 チェックを外す。

ーーー

ただし、アセンブリ参照の内容によってはこの画面まで至ることができません。その場合、ファイルの直接編集が有効です。

2012年7月12日木曜日

WinDbgで、エラー報告データを解析2(.NETfx 2.0向け)

前回の続編です。

今回は、スタックトレースを見ながら要因を追跡していきます。

WinDbgを起動します。

[File]→[Open Crash Dump...]

次の場所を開く(Windows Server 2003):
%USERPROFILE%\Local Settings\Application Data\PCHealth\ErrorRep\QSignoff

8C80969E.cab等、cabを開きます。

~~~

打ち込みます(.NET Framework 2.0対応のため)

.load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll

結果:
0:002> .load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll

------------------------------------------------------------ 
sos.dll needs a full memory dump for complete functionality. 
You can create one with .dump /ma <filename>
------------------------------------------------------------ 

~~~

打ち込みます。発出された例外を表示。

!pe

結果:
0:002> !pe
Exception object: 09fb423c
Exception type: System.IO.IOException
Message: 指定されたネットワーク名は利用できません。
InnerException: <none>
StackTrace (generated):

SP       IP       Function
00A4FB64 799D0B09 mscorlib_ni!System.IO.__Error.WinIOError(Int32, System.String)+0x75c9f9
00A4FBC0 79A0CE90 mscorlib_ni!System.IO.FileStream.WriteCore(Byte[], Int32, Int32)+0x7221a0
00A4FBE0 792EACD2 mscorlib_ni!System.IO.FileStream.FlushWrite(Boolean)+0x22
00A4FBF0 792EB7F7 mscorlib_ni!System.IO.FileStream.Dispose(Boolean)+0x57
00A4FC20 792CA80B mscorlib_ni!System.IO.FileStream.Finalize()+0x1b

StackTraceString: <none>
HResult: 80070040

考察:
  • FileStreamがExceptionの発生源になっています。
  • FileStreamは、ファイル名を持っているはずなので、それを探ってみたいと思います。

~~~

打ち込みます(スタックトレースを表示します)

!CLRStack -p

結果:

0:002> !CLRStack -p
OS Thread Id: 0x2198 (2)
ESP       EIP 
00a4fac0 7c97845c [HelperMethodFrame: 00a4fac0] 
00a4fb64 799d0b09 System.IO.__Error.WinIOError(Int32, System.String)
  PARAMETERS:
   errorCode = <no data>
   maybeFullPath = <no data>

00a4fbc0 79a0ce90 System.IO.FileStream.WriteCore(Byte[], Int32, Int32)
  PARAMETERS:
   this = <no data>
   buffer = <no data>
   offset = <no data>
   count = <no data>

00a4fbe0 792eacd2 System.IO.FileStream.FlushWrite(Boolean)
  PARAMETERS:
   this = 0x010a3550
   calledFromFinalizer = <no data>

00a4fbf0 792eb7f7 System.IO.FileStream.Dispose(Boolean)
  PARAMETERS:
   this = 0x010a3550
   disposing = 0x00000000

00a4fc20 792ca80b System.IO.FileStream.Finalize()
  PARAMETERS:
   this = <no data>

考察:
  • FileStreamのthisポインタが露出しています。
  • FileStreamのthisポインタから、インスタンスの内容物を解剖します。
~~~

打ち込みます。FileStreamのthisポインタをダンプします。

!do 0x010a3550

結果:
0:002> !do 0x010a3550
Name: System.IO.FileStream
MethodTable: 793051f4
EEClass: 790df0f0
Size: 80(0x50) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79330888  400018a        4        System.Object  0 instance 00000000 __identity
7992db14  4001b70        8 ...ream+ReadDelegate  0 instance 00000000 _readDelegate
7992dba0  4001b71        c ...eam+WriteDelegate  0 instance 00000000 _writeDelegate
7931c008  4001b72       10 ...ng.AutoResetEvent  0 instance 00000000 _asyncActiveEvent
79332eb8  4001b73       14         System.Int32  1 instance        1 _asyncActiveCount
7932e968  4001b6f      574     System.IO.Stream  0   shared   static Null
    >> Domain:Value  00161ee0:0109bab4 <<
793336dc  4001bfb       28        System.Byte[]  0 instance 010a4a90 _buffer
79330c6c  4001bfc       2c        System.String  0 instance 010a35a0 _fileName
79304738  4001bfd       44       System.Boolean  1 instance        0 _isAsync
79304738  4001bfe       45       System.Boolean  1 instance        0 _canRead
79304738  4001bff       46       System.Boolean  1 instance        1 _canWrite
79304738  4001c00       47       System.Boolean  1 instance        1 _canSeek
79304738  4001c01       48       System.Boolean  1 instance        0 _exposedHandle
79304738  4001c02       49       System.Boolean  1 instance        0 _isPipe
79332eb8  4001c03       34         System.Int32  1 instance        0 _readPos
79332eb8  4001c04       38         System.Int32  1 instance        0 _readLen
79332eb8  4001c05       3c         System.Int32  1 instance     4096 _writePos
79332eb8  4001c06       40         System.Int32  1 instance     4096 _bufferSize
7932ec38  4001c07       30 ...es.SafeFileHandle  0 instance 010a3640 _handle
793324f8  4001c08       18         System.Int64  1 instance 111877 _pos
793324f8  4001c09       20         System.Int64  1 instance -1 _appendStart
79304738  4001bf9      adc       System.Boolean  1   shared   static _canUseAsync
    >> Domain:Value  00161ee0:1 <<
79334198  4001bfa      57c ...ompletionCallback  0   shared   static IOCallback
    >> Domain:Value  00161ee0:0109d148 <<

考察:
  • _fileName が 010a35a0 を指しています。
~~~

打ち込みます。

!do 010a35a0


結果:
0:002> !do 010a35a0 
Name: System.String
MethodTable: 79330c6c
EEClass: 790ed65c
Size: 158(0x9e) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: \\192.168.2.119\share\DD7Backup\FDSET\DD7Backup遠方(11日)(夜)(Set1)(遠).log
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332eb8  4000096        4         System.Int32  1 instance       71 m_arrayLength
79332eb8  4000097        8         System.Int32  1 instance       70 m_stringLength
7933194c  4000098        c          System.Char  1 instance       5c m_firstChar
79330c6c  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  00161ee0:01091198 <<
7933189c  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  00161ee0:01091714 <<

考察:
  • 知りたかった情報が露出しました。

「指定されたネットワーク名は利用できません」の発生原因は、
バックアップのログファイルを書き込んでいる最中に、
NASがダウンしたからだ、と考えられます。


※ google-code-prettifyを組み込み、表示を最適化しました。

参考:SOS.dll (SOS デバッガー拡張)

2012年6月5日火曜日

私製INetCfg

INetCfgを使用して得られる、バインド情報を可視化してくれるプログラムを書いています。


この図を見ていますと、INetCfgの構造が把握し易くなります。

背景としましては:
  • ウィルス対策ソフトに不備が有る! 事が有ります。
  • その不備によって、Windowsが起動する際に、ネットワークアダプタを全部隠してしまう場合が有ります。
  • 仮説としましては、バインド情報を破壊しているのではないか、という事。
  • その際に、現状のバインド情報を可視化し、情報収集に役立てよう、という算段です。

2012年4月21日土曜日

~は動作を停止しました (CLR20r3:MDbg.exe編)

初めての方は、前編をご覧ください。

今回は、
.NET SDK コマンド ライン デバッガ (MDbg.exe) を用いて進めていきます。

.NET Framework 2.0 SDK等、SDKを入れていないと使えません。納品先等で活用したい場合は、持ち運ぶ等の工夫をします。

使用の際の注意点を:

Error: デバッグ対象とデバッガが互換性のないプラットフォームにあるので、操作に失敗しました。 (HRESULT からの例外: 0x80131C30)

32ビット版・64ビット版の区別、つまりPlatformの区別が有ります。

64ビット版(x64)の.NET Frameworkで動いているプログラムにアタッチするには、64ビット版のSDKに含まれているMDbg.exeを使います。

つまり「デバッガのPlatform=アタッチ先のPlatform」となるように、Platformを合わせる必要が有ります。

起動:

C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin>Mdbg.exe

MDbg (Managed debugger) v2.0.50727.42 (RTM.050727-4200) started.
Copyright (C) Microsoft Corporation. All rights reserved.

For information about commands type "help";
to exit program type "quit".

mdbg>

a」コマンドで、アタッチ可能なプロセス一覧を表示します。

mdbg> a
Please choose some process to attach
Active processes on current machine:
(PID: 968) C:\Proj\FNF\bin\Debug\FNF.exe
        (ID: 1) FNF.exe
(PID: 4020) C:\Proj\FNF\bin\Debug\FNF.vshost.exe
        (ID: 1) FNF.vshost.exe


a 968」を、実行。968番にアタッチします。

mdbg> a 968
[p#:0, t#:0] mdbg>


ちょっとプロンプトが変わりました。

p -d」で、デバッガ変数の一覧を表示します。例外落ちで停止しているので、$exが現れています。

[p#:0, t#:0] mdbg> p -d
$ex=System.ComponentModel.Win32Exception
$thread=System.Threading.Thread


p $ex」で、例外情報を見ます。

[p#:0, t#:0] mdbg> p $ex
$ex=System.ComponentModel.Win32Exception
        nativeErrorCode=2
        _className=<null>
        _exceptionMethod=<null>
        _exceptionMethodString=<null>
        _message="指定されたファイルが見つかりません。"
        _data=<null>
        _innerException=<null>
        _helpURL=<null>
        _stackTrace=array [192]
        _stackTraceString=<null>
        _remoteStackTraceString=<null>
        _remoteStackIndex=0
        _dynamicMethods=<null>
        _HResult=-2147467259
        _source=<null>
        _xptrs=0
        _xcode=-532459699


情報が見えてきました。

w」で、スタックトレースを見ます。

[p#:0, t#:0] mdbg> w
Thread [#:0]
*0. System.Diagnostics.Process.StartWithShellExecuteEx (source line information unavailable)
 1. System.Diagnostics.Process.Start (source line information unavailable)
 2. FNF.Program.Run (Program.cs:13)
 3. FNF.Program.Main (Program.cs:9)


Process.Startの中でトラぶっているのが判ります。

これで大体の原因は判ると思います。

それで、今回の例外落ちプログラムのソースコードは次のようになっています:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace FNF {
    class Program {
        static void Main(string[] args) {
            new Program().Run();
        }

        private void Run() {
            Process.Start(Guid.NewGuid().ToString("N") + ".exe");
        }
    }
}

~は動作を停止しました (CLR20r3編)

納品先などで、.NET Framework用プログラムが例外落ちした際の、例外情報の取得方法について考えてみたいと思います。

例外落ちの際、次のような画面が表示されると思います。



「問題の詳細」を一見しても、中身が判らないことが多いです:
---
説明:
  Stopped working

問題の署名:
  問題イベント名:                          CLR20r3
  問題の署名 01:                         fnf.exe
  問題の署名 02:                         1.0.0.0
  問題の署名 03:                         4f921d53
  問題の署名 04:                         System
  問題の署名 05:                         2.0.0.0
  問題の署名 06:                         4ea78da2
  問題の署名 07:                         3aae
  問題の署名 08:                         288
  問題の署名 09:                         System.ComponentModel.Win32
  OS バージョン:                          6.1.7601.2.1.0.272.33
  ロケール ID:                             1041

オンラインのプライバシーに関する声明をお読みください:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0411

オンラインのプライバシーに関する声明が利用できない場合は、プライバシーに関する声明をオフラインでお読みください:
  C:\Windows\system32\ja-JP\erofflps.txt
---

「System.Component.Win32Exceptionが発生したのか」程度は読み取ることができます。

イベントビューアで確認しても、似たような情報しか無いので、詳細に行き着きません。

そこで、プログラム終了する前に、デバッガをアタッチし、原因を追究します。

ここからは、デバッガごとに記事を分けたいと思います:

MDbg.exe

2012年1月18日水曜日

Reg-Free COM on .NET 2.0の実践

.NET 2.0 C#から、MFCで作ったようなCOM DLLを、レジストリに登録しないで呼び出す方法を、備忘したいと思います。
MFCにはCOleDataSourceクラスとか、OLEと連携する上で役立つクラスが多数有ります。

これらを.NETだけで実現しようとすると、膨大な手数になります。

C#でドラッグ・アンド・ドロップできるアプリ(バックアップの復元ソフト)を作る際に、活用できました。

具体的な手法は又の機会に譲るとして、ここでは要素技術のみを列挙いたします:

Handling Shell Data Transfer Scenarios
  FILEDESCRIPTOR
  FILECONTENTS
IAsyncOperation

Registration-Free Activation of COM Components: A Walkthrough
  Assembly Manifests

手順:

マニフェストファイルを用意します。紫色の部分を変えていきます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
      type="win32"
      name="DiffBkRestore"
      processorArchitecture="x86"
      version="1.0.0.0"
      />
  <file name="VFCopy.dll">
    <comClass clsid="{8FADBC22-CF67-4AEE-9B67-451C106B187E}" threadingModel="Apartment" />
  </file>
</assembly>


mt.exeでexeの中に入れ込みます。外付けのmanifestファイルでは、Reg-Freeが機能しませんでした。
紫色の部分を変えます。

mt.exe -manifest DiffBkRestore.manifest -outputresource:bin\x86\release\DiffBkRestore.exe;#1

私はNSISでセットアップを構築しています。NSISのビルド実行時にmt.exeが動くように作りこみするのも絶妙な手でしょう。

!system '"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\Bin\mt.exe" -manifest DiffBkRestore.manifest -outputresource:bin\x86\release\DiffBkRestore.exe;#1' = 0
;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\mt.exe
;C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools\Bin\mt.exe
;C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\Bin\mt.exe

mt.exeのパスが大量にメモってあるのは、環境が変わった際に探しやすいようにする為です。

where mt.exeで探してきました。

NSISでは、!systemでシェルコマンドを実行できます。失敗したらビルドが停止するように、" = 0"を最後に足しています。指定しないと失敗しても止まりません→ほぼ確実に見落します。

後、注意点として、processorArchitecturex86等に固定しないといけません。

.NETのアセンブリは、x86でビルドしましょう。

Any CPUでビルドしてしまうと、64ビットWindowsでは、x64で起動してしまいます。これではx86で作ったCOM DLLを読み込みできません。具体的には、BadImageFormatExceptionが発生すると思います。