Как запустить программу C в виде потока из приложения C# в системном трее?

У меня есть консольное приложение C, которое раньше запускалось на переднем плане в терминале CMD в Windows и принимало нажатия клавиш пользователя. Однако теперь его необходимо переместить на задний план и не требует ввода данных пользователем.

Я создал системный трей, который правильно реализован с правым щелчком мыши «выход» и «правый клик о». И есть терминальная программа, которая выполняет эту функцию.

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

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

Вопрос: Возможно ли это? И как я смогу это реализовать?

(Как правило, я не программист для ПК, использующий больше встроенного C, поэтому .NET для меня довольно чужд. Любая помощь очень ценится)


person Luke    schedule 19.12.2014    source источник
comment
Программа C слишком расплывчата. Я предполагаю, что вы имеете в виду консольное приложение, написанное на C, и в этом случае ответ нет, консольное приложение не может быть запущено как приложение в трее без изменений; у него должен быть как минимум дескриптор окна и цикл сообщений, чтобы получать уведомления, которых нет в консольных приложениях.   -  person Ken White    schedule 19.12.2014
comment
недостаточно подробностей для ответа.... но ваша программа .NET может запускать консольное приложение в фоновом режиме.   -  person Keith Nicholas    schedule 19.12.2014
comment
@Keith: Однако это не приложение для лотка, о чем и задается вопрос.   -  person Ken White    schedule 19.12.2014
comment
приложение в трее может запустить процесс   -  person Keith Nicholas    schedule 19.12.2014
comment
Люк, ваша программа на C ожидает какого-либо нажатия клавиш, пользовательского ввода?   -  person rodrigogq    schedule 19.12.2014
comment
Позвольте мне перефразировать это, чтобы быть более ясным. Извинения.   -  person Luke    schedule 19.12.2014
comment
@rodrigogq больше не ожидает никакого пользовательского ввода   -  person Luke    schedule 19.12.2014
comment
Я думаю, чтобы сделать это, функции в вашей программе C должны быть экспортированы с помощью чего-то вроде _declspec(dllexport)   -  person Icemanind    schedule 19.12.2014
comment
Да, лучший способ — это почти наверняка перестроить вашу программу на C как DLL, которая экспортирует одну или несколько функций. Я почти уверен, что вы можете вызывать произвольные библиотеки DLL из C#, хотя я не знаком с этим методом.   -  person Harry Johnston    schedule 19.12.2014
comment
Если он хочет просто начать и выйти из процесса, я не понимаю, почему ему нужно заходить так далеко.. Просто начать.. и выйти, когда пользователь попросит выйти. Я что-то упустил здесь? Поле about не должно запрашивать терминальную версию или что-то в этом роде. Это отдельные вещи.   -  person rodrigogq    schedule 19.12.2014
comment
@HarryJohnston - ему даже не нужно было бы перестраивать его как DLL. Вы по-прежнему можете экспортировать функции в EXE-файл. Но это имеет больше смысла как DLL   -  person Icemanind    schedule 19.12.2014
comment
@rodrigogq - Из своего вопроса он заявляет, что я хотел бы иметь возможность создать поток, который вызывает функции из моей существующей программы.   -  person Icemanind    schedule 19.12.2014
comment
@icemanind спасибо. Затем я удалил свой ответ. В любом случае, экспорт - хороший вариант.   -  person rodrigogq    schedule 19.12.2014
comment
@rodrigogq Кажется, я перестрою как DLL. Родригогк, вы упомянули, что я могу просто запустить и выйти из процесса, как я могу синтаксически сделать это, поскольку это звучит для меня как самый простой вариант? Или это не очень хорошая идея?   -  person Luke    schedule 19.12.2014
comment
@icemanind Привет, я, вероятно, буду экспортировать в DLL. Однако есть ли какая-либо причина, по которой нельзя просто запустить и выйти из процесса. Я сказал, что хотел вызвать свои функции из потока, однако, если можно просто запустить приложение C (без открытия терминала) в фоновом режиме и закрыть его с помощью системного приложения, я не понимаю, почему я бы не делай так... Спасибо   -  person Luke    schedule 19.12.2014
comment
@ Люк, я восстановил свой ответ для справки. Если вы ничего не звоните, просто работаете, попробуйте это.   -  person rodrigogq    schedule 19.12.2014
comment
@rodrigogq - Извини, чувак. Я мог дать тебе плохой совет. Из его вопроса просто звучало, что он хочет иметь возможность вызывать функции из программы на C. Если ваш ответ работает для него, он определенно проще, и вы заслуживаете признания ответа. Я проголосовал за ваш ответ, в любом случае.   -  person Icemanind    schedule 19.12.2014
comment
@icemanin, неважно! Я тоже узнал из вашего кода! :)   -  person rodrigogq    schedule 19.12.2014
comment
icemanind и rodrigogq предложили хорошие ответы, которые, похоже, будут решением моей проблемы. Я обновлю в понедельник и скажу, какой вариант я выбрал и насколько легко их было реализовать.   -  person Luke    schedule 19.12.2014
comment
Если кому-то было интересно: я реализовал решения как rodrigogq, так и icemanind; Решение -rodrigogq для использования Process.Start было невероятно легко реализовать (полезная связанная ссылка: stackoverflow.com/questions/3847330/) - однако был ограничен, когда дело доходит до правильного закрытия процесса. Решение -icemanind было сложнее реализовать, оно имело преимущества с точки зрения контроля (например, необходимо при записи в файл).   -  person Luke    schedule 22.12.2014


Ответы (3)


Как уже было сказано, вы можете использовать Process.Start из панели приложений C#.

    // Uses the ProcessStartInfo class to start new processes, 
    // both in a minimized mode. 
    void OpenWithStartInfo()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
        startInfo.WindowStyle = ProcessWindowStyle.Minimized;

        Process.Start(startInfo);

        startInfo.Arguments = "www.northwindtraders.com";

        Process.Start(startInfo);
    }

http://msdn.microsoft.com/en-us/library/53ezey2s(v=vs.110).aspx

Вы можете попробовать запустить его в скрытом состоянии: http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle(v=vs.110).aspx

Некоторые программисты советуют быть осторожными. Если ожидается какой-либо ввод, то, вероятно, ваш процесс может остановиться. убедитесь, что ничто на самом деле не останавливает вашу программу.

Вы также можете попробовать запустить команду cmd с Process.Start, но я бы сказал, что это слишком. Это запустит другой процесс без вашего управления приложением в трее С#:

 Process.Start("start /min cmd /c mycommand");
person rodrigogq    schedule 19.12.2014
comment
Я не уверен на 100%, что он хочет назвать свой исполняемый файл. Я думаю, что он может захотеть вызвать определенную функцию или определенные функции, которые скомпилированы в его исполняемый файл. - person Icemanind; 19.12.2014
comment
@rodrigogq Я думаю, что лучшим решением моей проблемы является создание потока, который вызывает функции DLL. Хотя ваш ответ я мог бы использовать для немного другого приложения, которое мне также нужно автоматизировать. Ваше здоровье - person Luke; 19.12.2014

Я не уверен, что это то, о чем вы спрашиваете, но если вы спрашиваете, можете ли вы вызывать функции из своей программы на C из приложения на C#, то вы можете. Пока у вас есть исходный код вашей программы на C. Чтобы функции на C были доступны программе на C#, их необходимо экспортировать. Я покажу вам пример:

MyAddDll.h

#include <iostream>

extern "C"
{
    __declspec(dllexport) int Add(int a, int b);
}

Здесь важно то, что ваша функция заключена в блок extern "C". По сути, это говорит компилятору не изменять имя вашей функции. Другая важная часть — __declspec(dllexport). Это сообщает компилятору, что вы хотите экспортировать эту функцию, чтобы ее можно было вызывать из другой программы (например, вашей программы C#).

MyAddDll.cpp

#include <iostream>
#include "MyAddDll.h"

extern "C"
{
    __declspec(dllexport) int Add(int a, int b)
    {
        return (a + b);
    }
}

Опять же, ваш код заключен в блок extern "C", и вам нужно добавить __declspec(dllexport) в функцию. Теперь вы можете скомпилировать это либо в файл DLL, либо в файл EXE. Теперь, чтобы вызвать его из С#, это довольно просто:

МояПрограмма.cs

class Program
{
    [DllImport("c:\\PathToMyDllOrExeFile\\MyAddDll.dll")]
    public static extern int Add(int val1, int val2);

    static void Main(string[] args)
    {
        int val1 = 12;
        int val2 = 4;
        Console.WriteLine("{0} + {1} = {2}", val1, val2, Add(val1, val2));
    }
}

Это все, что есть!

Одна из «подводных камней» заключается в том, чтобы убедиться, что ваша программа на C и ваша программа на C# скомпилированы либо как 32-битные, либо как 64-битные. Вы не можете скомпилировать программу C как 64-битную, а программу C# как 32-битную. Они оба должны использовать одинаковую битовую длину.

person Icemanind    schedule 19.12.2014
comment
Привет, спасибо, это очень полезно. Если у меня есть несколько файлов C, все ли они должны быть обернуты в DLL, или если я оберну основной как DLL, может ли он вызвать другие файлы C? - person Luke; 19.12.2014
comment
@Luke - любые файлы C, содержащие функции, которые вы хотите вызывать на C#, должны быть завернуты - person Icemanind; 19.12.2014
comment
Спасибо. Это должно помочь в реализации изменений. Ваше здоровье - person Luke; 19.12.2014
comment
@ Люк - Еще одна вещь. Я сделал предположение, что ваша программа на C была скомпилирована с помощью Microsoft Visual Studio. Если это не так, дайте мне знать, и я обновлю свой ответ. __declspec(dllexport) существует только в компиляторе Microsoft. Для любого другого компилятора нам пришлось бы создать файл export.def. - person Icemanind; 19.12.2014
comment
Я использую последнюю бесплатную версию Microsoft Visual Studio. - person Luke; 19.12.2014

Вы можете запустить свою программу C из кода .NET через System.Diagnostics.Process. Он будет запущен в отдельном процессе.

Вы также можете убить процесс из кода .NET.

person Tien Dinh    schedule 19.12.2014
comment
Вопрос касается приложения на панели задач, которое отличается от консольного приложения, запускаемого через Process. - person Ken White; 19.12.2014