Dot-Net

如何在託管 C++/CLI 項目中修復 CA2123(覆蓋連結需求應與基本相同)

  • October 31, 2013

我無法理解如何為 C++/CLI 項目修復 CA2123。這是一個展示該問題的範例項目:

  1. 創建一個 C# (.NET 4) 類庫

託管類.cs

命名空間 CSharpLibrary {

public interface IManagedClass
{
   void WriteSomething();
}

public class ManagedClass : IManagedClass
{
   public void WriteSomething()
   {
   }
}

}

2)創建一個 C++/CLI 控制台應用程序(VS 2010):

裝配資訊.cpp

#include "stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security;

[assembly:AssemblyTitleAttribute("CPlusPlusCLIConsoleApp")];
[assembly:AssemblyDescriptionAttribute("")];

[assembly:AssemblyVersionAttribute("1.0.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(false)];

[assembly:SecurityCritical];

CPlusPlusCLIConsoleApp.h

#pragma once

using namespace CSharpLibrary;
using namespace System::Security;

typedef void* (__cdecl FACTORY_PROC)();

namespace CPlusPlusCLIConsoleApp
{
   public ref class MainClass : public IManagedClass
   {
   public:
       [SecurityCritical]
       virtual void WriteSomething();
   };

};

CPlusPlusCLIConsoleApp.cpp

#include "stdafx.h"
#include "CPlusPlusCLIConsoleApp.h"

using namespace System;

int main(){};

namespace CPlusPlusCLIConsoleApp
{
   [SecurityCritical]
   void MainClass::WriteSomething()
   {
   }
};

啟用所有 Microsoft 安全規則後,我收到以下警告:

CA2123 覆蓋連結需求應與基本相同

將以下安全屬性添加到“MainClass::WriteSomething(void)”以匹配基礎方法“IManagedClass::WriteSomething(void)”上的 LinkDemand:“SecurityCriticalAttribute”。

CPlusPlusCLIConsoleApp cpluspluscliconsoleapp.cpp 13

我試圖遵循這個StackOverflow 答案的建議,但它沒有修復錯誤。

我知道託管 dll 預設為 SecurityCritical(我不想在我的原始項目中更改它),因為我沒有指定任何 SecurityAttribute。為什麼 C++ CLI dll 不遵循相同的預設值?

我應該遵循哪些步驟來修復此錯誤?(基本上我怎樣才能在 C++ CLI 中創建 WriteSomething 方法 SecurityCritical)

**編輯 1:**我在MSDN上問過同樣的問題。

**編輯 2:**聯繫了微軟,這是一種設計行為。C++\CLI 團隊只是沒有時間為 C++\CLI 實施 Level2 Security。因此 C++\CLI 總是停留在 Level1 Security。可以安全地抑制相同的程式碼分析警告。

這裡的根本問題是您的 C# 和 C++ 程序集使用兩種不同的透明度模型(請參閱http://blogs.msdn.com/b/shawnfa/archive/2009/11/11/transparency-models-a-tale-of -two-levels.aspxhttp://blogs.msdn.com/b/shawnfa/archive/2009/11/12/differences-between-the-security-rule-sets.aspx了解兩個級別的詳細資訊)。這是因為 C# 程序集預設編譯為 2 級,但 C++ 程序集由於某些明顯未記錄的原因被編譯器自動強制降至 1 級。不幸的是,後一種行為似乎不可替代。更糟糕的是,它在 VS2012 中似乎並沒有改變,而且看起來產品團隊也沒有考慮很快改變它

鑑於您不能將 C++ 程序集移動到級別 2,如果您想將執行檔保留在 C++ 中並且它必須包含介面實現,那麼您有幾個可能可行的選擇:

  1. 通過使用 SecurityRulesAttribute 將 C# 程序集移至級別 1。這大概只有在 C++ 控制台應用程序是 C# 庫的唯一使用者時才可以接受。
  2. 通過使用 PermissionSetAttribute 將 2 級安全關鍵性“升級”再現為完全信任連結/繼承需求。例如:
[SecurityCritical]
[PermissionSet(SecurityAction::LinkDemand, Unrestricted = true)]
[PermissionSet(SecurityAction::InheritanceDemand, Unrestricted = true)]
virtual void WriteSomething();

送出另一個關於Connect的錯誤報告(投票給已關閉的錯誤似乎不是很有用)或在UserVoice上送出功能請求以請求更改編譯器行為也可能是值得的。(鑑於 2 級應該是 .NET 4.0 及更高版本的預設設置,鎖定到 1 級是非常奇怪的。)

引用自:https://stackoverflow.com/questions/17571948