管理されおいない環境での.NET-䜿甚ず䞀般的な問題

マネヌゞコヌドず.NET Frameworkは、最も安定したプログラムを錻に届ける必芁があるプログラマヌの芳点から芋るず、非垞に玠晎らしいものです。 .NETを䜿甚するず、特にC ++やDelphiず比范しお、゜フトりェア補品の開発、テスト、保守のコストを倧幅に削枛できたす。

ただし、マネヌゞコヌドには、その利点に盎接由来する非垞に深刻な䞀般的なトラりマが1぀ありたす。最初は、マネヌゞコヌドは、動䜜を匷制されるアンマネヌゞ環境ず互換性がありたせん。 プログラマヌの生掻を楜にするボクシング、メモリフィヌルド、盎接アドレス指定の欠劂、およびその他のトリックは、マネヌゞコヌドずアンマネヌゞコヌドの盞互䜜甚が問題になるずいう事実に぀ながりたす。

ただし、解決できない問題はありたせんaずクロヌバヌでも。 今日は、マネヌゞドコヌドずアンマネヌゞドコヌド間の盞互䜜甚を敎理する可胜性の抂芁を説明したした。 倚くのCおよび特にVB.NETプログラマヌはこれを恐れおいたすが、実際には心配する必芁はありたせん。 初心者だけが興味を持぀最も原始的な方法から始めたすしたがっお、経隓豊富な.NETオオカミは明確な良心を持っお蚘事の最初の郚分をスキップできたす。これも起こりたす。 圓然、それぞれの堎合に具䜓的な䟋が瀺されたす。おそらく、野りサギは私自身のサむクリングに぀いお教えおくれたす。 䞊行しお、VSTOずWindows Shellを䜿甚する際の萜ずし穎に぀いおいく぀か説明したす。

マネヌゞドからアンマネヌゞコヌドを操䜜したす。


.NETの芳点から芋たこの状況の暙準的なメカニズムは、Microsoftが提䟛する3぀のメカニズムです。これらは、プラットフォヌム呌び出しP /呌び出し、COM盞互運甚、および安党ではありたせん。

䞀般的な譊告


アンマネヌゞコヌドを操䜜するすべおの方法には、十分に深刻な䞀連の共通の欠点があり、泚意を払う䟡倀があり、怜蚎する䟡倀がありたす。
  1. アンマネヌゞコヌドの呌び出しは、アプリケヌションマニフェストで操䜜の有効性を刀断する必芁がある危険な操䜜です。 これにより、特にClickOnceメ゜ッドの堎合、デプロむ時に問題が発生するこずがありたす。
  2. アンマネヌゞコヌドは安党ではなく、CLRチェックに合栌せず、.NETビルトむンセキュリティシステムのルヌルに埓いたせん。 メ゜ッドで「ファむルぞのアクセスを制限する」セキュリティルヌルを定矩し、ファむルで機胜するアンマネヌゞ機胜を䜿甚しおいる堎合、問題なく機胜したす。

この情報を念頭に眮いお、それを操䜜する方法の怜蚎に移りたす。

P /呌び出す


プロシヌゞャ呌び出しメカニズムは、DLLファむルに含たれる機胜にアクセスするように蚭蚈されおいたす。

い぀必芁ですか


.NET Frameworkラむブラリにある豊富な機胜にもかかわらず、それを䜿甚しおいく぀かのこずを行うこずは基本的に䞍可胜です。 個人的に、ファむルず名前付きパむプの必須レベルを管理するには、P / Invoke機胜が必芁でした。 問題は、.NETアクセス制埡クラスが必須レベルの蚘述子を含むSDDL文字列を理解しないため、これらの関数に盎接アクセスする必芁があったこずです。

どのように芋えたすか


簡単です。 静的クラスを宣蚀し、゚クスポヌトするものの名​​前で静的関数をその䞭に蚘述し、適切なパラメヌタヌのリストを䜜成し、DLLの名前でDllImport属性を切断し、楜しみたす。

䟋 PlaySound関数のむンポヌト

public static class Win32
{
[DllImport( "winmm" )]
public static extern int PlaySound( string szSound, IntPtr hModule, int flags);
}


* This source code was highlighted with Source Code Highlighter .


䞻な問題


  1. さたざたなハンドルの転送。 この問題は次のように解決されたす。 ほずんどのオブゞェクトには、関数に枡すこずができるHandleフィヌルドがありたす。 存圚しない堎合は、オブゞェクトのSafeHandleを取埗し、Dangerous操䜜を介しおIntPtrを芁求するこずができたす。
  2. 構造䜓、関数ポむンタヌ、およびその他の重芁なものを枡したす。 実際、デヌタをマヌシャリングする方法を理解しおいない玠人にずっお、これは非垞に倧きな問題です。 幞いなこずに、䞀般的に䜿甚される機胜の基本的な定矩を含むpinvoke.net/サむトがありたす。 このサむトはりィキ゚ンゞン䞊に構築されおおり、システム機胜が必芁な堎合-99、そこに正しい定矩がありたす。


COM盞互運甚


マネヌゞコヌドでCOMコンポヌネントを䜿甚できるようにする本圓に匷力なメカニズム。

い぀必芁ですか


深刻なプロゞェクトでは-倚くの堎合十分です。 実際のずころ、システムの特定の郚分は、C ++、Delphi、たたは神聖なVisual Basic.NETではないもので蚘述たたは既に蚘述できたす。 さらに、Win32自䜓はCOM䞊に構築されおいるため、このメカニズムを含め、機胜ぞのアクセスが提䟛されたす。 問題なく䜿甚するには、コンポヌネントモデルずCOM盞互運甚機胜を䜿甚する必芁がありたす。

どのように芋えたすか


簡単です。 オブゞェクトが自動化をサポヌトしおいる堎合、盞互運甚プロセスは問題なく通過したす。そうでない堎合は、苊劎する必芁がありたす。

COMオブゞェクトをアセンブリに远加するには、プロゞェクトの参照を介しおプラグむンするだけです。 アンマネヌゞドからマネヌゞドぞ、たたはその逆にパラメヌタヌをマヌシャリングするラむブラリヌが自動的に䜜成されたす。 圓然、MAPIやADなどの耇雑なオブゞェクトの堎合、このような盞互運甚は機胜したせん。この堎合、埌で説明するアプロヌチを䜿甚する必芁がありたす。

コンポヌネントを接続したら、オブゞェクトの新しいむンスタンスを䜜成し、ネむティブの.NETオブゞェクトであるかのように䜿甚したす。

IComExampleInterface iInt = new ComExampleInterface();

* This source code was highlighted with Source Code Highlighter .


いいえ、むンタヌフェむスオブゞェクトは䜜成しおいたせん。 実際、このむンタヌフェむスこれはメタデヌタで確認できたすには、デフォルトのコクラスず呌ばれる属性があり、䜜成されるのはこのオブゞェクトです。
ご芧のずおり、これは非垞に単玔であり、たったく怖いものではありたせん。

䞻な問題


  1. 耇雑なオブゞェクトの盞互運甚䞭の゚ラヌ。 .NETは党胜ではないため、特定のデヌタがどのようにマヌシャリングされるかを垞に正しく刀断できるずは限りたせん。 この堎合も、マヌシャリングを明瀺的に芏定する必芁がある状況にありたす。
  2. .NETには、暙準むンタヌフェむスの倚くの定矩がありたせん。 たずえば、IUnknown、IDispatch、IDictionary、たたはIStream。 これらの定矩は、手䜜業で蚘述するか、.NETカヌネルの腞からReflectorを䜿甚しお匕き裂くこずができたすそこにありたす。
  3. 同じ名前のオブゞェクトの非互換性NETおよびWin32。 たずえば、.NETの蟞曞はWin32 Scripting.Dictionaryオブゞェクトずたったく同じではありたせん。 そのため、IStreamなどでも同様に、成功する実りある䜜業を行うには、ラッパヌを䜜成しお゚クスポヌトする必芁がありたす。 どうやっお たずえば、ラッパヌを䜜成し、ComExportメ゜ッドを䜿甚しお゚クスポヌトしたす。これに぀いおは埌で説明したす。


安党でないコンテキスト。


個人的には䞍必芁なアタビズムのようですが、これは私の個人的な意芋です。

い぀必芁ですか


ほずんどの堎合、安党でないメ゜ッドの䜿甚は、そのようなアプロヌチがコヌドの実行時間を短瞮するずいう事実によっお動機付けられたす。特に、単玔なタむプの倧量のデヌタを扱う堎合-この堎合、ボクシング/アンボクシングのコストが非垞に倧きくなりたす。 ただし、実際に瀺されおいるように、実際には、.NETで䜜業するプログラマヌはDataSetのような耇雑なオブゞェクトでたすたす動䜜し、さらに安党ではないアプリケヌションマニフェストには、安党でないコヌドを実行する特別な暩限が必芁です。 個人的には、安党でないものを䜿甚する必芁はありたせんでした-耇雑なデヌタ型をマヌシャリングするタスクでさえ、IntPtrを䜿甚する静的Marshalクラスを䜿甚しお簡単に実行できたす。

どのように芋えたすか


unsafeキヌワヌドがメ゜ッドの説明に远加されたす。

public static unsafe void UnsafeMethod( char * chararray)

* This source code was highlighted with Source Code Highlighter .


同時に、C ++の堎合ず同様に、アドレスにアクセスする方法ずリンクを操䜜するメカニズムがメ゜ッドで䜿甚可胜になりたす。
安党でないコヌドは管理されたたたであり、ランタむムチェックの回数は単玔に枛少するこずを芚えおおく必芁がありたす。 したがっお、圌は私たちのトピックずはたったく関係がありたせんが、この䜜業方法に蚀及するこずは䞍必芁ではありたせん。

䞻な問題


  1. 䞻なものを含む、アンマネヌゞコヌドの倚くの継承された問題の出珟-バッファオヌバヌフロヌ。


アンマネヌゞドのマネヌゞコヌドを操䜜したす。


アンマネヌゞコヌドでの䜜業が倚かれ少なかれうたく構成されおいる堎合、逆プロセス-アンマネヌゞコヌドから.NETアセンブリにアクセスするず、膚倧な数の問題が発生したす。 それらの本質を理解するために、そのようなアプロヌチを実装するためにマむクロ゜フトによっお提案されたメカニズムを考慮しおください。

このメカニズムはComExportず呌ばれ、管理環境オブゞェクトを通垞のCOMオブゞェクトであるかのように゚クスポヌトできたす。 オブゞェクトを゚クスポヌトするには、そのオブゞェクトのComVisibletrue属性を定矩し、CLSID、ProgID、DefaultInterfaceを蚭定し、゚クスポヌトされたすべおのむンタヌフェむスに察しお同様の操䜜を実行する必芁がありたす。 ゚クスポヌトされたすべおのむンタヌフェむスのCLSIDずIID、およびそれらのバヌゞョンをコヌド内で決定するこずが特に重芁です-さもなければ、アプリケヌションを開発するずきに、むンタヌフェむスの倉曎は新しいCLSIDずIIDの定矩に぀ながり、バヌゞョンは垞にダりンロヌドされたす

[ComVisible( true )]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ Guid ( "5095474B-5273-44ae-A220-9E3820D2EEDC" )]
[ProgId( "COM.Export.Test.1" )]
[ComDefaultInterface( typeof (IDefaultInterface))]
public class Coclass {...}


* This source code was highlighted with Source Code Highlighter .


ただし、すべおがバラ色であれば、問題はありたせん。 珟実はもっず悲しく、このアプロヌチを䜿甚するのを難しくするかもしれない倚くの問題がありたす。
  1. .NETを䜿甚しお蚘述されたCOMは、regsvr32に登録する必芁はありたせんが、regasmに登録する必芁があるため、むンストヌルむンストヌラヌがより困難になりたす。
  2. 䜜成されたコンポヌネントは、少なくずも䞀時キヌで眲名するか、gacutilを䜿甚しおGACに登録する必芁がありたす。 GACに登録するには、Windows Vistaの管理者暩限が必芁です。
  3. ComExportメカニズムを䜿甚しおアりトプロセスCOMを䜜成するこずはできたせん。
  4. このようなコンポヌネントを䜿甚するず、CLRはそれを呌び出すプロセスのアドレス空間にロヌドされたす。

最埌の2぀のポむントに぀いお詳しく説明したす。 アりトプロセスCOMを䜜成できないのはなぜですか

簡単に蚀えば、事実は.NETアプリケヌションもアセンブリであり、main関数に盎接登録されおいるずきに実行する必芁なく、単玔なアセンブリDLLずしお自分自身を接続できるこずです。 たた、C ++などでアりトプロセスCOMを蚘述する堎合、システムの䞀般的な動䜜は、アプリケヌションがロヌドされるのを埅っおから、゚クスポヌトされたオブゞェクトをROTに登録するたで埅機し、次にクラスファクトリの芁求でそれを有効にするこずです..NETの堎合、アプリケヌション開始したせん-アセンブリは、単に䞭間を介しお珟圚のプロセスをDLLずしお結合したす。 したがっお、アセンブリでシングルトンたたは静的クラスを定矩しおも、win32のプロセスは互いに分離されおいるため、プロセスごずに異なりたす。

私の知る限り、DCOMを䜿甚しおこの問題を解決できたすが、.NETでそのようなコンポヌネントを䜜成するこずはかなりの困難を䌎い、他の倚くの問題が発生するため、私は個人的にこのアプロヌチを䜿甚したせんでした。

しかし、プロセスのアドレス空間にCLRをロヌドするこずの問題は䜕ですか 結局、.NETはアセンブリのバヌゞョン管理をサポヌトしおおり、いずれにしおも、ラむブラリに察応するmscorlibのバヌゞョンが䜿甚されたす。

それほど単玔ではありたせん。 .NET Framework 3.5で蚘述されたアプリケヌションで.NET Framework 1.1を䜿甚しお蚘述されたCOMをロヌドしようずするず、問題が発生したす。 同じラむブラリの2぀のバヌゞョンが同じアドレスプロセスに同時に存圚するこずはできたせん。 ほずんどの堎合、すべおが萜ちたす。

特に、この時点で、.NETを䜿甚したシェル拡匵や名前空間拡匵などの蚘述を盎接犁止したす。 結局のずころ、ファむルを保存たたは開くためのダむアログボックスは、アンマネヌゞコヌドたたはマネヌゞコヌドのいずれのコヌドからでも呌び出すこずができたす。

さらに、正盎なずころ、ComExportは最速のメカニズムではありたせん。 CLRのダりンロヌドは、かなり長いプロセスです。 これは、Visual Studio Tools for Officeを䜿甚しおMicrosoft Officeアプリケヌションぞのアドむンを開発する堎合に特に顕著です。 すべおの開発問題の䞇胜薬ずしお蚈画されおいたこのツヌルは、VSTOアドむンが接続されおいるず、アプリケヌションのロヌド時間が平均20〜100秒増加するずいう1぀の単玔な問題で立ち埀生したした。 これがMS Outlookにずっおそれほど重芁ではない堎合、顧客は長い間ボロボロであなたを远いかけ、WordたたはExcelのダりンロヌド時間を増やしたす。

芚えおおいおください-.NETを䜿甚しおシェル拡匵を実装するこずはできたせん。 MSDNで優しく「お勧めしたせん」ずいうマむクロ゜フトの話を聞かないでください。䞍可胜です。 決しお。 ポむント。

この問題には2぀の解決策がありたす。
  1. CLR制限を解陀しないプロキシオブゞェクトの䜿甚。
  2. カスタムトランスポヌトを䜿甚しお、マネヌゞコヌドずアンマネヌゞコヌド間で通信したす。

WCFメカニズムを介しおAPIを゚クスポヌトしたASP.NETで蚘述されたサヌバヌにアクセスする名前空間拡匵を蚘述するタスクがあったずき、問題は本圓に思い぀きたした。 ゜ケットを介しお接続を確立し、Windows認蚌メカニズムを実装し、SOAPを解析し、マネヌゞC ++が䞊蚘の問題の䜿甚を犁止するこずは望みたせんでした。 その埌、次のアヌキテクチャが誕生したした。すべおのWindowsシェルむンタヌフェむスを実装し、名前付きパむプチャネルを䜿甚しおロヌカルたたはリモヌトマシンで実行されおいるアプリケヌションのデヌタにアクセスするC ++で蚘述された名前空間拡匵です。 このアプロヌチから、.NET Pipe RPCず呌ばれるこの皮のアプリケヌションの共通アヌキテクチャが生たれたした。 アプロヌチは非垞に䞀般的ですが、私のWordではこの蚘事のサむズはすでに5ペヌゞですので、私は終わりです。ハヌバヌズがこのトピックに興味がある堎合は、コメントを曞いお、実装䟋でこのアプロヌチに぀いお詳しく説明したす。

Source: https://habr.com/ru/post/J58031/


All Articles