42734

ВЗАИМОДЕЙСТВИЕ С УНАСЛЕДОВАННЫМ ПРОГРАММНЫМ КОДОМ

Лабораторная работа

Информатика, кибернетика и программирование

Очень часто сборки .NET должны успешно взаимодействовать со сложными приложениями, где значительную часть кода составляют классические СОМ- серверы. Код модулей СОМ является двоичным и платформенно-зависимым (в отличие от полностью платформенно-независимого кода IL). СОМ-серверы работают с уникальным набором типов данных (BSTR, VARIANT и т. п.), содержание которых в разных языках программирования сильно различается.

Русский

2013-10-30

167.37 KB

3 чел.

ЛАБОРАТОРНАЯ РАБОТА № 5.1

ВЗАИМОДЕЙСТВИЕ С УНАСЛЕДОВАННЫМ ПРОГРАММНЫМ КОДОМ

Очень часто сборки .NET должны успешно взаимодействовать со сложными приложениями, где значительную часть кода составляют классические СОМ- серверы. Код модулей СОМ является  двоичным и платформенно-зависимым (в отличие от полностью платформенно-независимого кода IL).  СОМ-серверы работают с уникальным набором типов данных (BSTR, VARIANT и т. п.), содержание которых
в разных языках программирования сильно различается. В каждом программном модуле СОМ должны быть реализованы достаточно сложные элементы (такие как фабрики классов, код IDL, записи в реестр). В  СОМ-объектах необходимо отслеживать каждую ссылку на объект. Eсли
ошибиться в ссылках на объект, то это может привести к утечке памяти.
 

Следовательно, между типами .NET и СОМ так мало общего, что трудно даже представить, как такие разные типы могут успешно взаимодействовать друг с другом. Но в реальной работе возникает очень много ситуаций, когда необходимо обеспечить такое взаимодействие. Платформа .NET поддерживает следующие виды совместимости с унаследованным кодом:

  1.  вызовы из типов .NET напрямую к модулям DLL, созданным на С (то есть обращения к Win32 API или пользовательским модулям DLL);
  2.  взаимодействие .NET  и СОМ;
  3.  применение элементов управления ActiveX  в Windows Forms;
  4.  вызовы из типов СОМ к типам .NET;

В данной лабораторной работе будут рассмотрены пункты  2 и 3.

РЕАЛИЗАЦИЯ ВНУТРЕННЕГО СЕРВЕРА COM В DELPHI

  1.  Для создания в Delphi внутреннего сервера СОМ, реализуемого библиотекой DLL, выполните команду File New | Other и на странице ActiveX Депозитария выберите пиктограмму ActiveX Library. Будет создан новый проект, который сохраните под каким-то именем, например, PMyComServ.

Взгляните на созданный Delphi код этого проекта:

library  PMyComServ;

uses

ComServ;

exports

DllGetClassObject,

DllCanUnloadNow,

DllRegisterServer,

DllUnregisterServer;

($R   *.RES)

begin

end. .

Оператор uses подключает к проекту модуль ComServ, в котором описан класс TComServ, реализующий свойства сервера СОМ. Объект ComServ этого класса автоматически создается в проекте и позволяет через свои свойства получать информацию о сервере и его объектах.

Как видно из приведенного выше кода, библиотека экспонирует четыре функции. Все они вызываются в нужные моменты автоматически.

  1.  Теперь надо добавить в  сервер объект. Пусть это будет  объект, имеющий два интерфейса, первый из которых имеет две арифметические функции: сложение и вычитание двух действительных чисел, а второй — функции умножения и деления действительных чисел.

Выполните опять команду File New | Other и на странице ActiveX Депозитария выберите пиктограмму COM Object. Перед вами откроется окно, показанное на рисунке 1. В окне Class Name вы должны указать имя класса создаваемого объекта. К этому имени будет автоматически добавлен префикс «Т». Так что имя «MyObject», которое вы видите на рисунке 1, приведет к созданию класса TMyObject.

 

Рисунок 1 – Добавление объекта

Выпадающий список Instancing позволяет выбрать способ создания объекта (см. таблицу 1).

Таблица 1 Описание способов создания объектов

Internal

Объект создается только внутренне                                      

Single Instance

Каждый сервер может содержать только один экземпляр объекта, так что для каждого клиента создается отдельный экземпляр сервера                                                                          

Multiple Instances

   Для каждого клиента создается отдельный экземпляр объекта в пределах адресного пространства одного сервера     

В данном примере выбор в списке Instancing не имеет значения, так как для внутреннего сервера, который мы создаем, этот параметр игнорируется.

Выпадающий список Threading model определяет способы вызова клиентами интерфейса объекта СОМ в многопоточных приложениях (см. таблицу 2).

Таблица 2 Способы вызова клиентами интерфейса объекта СОМ в многопоточных приложениях

Single

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

Apartment

Все вызовы клиентов обрабатываются в одном потоке, в котором был создан объект. Предполагается, что к объекту в каждый момент времени обращается только один поток клиента. Надо принимать меры для защиты глобальных данных

Free

Объекты обрабатывают вызовы произвольного числа потоков одновременно. Надо принимать меры для защиты всех локальных и глобальных данных

Both

To же, что Free, только откаты осуществляются гарантированно в том же потоке

Neutral

Множество клиентов могут вызывать объект в различных потоках, но предполагается, что между этими вызовами не возникает конфликтов. Эта модель не может использоваться для объектов, имеющих пользовательский интерфейс, т.е. визуальные компоненты. Модель поддерживается только для СОМ+. Для СОМ она эквивалентна Apartment

  1.  В окне Implemented interfaces задается имя интерфейса вашего объекта СОМ по умолчанию. Вы можете согласиться с предложенным именем, которое является именем класса с префиксом «I», или написать новое имя. Созданный интерфейс будет наследником IUnknown и в дальнейшем вы сможете задать его реализацию, пользуясь описанным далее редактором библиотеки типов.

Вместо реализации нового интерфейса вы можете выбрать один из зарегистрированных в вашей системе, пользуясь кнопкой List. При использовании зарегистрированного интерфейса обязательно надо пользоваться этой кнопкой, так как если вы просто напишете в окне имя существующего интерфейса, система не поймет, что это не новый, а существующий интерфейс.

  1.  Окно Description дает возможность ввести текстовое описание объекта СОМ. Индикатор Include Type Library определяет автоматическую генерацию библиотеки типов. Индикатор Mark interface OleAutornation разрешает маршаллинг — вызов функции интерфейса удаленными объектами в другом процессе и на другой машине, чтобы не усложнять свою задачу, выключите этот индикатор.

После того, как вы заполните всю информацию в окне и щелкнете на ОК перед вами откроется окно редактора библиотеки типов (рисунок 2), а в окне Редактора Кода вы сможете увидеть заготовку модуля объекта СОМ. Она будет иметь вид:

unit UObject;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses

Windows, ActiveX, Classes, ComObj, PMyComServ_TLB, StdVcl;

type

TMyObjec=class (TTypedComObject, IMyObject)

protected

// Здесь объявляются методы интерфейса

end;

implementation

uses ComServ;

initialization

TTypedComObjectFactory.Create(ComServer, TMyObject,

Class_MyObject, ciMultilnstance, tmApartment);

end.

  1.  Вы видите, что в раздел initialization включен конструктор фабрики класса. Класс фабрики класса создан Delphi автоматически.
  2.  Вызвав Менеджер Проектов (команда View Project Manager) вы увидите, что помимо этого модуля сгенерировался и включился в проект файл РМуComServ_TLB.pas — модуль библиотеки типов.
  3.  Теперь займемся разработкой методов созданного объекта. В первый момент после создания объекта окно редактора библиотеки типов (рисунок 2 ) откроется автоматически. В дальнейшем вы в любой момент можете вызвать это окно командой View | Type Library. Эта команда доступна только в том случае, если ваш проект содержит библиотеку типов.

Рисунок 2 - Редактор библиотеки типов

  1.  В левой панели окна редактора библиотеки типов вы видите дерево элементов вашего объекта СОМ. Правая многостраничная панель позволяет посмотреть и задать свойства вершины, выделенной в левой панели. А инструментальная панель верху окна содержит быстрые кнопки, позволяющие вводить в объект новые интерфейсы, методы, свойства и т.п.
  2.  Начнем с добавления методов в интерфейс IMyObject. Выделите в левой панели вершину этого интерфейса и щелкните на быстрой кнопке New Method. В дереве левой панели появится вершина нового метода. Назовите этот метод Add — он будет складывать два числа. Выделите вершину метода и перейдите в правой панели на страницу Parameters, которая показана на рисунке 3. В выпадающем списке Return Type надо выбрать тип возвращаемого методом значения -  в нашем примере float. Для задания параметров метода нажмите кнопку Add.

Рисунок 3 - Определение входных и  выходных параметров

  1.  В нижнем окне панели появится строка, соответствующая вводимому параметру. В столбце Name надо задать имя параметра («Numberl» на рисунке 3). В столбце Туре надо выбрать из выпадающего списка тип параметра. В столбце Modifier можно выбрать модификаторы параметра: входной, выходной, необязательный, со значением по умолчанию и т.п. В нашем примере можно оставить значение по умолчанию «[in]».
  2.  Аналогичным образом надо задать второй параметр. Далее так же, как вы добавили метод Add, добавьте в интерфейс метод Sub — вычитание чисел.
  3.  Теперь надо ввести в объект второй интерфейс. Щелкните на быстрой кнопке New Interface (крайняя левая). В левой панели появится новая вершина. Назовите новый интерфейс «IMyObject2». Укажите для нового интерфейса родительский интерфейс – IUnknown.
  4.  Выделите эту вершину, перейдите на правой панели на страницу Flags и выключите на ней флаги Dual и OleAutomation, чтобы не усложнять нашу задачу.
  5.  Введите в новом интерфейсе так же, как делали раньше, два метода Mult — перемножение чисел, и Div — деление.    
  6.  Вы описали второй интерфейс. Теперь надо ввести его в ваш объект. Выделите в левой панели вершину объекта MyObject и перейдите в правой панели на страницу Implements. Щелкните на ней правой кнопкой мыши и выберите в контекстном меню раздел InsertInterface. Перед вами откроется окно со списком интерфейсов, которые вы можете добавить в свой объект. Выберите из него созданный вами интерфейс IMyObject2. Интерфейс включится в ваш объект.
  7.  Описание объекта закончено. Теперь надо написать реализацию введенных методов. Щелкните на быстрой кнопке Refresh Implementation — обновить реализацию. Перейдите в редактор кода и посмотрите модуль объекта. Вы увидите в объявлении класса ссылку на оба интерфейса, объявления введенных вами методов, а в разделе implementation найдете заготовки реализации этих методов. Напишите в них соответствующие операторы. В результате модуль объекта приобретет вид:

unit Unit1;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses

 Windows, ActiveX, Classes, ComObj, PMyComServ_TLB, StdVcl;

type

 TMyObject = class(TTypedComObject, IMyObject, IMyObject2)

 protected

   function Add(Number1, Number2: Single): Single; stdcall;

   function Div_(Number1, Number2: Single): Single; stdcall;

   function Mult(Number, Number2: Single): Single; stdcall;

   function Sub(Number1, Number2: Single): Single; stdcall;

   {Declare IMyObject methods here}

 end;

implementation

uses ComServ;

function TMyObject.Add(Number1, Number2: Single): Single;

begin

  Result:=Number1+Number2;

end;

function TMyObject.Div_(Number1, Number2: Single): Single;

begin

  Result:=Number1/Number2;

end;

function TMyObject.Mult(Number, Number2: Single): Single;

begin

  Result:=Number*Number2;

end;

function TMyObject.Sub(Number1, Number2: Single): Single;

begin

  Result:=Number1-Number2;

end;

initialization

 TTypedComObjectFactory.Create(ComServer, TMyObject, Class_MyObject,

   ciMultiInstance, tmApartment);

end.

  1.  Обратите внимание, что Delphi автоматически изменила имя метода Div на Div_, так как мы случайно  задали методу имя, совпадающее с именем соответствующей операции Object Pascal. Чтобы в кодах не возникала двусмысленность, Delphi добавила в конце имени метода символ подчеркивания.
  2.  Теперь все сделано, объект в составе сервера СОМ создан. Выполните компиляцию проекта (Project|Compile All Project).
  3.  Осталось зарегистрировать сервер в системе. Это можно сделать командой Run | Register ActiveX Server главного меню Delphi. Если вы в дальнейшем надумаете удалить его (вряд ли наш тестовый сервер представляет какую-то ценность), вы должны будете выполнить команду Run | Unregister ActiveX Server.

Отметим еще, что для распространения вашего проекта между пользователями вам потребуется библиотека типов на языке IDL Трансляция ее осуществляется быстрой  кнопкой Export To IDL — крайняя правая на рисунке 3.

  1.  Осталось проверить работу нашего сервера. Создайте тестовое приложение, включающее два окна Edit, в которых пользователь может задавать числа, две кнопки, одна из которых выполняет методы первого, а другая — второго интерфейса, и две метки для отображения результатов (рисунок 4.).

Рисунок 4 - Тестовый пример

Код этого приложения может сеть вид:

unit Unit3;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls,PMyComServ_TLB;

type

 TForm1 = class(TForm)

   Edit1: TEdit;

   Edit2: TEdit;

   Label1: TLabel;

   Label2: TLabel;

   Button1: TButton;

   Button2: TButton;

   procedure FormCreate(Sender: TObject);

   procedure Button1Click(Sender: TObject);

   procedure Button2Click(Sender: TObject);

 private

   { Private declarations }

 public

   { Public declarations }

 end;

var

 Form1: TForm1;

 Interface1:IMyObject;

 Interface2:IMyObject2;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

 Interface1:=CoMyObject.Create;

 Interface1.QueryInterface(ImyObject2,Interface2);

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

 Label1.Caption:=FloatToStr(Interface1.Add(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text)));

 Label2.Caption:=FloatToStr(Interface1.Sub(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text)));

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

Label1.Caption:=FloatToStr(Interface2.Mult(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text)));

Label2.Caption:=FloatToStr(Interface2.Div_(StrToFloat(Edit1.Text),StrToFloat(Edit2.Text)));

end;

end.

  1.  Обратите внимание прежде всего на то, что в оператор uses включена ссылка на модуль созданной вами библиотеки типов PMyComServ_TLB.pas. Далее после объявления класса формы вводятся две переменные Interface1 и Interface2 соответственно типов IMyObject и IMyObject2, объявленных в вашем объекте СОМ.
  2.  Процедура FormCreate является обработчиком события OnCreate формы. Первый оператор этого обработчика создает CoClass класса CoMyObject и возвращает указатель на интерфейс по умолчанию IMyObject в переменную Interfacel.
  3.  Чтобы получить указатель на второй интерфейс, используется функция Querylnterface первого интерфейса, в которую передаются как параметры имя второго интерфейса IMyObject2 и переменная Interface2. В результате переменной Interfaсе2 присваивается указатель на интерфейс IMyObject2.

Код примера очевиден: при щелчках на той или иной кнопке в метки Label1 и Label2 заносятся результаты выполнения соответствующих методов интерфейсов с параметрами, получаемыми из окон Editl и Edit2.

Для взаимодействия .NET с COM  выполните следующие действия:

  1.  Создайте проект в C# , изображенный на рисунке 5.

Рисунок  5 – Пример COM-клиента на C#

  1.  Выполните раннее связывание с СOM-сервером при помощи диалогового окна Add Reference (см. рисунок 6).

Рисунок 6- Вызов диалогового окна Add Reference

  1.  В появившемся диалоговом окне выбираете нужный COM-сервер (см. рисунок 7.

Рисунок 7 – Обращение к COM-серверу средствами Visual Studio .NET

  1.  Для  упрощения доступа к COM-серверу добавьте строку:

namespace com

{

   using PMyComServ; // !!!!!

   public partial class Form1 : Form

   {

       public Form1()

       {

           InitializeComponent();

       }

  1.   Объявите глобальные переменные:

MyObject m;

     IMyObject i;

IMyObject2 j;

  1.   Для события Click кнопки Button1 (Интерфейс1) напишите следующий программный код:

private void button1_Click(object sender, EventArgs e)

{

// Создаем объект MyObject          

m = new MyObject();

// Явным образом получаем ссылку на интерфейс IMyObject

    i = m;

    float s1 = Convert.ToSingle(textBox1.Text);

    float s2 = Convert.ToSingle(textBox2.Text);

// Вызываем методы интерфейса IMyObject

    label1.Text = Convert.ToString(i.Add(s1, s2));

    label2.Text = Convert.ToString(i.Sub(s1,s2));

 }

  1.  Для события Click кнопки Button2 (Интерфейс2) напишите следующий программный код:

private void button2_Click(object sender, EventArgs e)

{

// Создаем объект MyObject

  m = new MyObject();

// Явным образом получаем ссылку на интерфейс IMyObject

  i = m;

// Получаем ссылку на интерфейс IMyObject2

// через интерфейс IMyObject

  j = (IMyObject2)i;

  float s1 = Convert.ToSingle(textBox1.Text);

  float s2 = Convert.ToSingle(textBox2.Text);

  label1.Text = Convert.ToString(j.Mult(s1, s2));

  label2.Text = Convert.ToString(j.Div(s1, s2));

}

ЗАДАНИЯ  К ЛАБОРАТОРНОЙ РАБОТЕ № 5_1

Создайте COM-объект, имеющий два интерфейса, каждый интерфейс содержит два метода:

  1.  Работа со строками. Введите предложение. Выполните подсчет гласных  и согласных  букв, количества слов и количества слов, начинающихся с гласных.
  2.  Работа со строками. Введите предложение. Выполните подсчет букв  и знаков препинания,. количества слов и количества слов, начинающихся с больших английских букв.
  3.  Строки. Введите предложение и определите длину самой большой цепочки идущих подряд цифр и букв, а также удалите все лишние пробелы (между каждым словом только 1 пробел)  и расставьте дополнительные пробелы таким образом, чтобы длина всей строки была равна 40 символов.
  4.  Работа со строками. Введите предложение. Замените все маленькие буквы на большие. Замените все большие буквы на маленькие. Переверните все предложение. Переверните каждое слово.
  5.   Геометрия. По известному радиусу окружности найдите длину окружности, площадь круга, периметр и площадь квадрата, описанного около окружности.
  6.  Геометрия. Даны катеты прямоугольного треугольника, найдите гипотенузу треугольника, периметр треугольника, площадь треугольника по формуле Герона и по известной стороне и высоте треугольника.
  7.  Геометрия. Даны радиус и высота цилиндра. Найдите площадь цилиндра, объем цилиндра, площадь боковой поверхности и площадь основания.
  8.  Геометрия.  Даны стороны прямоугольного параллелепипеда. Найдите площадь поверхности  и объем параллелепипеда, а также площадь одной  грани и площадь боковой поверхности.
  9.  Физика. Даны три сопротивления.  Найдите сопротивление соединения для случаев, когда соединение параллельное и когда последовательное. А также, значение наибольшего и наименьшего сопротивлений.
  10.  Математика. Введите число и определите, является ли оно простым,  найдите НОД числа, определите является ли число степенью двух и степенью  трех.
  11.  Булева алгебра. Введите десятичное число и переведите его в двоичное, введите двоичное число и переведите его в десятичное. Выполните аналогичный перевод десятичного числа в шестнадцатеричное  и шестнадцатеричного в десятичное.
  12.  Булева алгебра. Введите двоичное число и выполните операции сложения, вычитания, умножения и деления. Результат выведите в двоичной форме.
  13.  Булева алгебра. Введите шестнадцатеричное число и выполните операции сложения, вычитания, умножения и деления. Результат выведите в шестнадцатеричной форме.
  14.  Булева алгебра. Введите восьмеричное число и выполните операции сложения, вычитания, умножения и деления. Результат выведите в восьмеричной форме.


 

А также другие работы, которые могут Вас заинтересовать

28696. Конец двоевластия и установление единовластия Временного правительства. Антинародная политика Временного правительства. Провозглашение России Республикой. Центральные и местные органы власти и управления 13.46 KB
  Конец двоевластия и установление единовластия Временного правительства. Антинародная политика Временного правительства. Центральные и местные органы власти и управления. На 1 съезде Советов рабочих и солдатских депутатов была принята резолюция о сотрудничестве с Временным праввом.
28697. Политическая и законотворческая деятельность Временного правительства по основным социально-политическим и экономическим проблемам страны 13.75 KB
  правво принимает ряд правовых актов значительно расширяющих демократиче права и свободы граждан. В марте принимается постановление О кооперативных товариществах и их союзах возникающих без особого разрешения правитвенной власти. Вместе с тем правво отказывся от некотх чрезвычх мер запретив аресты без суда и ограничив число областей объявленных на военном положи постановле О лицах арестованных во внесудом порядке.
28698. Октябрьское вооруженное восстание 1917 г. и установление диктатуры пролетариата в России 13.87 KB
  Комитет состоял из представителей армии профсоюзов фабричнозаводских комитетов военных секций Советов и др. Важная роль в становлении Советского государства и государственного аппарата принадлежала Всероссийскому съезду Советов рабочих и солдатских депутатов. Ленин выдвинул идею диктатуры пролетариата в виде республики Советов. Новый госный строй России диктатуру пролетариата в виде республики Советов окончательно утвердила принятая 10 июля 1918 г.
28699. II-ой Всероссийский съезд Советов, его состав. Исторические декреты съезда о мире и земле 12.38 KB
  IIой Всероссийский съезд Советов его состав. Исторические декреты съезда о мире и земле. Важная роль в становлении Советского гос0ва и государственного аппарата принадлежала Всероссийскому съезду Советов рабочих и солдатских депутатов. Съезд больш.
28700. Слом старого государственного аппарата после Октябрьского вооруженного восстания1917г Упразднение органов буржуазного самоуправления. Роспуск Учредительного собрания 12.77 KB
  Руководство этим процессом осуществляли Всероссийские съезды Советов Петроградский ВРК ВЦИК НКВД и другие органы. когда Декретом ВЦИК и СНН упразднялись все сословия и сословные организации и учреждения. Председатель ВЦИК Я. Свердлов от имени ВЦИК и ЦК партии большевиков зачитал и предложил принять Декларацию прав трудящегося и эксплуатируемого народа.
28701. Военно-революционный комитет Петрограда и его роль в переходе власти к Советам. Создание милиции, судебных органов, ВЧК и Красной Армии, их компетенции и борьба против контрреволюции 14.26 KB
  Создание милиции судебных органов ВЧК и Красной Армии их компетенции и борьба против контрреволюции.10 вводится в действие приказ По рабочей милиции. НКВД и Наркомюст утвердили совместную инструкцию Об организации советской рабочекрестьянской милиции. Руководство органами милиции осуществляло Главное управление рабочекрестьянской милиции НКВД РСФСР.
28702. «Декларация прав трудящегося и эксплуатируемого народа», ее содержание и значение 12.2 KB
  Декларация прав трудящегося и эксплуатируемого народа ее содержание и значение. Декларация Прав Трудящегося И Эксплуатируемого Народа важнейший конституционный акт Советской республики законодательно закрепивший завоевания Октябрьской революции и провозгласивший основные принципы и задачи социалистического государства. Декларация была утверждена III Всероссийским съездом рабочих солдатских и крестьянских депутатов. Декларация состояла из четырех разделов.
28703. «Декларация прав народов России», ее содержание и значение 15 ноября 1917 г. 11.56 KB
  Декларация прав народов России ее содержание и значение 15 ноября 1917 г. Исполняя волю съездов Совет Народных Комиссаров решил положить в основу своей деяти по вопросу о национальностях России следующие начала: 1 Равенство и суверенноcть народов России. 2 Право народов России на свободное самоопределение вплоть до отделения и образования самостоятельного государства. 4 Свободное развитие национальных меньшинств и этнографических групп населяющих территорию России.
28704. Мероприятия Советского государства по созданию новой экономики. Национализация банков связи, транспорта, внешней торговли, крупной промышленности 13.92 KB
  ВСНХ принял постановление согласно котму все частные предпря с числом рабочих свыше 5 при наличии механического двигателя на предприятии или 10 без двигателя человек объявлялись национализированными. органа по рукву эккой страны учреждался Высший совет народного хозва ВСНХ. ВСНХ действовал в качестве органа при правве. ВСНХ д.