Войти
Urho3DФорумURHOSHARP

Скрипт на сишарпе и межпроцессное взаимодействие

Страницы: 1 2 Следующая »
#0
9:34, 6 дек. 2016

Вопросы напрямую  не относятся к урхошарпу, но хочу проконсультироваться у местных гуру сишарпа :)

1) Я хочу сделать приложение, которое использует в качестве скрипта исходник на сишарпе.
Иными словами есть само запускаемое приложение и набор скриптов в *.cs файлах.
Приложение берет эти файлы и налету компилирует их в dll-ку. Нужно предоставить этой dll-ке доступ к объектам самого приложения, а приложение должно уметь вызывать определенный набор функций из скрипта (короче как плагин, только который компилируется на лету из исходников). А также эту dll нужно выгружать из памяти в случае изменения скрипта, компилировать измененный скрипт и заново подключать dll'ку. Такое вообще возможно? Куда копать, чего читать.

2) Я хочу одновременно запускать несколько одинаковых экземпляров приложения и чтобы каждое приложение могло отправлять широковещательное сообщение всем другим в виде строки.
То есть один экземпляр приложение отправляет в эфир сообщение "Аларм", а все другие приложения получают эту строку и могут среагировать.
Я накопал такое https://msdn.microsoft.com/en-us/library/bb546102(v=vs.110).aspx
Это то что мне нужно? Однако там нужно создавать клиент и сервер. Но у меня все экземпляры приложения равноправны.
То есть мне в каждом экземпляре нужно создавать сервер на отправку и клиент для прослушивания широковещательных сообщений?
Или это по другому делается?


#1
9:47, 6 дек. 2016

1) AppDomain позволяет загружать assembly. Выгружать можно прибив AppDomain и создав новый.

      public event EventHandler<CompilerEventArgs> ErrorDataReceived;
        public event EventHandler<CompilerEventArgs> OutputDataReceived;
        public event EventHandler<CompilerEventArgs> InputDataReceived;

        public async Task<string> CompileScripts()
        {
            var Scripts = _codeFolder.FindScripts();
            var solutionPath = _codeFolder.GetSolutionPath();

            var folder = Path.Combine(solutionPath, "Core", "bin", "Release");
            Directory.CreateDirectory(folder);
            var fileName = Path.Combine(folder, ProjectName + ".dll");

            var assemblyInfoFolder = Path.Combine(solutionPath, "Core", "Properties");
            Directory.CreateDirectory(assemblyInfoFolder);
            var assemblyInfoFile = Path.Combine(assemblyInfoFolder, "AssemblyInfo.cs");
            SolutionGenerator.GenerateFileIfDoesntExist(assemblyInfoFile, new AssemblyInfo(_solutionGenerator));

            var frameworkPath = RuntimeEnvironment.GetRuntimeDirectory();
            var cscPath = Path.Combine(frameworkPath, "csc.exe");
            var info = new ProcessStartInfo(cscPath);

            var references =
                //new string[] { "System.dll", "System.Core.dll", "System.Xml.dll", "System.Xml.Linq.dll", "Microsoft.CSharp.dll", "mscorlib.dll" }.Select(_=>
                //    Path.Combine(
                //        @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7",
                //        _)).ToList();
                Directory.GetFiles(
                    @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7",
                    "*.dll");
            var urhoLib = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), @"Urho.dll");
            info.Arguments =
                "/noconfig /unsafe+ /nowarn:1701,1702,2008 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /errorendlocation /preferreduilang:en-US /nologo /target:library /optimize /utf8output /out:" +
                fileName + " /reference:\"" + urhoLib + "\" " +
                string.Join(" ", references.Select(_ => "/reference:\"" + _ + "\"")) + " " +
                string.Join(" ", Scripts.Select(_ => "\"" + _ + "\"")) + " " +
                assemblyInfoFile;
            info.WorkingDirectory = _codeFolder.ProjectFolder;
            info.UseShellExecute = false;
            info.CreateNoWindow = true;
            info.RedirectStandardOutput = true;
            info.RedirectStandardError = true;
            Debug.WriteLine(info.FileName + " " + info.Arguments);
            InputDataReceived?.Invoke(this, new CompilerEventArgs(info.FileName + " " + info.Arguments));
            var p = Process.Start(info);
            p.BeginErrorReadLine();
            p.BeginOutputReadLine();
            var outputMessage = new StringBuilder();
            var errorMessage = new List<string>();
            p.ErrorDataReceived +=
                delegate(object sender, DataReceivedEventArgs e)
                {
                    if (e.Data != null)
                    {
                        ErrorDataReceived?.Invoke(this, new CompilerEventArgs(e.Data));
                        outputMessage.AppendLine(e.Data);
                    }
                };
            p.OutputDataReceived +=
                delegate(object sender, DataReceivedEventArgs e)
                {
                    if (e.Data != null)
                    {
                        OutputDataReceived?.Invoke(this, new CompilerEventArgs(e.Data));
                        outputMessage.AppendLine(e.Data);
                        if (e.Data.IndexOf(": error") > 0)
                            errorMessage.Add(e.Data);
                    }
                };

            try
            {
                await p.WaitForExitAsync();
            }
            catch (Exception ex)
            {
                throw new Exception("Can't compile", ex);
            }

            if (p.ExitCode != 0)
            {
                throw new CompilationExeption(outputMessage.ToString(), errorMessage);
            }

            return fileName;
        }

Файлы из C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7 лучше с собой таскать.

2) Если тебе нужно именно между процессами общаться то пайпы, WCF, shared memory и прочее. Можешь даже UDP пакет слать на LocalHost. Вариантов масса - всё зависит от целевых ОС и прочих особенностей.
Если тебе надо в рамках одного процесса общаться между AppDomain'ами то засовываешь в них прокси-объект унаследованный от MarshalByRefObject  и дёргаешь его методы.

#2
9:55, 6 дек. 2016

Я бы посоветовал тебе IronPython, имхо даже с нуля его легче применить, чем шарповским методом воротить комбайн

#3
9:56, 6 дек. 2016

> Если тебе нужно именно между процессами общаться то пайпы, WCF, shared memory и прочее. Можешь даже UDP пакет слать на LocalHost. Вариантов масса - всё зависит от целевых ОС и прочих особенностей.

я сам выбрать не способен )) самое универсальное (в смысле на всех платформах будет работать) это наверное UDP слать, но открытие портов может потребовать всяких разрешений от юзера, так что его я бы не стал использовать

#4
11:36, 6 дек. 2016

GLoom, ты вручную компилятор запускаешь, а есть класс CodeDomProvider для этого https://habrahabr.ru/post/110999/ :)

#5
13:15, 6 дек. 2016

1vanK
Да, ты чертовски прав.

Естт еще отличная книжка "метапрограммирование на .net" (кажется так). Там рассматриваются варианты кодогенерации разные.

Кроме питона есть еще всякие Aluminium Lua и т.п. да и в самой урхе же была lua интеграция. Может ее задействовать?

#6
13:40, 6 дек. 2016

ох подозреваю что велосипед какой-то пишешь :D
Межпроцессами да, пайпы. Если нужен бродкаст - может лучше написать отдельный процесс-сервак для остальных? :)
Либо может есть какой аналог ServiceBus для таких целей, но это пушкой по воробьям :)
Скриптинг на шарпе можно посмотреть на CSX (scripting api) вместо велосипедов с компиляции и аппдомейном. Напиши что ты вообще хочешь сделать? :)

#7
13:48, 6 дек. 2016

> Напиши что ты вообще хочешь сделать? :)

MUD-клиент, если это это о чем-то говорит )

#8
13:53, 6 дек. 2016

> Скриптинг на шарпе можно посмотреть на CSX (scripting api) вместо велосипедов с компиляции и аппдомейном.

чего это?

#9
17:10, 6 дек. 2016

Чем больше копаюсь, тем меньше понимаю. Я хочу использовать отдельный домен для плагина, чтобы его можно было выгрузить. Но чтобы дернуть функцию из плагина мне нужно загрузить сборку и в главный домен и в созданный. А из главного домена выгрузить сборку нельзя. И в чём смысл?

#10
17:19, 6 дек. 2016

Плагин должен загрузить общую DLL какую то с интерфейсами и т.п. А дальше через  MarshalByRefObject надо инстанцировать объект так чтоб в одном домене он был настоящим а в другом через ссылку. Какой где сообразить не могу - приболел и плохо соображаю.

#11
17:48, 6 дек. 2016
MUD-клиент
http://stackoverflow.com/questions/14974404/socket-programming-mu… nt-one-server

...
https://habrahabr.ru/post/242209/

#12
17:55, 6 дек. 2016

Ух как все запутано то...

Вот у меня есть приложение: в нем есть поле ввода и поле вывода.
И мне нужно загружать и выгружать какой-то скрипт. В скрипт я передаю то, что было введено в поле ввода. Скрипт это как-то обрабатывает в своем домене и вызывает разные функции уже в домене приложения (например вывод в поле вывода).

Как мне изплагина выполнять функции в главном домене? Я ведь не могу в плагине сделать CreateInstanceFromAndUnwrap, потому что в главном домене уже есть экземпляр.

#13
18:07, 6 дек. 2016

Zamir
> https://habrahabr.ru/post/242209/
я весь день седня гуглю и уж первую ссылку в гугле я точно видел))
и она мне не помогает )

#14
18:43, 6 дек. 2016
я весь день седня гуглю и уж первую ссылку в гугле я точно видел))
тот неловкий момент, когда от души хочешь помочь и не можешь)
Страницы: 1 2 Следующая »
Urho3DФорумURHOSHARP

Тема в архиве.