{"id":713,"date":"2020-11-27T11:48:08","date_gmt":"2020-11-27T16:48:08","guid":{"rendered":"https:\/\/badecho.com\/?p=713"},"modified":"2020-11-27T11:48:11","modified_gmt":"2020-11-27T16:48:11","slug":"nativemethods-in-dotnet-5","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/","title":{"rendered":"P\/Invokes, NativeMethods, and CA1060 in .NET 5.0"},"content":{"rendered":"\n<h2>Are NativeMethods-Styled Classes Needed in .NET 5.0?<\/h2>\n\n\n\n<p>Hello everyone. If you haven&#8217;t heard the news, <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-5-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">.NET 5.0 is now upon us<\/a>. At the time of writing, it&#8217;s the newest of the new, and it is the latest entry in Microsoft&#8217;s rather confusing (if you stop paying attention for any time at all) versioning and release strategy for its .NET technologies.<\/p>\n\n\n\n<p>After all the work that has been done on the .NET Core side of things, it seems like this is Microsoft&#8217;s official christening of their successor to the .NET Framework. So, anyone working on anything new, or anything wanting support in the distant future, will probably be trying it out.<\/p>\n\n\n\n<p>Since its release has coincided with a number of efforts I&#8217;m making in the creation of an <a href=\"https:\/\/badecho.com\/index.php\/what-is-omnified\/\" target=\"_blank\" rel=\"noreferrer noopener\">Omnified<\/a> technology stack, I made sure to switch to it right away so I could start working with it. I&#8217;ve been buried in too much assembly code and older .NET Framework application code as of late, so I had a lot of makeup learning to do in order to start to fully grasp all the changes that came with .NET Core development.<\/p>\n\n\n\n<p>One thing I became familiar with rather quickly was the new way that code analysis was being done, in particular the new <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/code-quality\/roslyn-analyzers-overview?view=vs-2019\" target=\"_blank\" rel=\"noreferrer noopener\">Roslyn analyzers<\/a> that ship with the .NET 5.0 SDK.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"366\" height=\"113\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Analyzers.png\" alt=\"Shows a bit of a Solution Explorer window displaying a project named Statsplash with the Dependencies and Analyzers folders expanded.\" class=\"wp-image-723\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Analyzers.png 366w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Analyzers-300x93.png 300w\" sizes=\"(max-width: 366px) 100vw, 366px\" \/><figcaption>Goodbye FxCop &#8212; Hello design-time code analysis.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Many of the rules are, for some reason, essentially disabled by default. I enabled them so I could see (with masochistic glee) what would be flagged. Not long after, I get hit with the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CA1060: Move pinvokes to native methods class<\/code><\/pre>\n\n\n\n<p>Right. Of course! I&#8217;ve always put my P\/Invoke declarations into a NativeMethods-styled class. But I didn&#8217;t this time, with a new project targeting .NET 5.0, for reasons which caused me to be surprised to see it being flagged by Code Analysis. It was my belief that this practice would now be null and dead with the latest .NET.<\/p>\n\n\n\n<p>Why did I think this way? We&#8217;ll get to my reasoning in a bit. First, let&#8217;s just quickly go over what <strong>CA1060 <\/strong>is and what the whole NativeMethods rigmarole is all about.<\/p>\n\n\n\n<h2>No Native Methods Outside of NativeMethods!<\/h2>\n\n\n\n<p>If we want to call into some unmanaged code, we need to make use of P\/Invoke, also known as Platform Invocation Services, via the use of a the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.dllimportattribute?view=net-5.0\" target=\"_blank\" rel=\"noreferrer noopener\">DllImportAttribute<\/a>. If any methods decorated with this attribute exist in your code outside of a class named either <strong>NativeMethods<\/strong>, <strong>SafeNativeMethods<\/strong>, or <strong>UnsafeNativeMethods<\/strong>, you will trigger a <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fundamentals\/code-analysis\/quality-rules\/ca1060\" target=\"_blank\" rel=\"noreferrer noopener\">CA1060 Code Analysis warning<\/a>.<\/p>\n\n\n\n<p>The recommendation to corral the P\/Invoke methods into one of these classes is mainly driven by <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/framework\/misc\/code-access-security\" target=\"_blank\" rel=\"noreferrer noopener\">Code Access Security<\/a> concerns. If operating in a CAS environment, .NET code can only execute unmanaged code if it has the <strong>UnmanagedCode<\/strong> permission.<\/p>\n\n\n\n<p>Ensuring that a particular caller has this permission requires a full stack walk when the P\/Invoke code is called. This can be expensive in terms of performance. <\/p>\n\n\n\n<p>The way to get around this hit to performance is through the use of the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.security.suppressunmanagedcodesecurityattribute?view=net-5.0\" target=\"_blank\" rel=\"noreferrer noopener\">SuppressUnmanagedCodeAttribute<\/a>. Throwing this on a class causes the permission check to no longer occur, avoiding the stack walk. It will also basically allow for even potentially untrusted code to be able to call these methods.<\/p>\n\n\n\n<p>So, in order to make it clear which code is using this attribute, with all of its potential security implications, the NativeMethods triad of classes was born.<\/p>\n\n\n\n<p>I tend to ignore what Microsoft says, and look at <em>what they do<\/em>. And indeed, you will find throughout the (soon to be old) .NET Framework class libraries a faithful following of this practice.<\/p>\n\n\n\n<h2>But Must I Use NativeMethods-Styled Classes with .NET 5.0?<\/h2>\n\n\n\n<p>No. It&#8217;s a practice that will eventually fade into antiquity. There simply is no reason to do so anymore. And that&#8217;s because of a big change that came with .NET Core: <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/porting\/net-framework-tech-unavailable\" target=\"_blank\" rel=\"noreferrer noopener\">the dropping of Code Access Security<\/a>.<\/p>\n\n\n\n<p>I always viewed Code Access Security as a fine example of overengineering that resulted in a silly amount of unnecessary work and consideration, and I&#8217;m simply overjoyed to see Microsoft chucking it out the window.<\/p>\n\n\n\n<p>The purpose behind the different NativeMethods classes was <em>entirely<\/em> related to security implications that arose with Code Access Security and the SuppressUnmanagedCodeAttribute. Thus, my surprise with this code analysis rule still being a thing in the new .NET 5.0 SDK.<\/p>\n\n\n\n<p>Still, it makes some sense to have some sort of organization behind your P\/Invoke declarations. Also, as I said before, I tend to ignore what Microsoft says and <em>look at what they do<\/em>. So, in the new .NET 5.0 library sources, is Microsoft still using NativeMethods-styled classes?<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"338\" height=\"511\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Interop.png\" alt=\"Shows a listing of decompiled classes holding P\/Invokes in the new .NET 5.0 library.\" class=\"wp-image-724\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Interop.png 338w, https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Interop-198x300.png 198w\" sizes=\"(max-width: 338px) 100vw, 338px\" \/><figcaption>Nope. No more NativeMethods. Long live the Interop class.<\/figcaption><\/figure><\/div>\n\n\n\n<p>Looks like Microsoft has eschewed the NativeMethods type and is instead throwing P\/Invokes into an <strong>Interop<\/strong> class, with multiple other nested classes for methods belonging to particular modules. <\/p>\n\n\n\n<p>If we look at the online reference source, we can further see that the Interop class and the various nested classes are scattered among multiple files as <em><strong>static partial classes<\/strong><\/em> (yes, something I haven&#8217;t run into too much myself), with each file owing to some particular type of operation or theme (i.e. a file for anything to do with <a href=\"https:\/\/source.dot.net\/#System.Private.CoreLib\/Interop.ReadDir.cs\" target=\"_blank\" rel=\"noreferrer noopener\">reading a directory<\/a>).<\/p>\n\n\n\n<p>So there you have it. When going forward into the great unknown with your revolutionary new ideas and fabulous new coded technologies: if it&#8217;s targeting .NET 5.0, drop the NativeMethods act! And disable code analysis rule <strong>CA1060<\/strong>.<\/p>\n\n\n\n<p>I myself will do as our Microsoft overlords are doing, and throw all my stuff into an internal static class named <strong>Interop<\/strong>. Looks slicker than <strong>NativeMethods<\/strong> anyway&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Are NativeMethods-Styled Classes Needed in .NET 5.0? Hello everyone. If you haven&#8217;t heard the news, .NET 5.0 is now upon [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10],"tags":[41,42,43],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>P\/Invokes, NativeMethods, and CA1060 in .NET 5.0 - omni&#039;s hackpad<\/title>\r\n<meta name=\"description\" content=\"To follow best practices, methods using P\/Invoke would go into a NativeMethods class to avoid a CA1060. With .NET 5.0, there&#039;s no reason to.\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"P\/Invokes, NativeMethods, and CA1060 in .NET 5.0 - omni&#039;s hackpad\" \/>\r\n<meta property=\"og:description\" content=\"To follow best practices, methods using P\/Invoke would go into a NativeMethods class to avoid a CA1060. With .NET 5.0, there&#039;s no reason to.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2020-11-27T16:48:08+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2020-11-27T16:48:11+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Analyzers.png\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/badecho.com\/#website\",\"url\":\"https:\/\/badecho.com\/\",\"name\":\"omni&#039;s hackpad\",\"description\":\"Game Code Disassembly. Omnified Modification. Madness.\",\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/badecho.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2020\/11\/Net50Analyzers.png\",\"width\":366,\"height\":113,\"caption\":\"Goodbye FxCop -- Hello design-time code analysis.\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/\",\"name\":\"P\/Invokes, NativeMethods, and CA1060 in .NET 5.0 - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#primaryimage\"},\"datePublished\":\"2020-11-27T16:48:08+00:00\",\"dateModified\":\"2020-11-27T16:48:11+00:00\",\"description\":\"To follow best practices, methods using P\/Invoke would go into a NativeMethods class to avoid a CA1060. With .NET 5.0, there's no reason to.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"P\/Invokes, NativeMethods, and CA1060 in .NET 5.0\",\"datePublished\":\"2020-11-27T16:48:08+00:00\",\"dateModified\":\"2020-11-27T16:48:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2020\/11\/27\/nativemethods-in-dotnet-5\/#primaryimage\"},\"keywords\":\".NET,C#,Code Analysis\",\"articleSection\":\"General Dev\",\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\",\"name\":\"Matt Weber\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7e345ac2708b3a41c7bd70a4a0440d41?s=96&d=mm&r=g\",\"caption\":\"Matt Weber\"},\"logo\":{\"@id\":\"https:\/\/badecho.com\/#personlogo\"}}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/713"}],"collection":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/comments?post=713"}],"version-history":[{"count":2,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/713\/revisions"}],"predecessor-version":[{"id":725,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/713\/revisions\/725"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}