MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Работа с Common Intermediate Language"
Answer 888885
есть ли какая-нибудь IDE для разработки приложений на чистом IL
Как вариант, сделать саму Visual Studio такой IDE, пользуясь пользовательскими шаблонами.
I. Шаблон проекта
Создадим проект консольного приложения C#, назовем его, скажем, CilProject.
В обозревателе решений в контекстном меню проекта вызовем пункт "Выгрузить проект". Там же у выгруженного проекта вызовем пункт "Изменить проект".
Найдем в XML узел
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets>
И заменим его на следующий код:
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" /> <Target Name="CreateManifestResourceNames" /> <Target Name="CoreCompile" Inputs="$(MSBuildAllProjects);@(Compile);" Outputs="@(IntermediateAssembly);"> <GetFrameworkPath> <Output TaskParameter="Path" PropertyName="FrameworkPath" /> </GetFrameworkPath> <PropertyGroup> <IlAsmCommand>"$(FrameworkPath)\Ilasm.exe" /NOLOGO /DLL /OUTPUT:"@(IntermediateAssembly)" </IlAsmCommand> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' " > <IlAsmCommand>$(IlAsmCommand) /DEBUG </IlAsmCommand> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Release' " ><IlAsmCommand>$(IlAsmCommand) /OPTIMIZE </IlAsmCommand></PropertyGroup> <PropertyGroup Condition=" '$(AssemblyOriginatorKeyFile)' != '' " > <IlAsmCommand>$(IlAsmCommand) /KEY:"$(AssemblyOriginatorKeyFile)" </IlAsmCommand> </PropertyGroup> <Exec Command="$(IlAsmCommand) @(Compile->'"%(FullPath)"', ' ')" Outputs="@(IntermediateAssembly)" /> <CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''" /> </Target>
Снова загрузим проект (в том же контекстном меню выберем пункт "Перезагрузить проект").
Заменим AssemblyInfo.cs на AssemblyInfo.il:
.assembly CilProject { }
Заменим Program.cs на Program.il:
.method public static void Main() cil managed { .entrypoint .maxstack 1 ldstr "Hello, world!" call void [mscorlib]System.Console::WriteLine(string) call int32 [mscorlib]System.Console::Read() pop ret }
Для обоих .il файлов в свойствах установим Действие при сборке - Компилировать. После этого проект должен собираться и запускаться.
В Visual Studio выберем Проект - Экспорт шаблона - Шаблон проекта, в диалоговом окне введем имя и описание и установим галку "Автоматически импортировать в Visual Studio". В результате должен получиться такой шаблон CilProject.csproj (для VS 2017 и .NET 4.0):
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{$guid1$}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>$safeprojectname$</RootNamespace> <AssemblyName>$safeprojectname$</AssemblyName> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <Deterministic>true</Deterministic> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> <Reference Include="System" /> </ItemGroup> <ItemGroup> <Compile Include="Program.il" /> <Compile Include="Properties\AssemblyInfo.il" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" /> <Target Name="CreateManifestResourceNames" /> <Target Name="CoreCompile" Inputs="$(MSBuildAllProjects);@(Compile);" Outputs="@(IntermediateAssembly);"> <GetFrameworkPath> <Output TaskParameter="Path" PropertyName="FrameworkPath" /> </GetFrameworkPath> <PropertyGroup> <IlAsmCommand>"$(FrameworkPath)\Ilasm.exe" /NOLOGO /OUTPUT:"@(IntermediateAssembly)" </IlAsmCommand> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <IlAsmCommand>$(IlAsmCommand) /DEBUG </IlAsmCommand> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <IlAsmCommand>$(IlAsmCommand) /OPTIMIZE </IlAsmCommand> </PropertyGroup> <PropertyGroup Condition=" '$(AssemblyOriginatorKeyFile)' != '' "> <IlAsmCommand>$(IlAsmCommand) /KEY:"$(AssemblyOriginatorKeyFile)" </IlAsmCommand> </PropertyGroup> <Exec Command="$(IlAsmCommand) @(Compile->'"%(FullPath)"', ' ')" Outputs="@(IntermediateAssembly)" /> <CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''" /> </Target> </Project>
Файл шаблона будет помещен в
(Мои документы)\Visual Studio 2017\Templates\ProjectTemplates
. После этого в окне создания проекта в категории Visual C# появится наш CilProject.Уже можно писать программы (ссылки на сборки вписывать в AssemblyInfo.il, а код добавлять в виде файлов .il с действием при сборке "Компилировать").
II. Шаблон элемента
Для удобства создадим также шаблон класса. Добавим файл Class1.il:
.class public auto ansi beforefieldinit Class1 extends [mscorlib]System.Object { .method public hidebysig static void Method() cil managed { ret } }
В Visual Studio выберем Проект - Экспорт шаблона - Шаблон элемента, в диалоговом окне выберем файл Class1.il, установим галку "Автоматически импортировать в Visual Studio" и введем остальные параметры. Получим zip-файл с шаблоном в каталоге
(Мои документы)\Visual Studio 2017\Templates\ItemTemplates
, распакуем его и откроем файл .vstemplate. В нем найдем узел<ProjectItem...>
и добавим в него атрибутItemType="Compile"
:<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item"> <TemplateData> <DefaultName>CilClass.il</DefaultName> <Name>CilClass</Name> <Description>Class (CIL)</Description> <ProjectType>CSharp</ProjectType> <SortOrder>10</SortOrder> <Icon>__TemplateIcon.ico</Icon> </TemplateData> <TemplateContent> <References /> <ProjectItem ItemType="Compile" SubType="" TargetFileName="$fileinputname$.il" ReplaceParameters="true">Class1.il</ProjectItem> </TemplateContent> </VSTemplate>
Запакуем файлы в такой же ZIP-архив и поместим на место старого в каталоге ItemTemplates. Перезапустим студию, после этого в окне добавления элемента, в категории "Элементы Visual C#" появится наш шаблон класса.
Результат
Что-то такое:
Плюсы: работает отладка, вывод ошибок и предупреждений компилятора с указанием файла и строки, можно переключаться между конфигурациями Debug/Release.
Минусы: не работают свойства проекта, функционал добавления ссылок через интерфейс студии, подсветка синтаксиса, проверка ошибок во время редактирования и многое другое.
Итоговые файлы шаблонов: шаблон проекта, шаблон элемента.
чем бы следовало вооружиться для более детального его изучения
Утилитой IL Disassembler, документацией класса System.Reflection.Emit.OpCodes, третьим разделом спецификации.
Источники
Visual Studio Project and item templates
How can i load a template I have created in Visual Studio?
Are there any examples of compiling CIL code from within a Visual Studio project
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.