2015-07-14 5 views
2

Я создаю сборку .NET, которая должна быть COM-вызываемой, например. VB6 и т. Д.Установка определенного значения COM HRESULT из .NET.

Большая часть материала отлично работает - сейчас я точно настраиваю обработку ошибок.

Что я хотел бы сделать, это создать определенные значения HRESULT за исключением моих исключений - например. используйте значения, такие как 0x88880001 и т. д. для моих случаев исключения. Я бы хотел использовать общий «префикс» (например, 0x8888), а затем добавить к этому номер мои внутренние коды ошибок (от десятичного до 1001 вверх).

Таким образом, моя внутренняя ошибка 1001 должна стать HRESULT = 0x888803E9 и так далее.

У меня есть свой собственный класс исключений .NET, и я знаю, что могу установить защищенное свойство HResult на базе ApplicationException класс - но почему-то мне не удается получить мой «префикс» плюс мой код ошибки для работы. ...

с использованием системы;

public class CustomException : ApplicationException 
{ 
    public CustomException(string message, int errorCode) : base(message) 
    { 
     base.HResult = (uint) 0x88880000 + errorCode; 
    } 
} 

Независимо от того, что я пытаюсь здесь - я просто не могу получить int значение (для base.HResult, который является int), который представляет 0x888803E9 хранить в моем базовом классе ...

Что же я отсутствует здесь ??

ответ

6

Компилятор C# просто мешает вам отключить ошибку переполнения. Разумеется, многие из этого типа кода не могут пережить проверку переполнения, а не тот вид неудачи, который вы когда-либо захотели в коде обработки ошибок :). Обратите внимание, как код в upvoted ответется с помощью Project> Properties> Build> Advanced> "Check for арифметическое переполнение/нижнее значение ". Опция, которая недостаточно используется.

Вы должны использовать непроверенную ключевое слово, чтобы подавить эту проверку выполнения:

base.HResult = unchecked((int)(0x88880000U + errorCode)); 

Или вы можете подавить его во время компиляции:

const int ErrorBase = unchecked((int)0x88880000); 
    base.HResult = ErrorBase + errorCode; 

Мучительно: в HRESULT вас 'll generate не является допустимым, у него нет правильного кода объекта. Этот код дает подсказку, откуда возникла ошибка. Код Interop должен использовать 0x80040000 в качестве базы ошибок для выбора FACILITY_ITF. Не уверен, что вы когда-нибудь получите какое-либо горе по сравнению с 0x88880000, но самая важная строка сообщения, которую вы создаете. К сожалению, ISupportErrorInfo, как правило, пропускается в клиентском коде, поэтому нет большой гарантии того, что кто-то действительно его видит.

+0

Спасибо, это похоже на трюк - независимо от настроек проекта! :-) Не могу поверить, что настройки ** ВЫКЛ ** по умолчанию, в проекте C# .... в VB - может быть, ОК - но на C# - серьезно? –

+0

Он включен по умолчанию в VB. К сожалению, проверка переполнения довольно дорога, большие потери. –

2
base.HResult = (int)((uint)0x88880000 + errorCode); 

база.HResult - это System.Int32.

Ваш номер больше, чем Int32, однако он перевернулся. Не уверен точно, что вам нужно, и может помочь checked.

Однако, это, кажется, чтобы проверить:

void Main() 
{ 
    var ce = new CustomException("uh oh", 1001); 
    Console.WriteLine(ce.HResult); 
    // Convert integer as a hex in a string variable 
    string hexValue = ce.HResult.ToString("X"); 
    // Convert the hex string back to the number 
    int decAgain = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);   
    Console.WriteLine(hexValue); 
    Console.WriteLine(decAgain); 
} 


public class CustomException : Exception 
{ 
    public CustomException(string message, int errorCode) : base(message) 
    { 
     base.HResult = (int)((uint)0x88880000 + errorCode); 
    } 
} 

Лучшая практика для всех исключений являются производными от класса Exception.

+0

Вы попробовали этот код? Он выдает 'OverflowException' на' (int) ((uint) 0x88880000 + errorCode) '. – acelent

+0

нет в LINQPad. возможно, вы используете VS с настройкой, описанной @Hans Passant – jacoblambert