如何从C#系统托盘应用程序中将C程序作为线程运行?

我有一个C控制台应用程序,它曾经在 WindowsCMD 终端中运行,并获取用户按键输入。但是现在需要将其移动到后台并且不需要用户输入。

我创建了一个系统托盘,通过右键单击退出并右键单击即可正确实现。并有一个功能的终端程序。

我希望能够创建一个调用我现有程序中不需要终端的函数的线程,而不是重新编写程序。

只是强调控制台交互方面已从代码中删除,因为应用程序响应击键等。希望这有点澄清事情。

Question: Is this possible? And how would I be able to implement this?

(我一般不是使用更多嵌入式C的PC程序员,所以.NET对我来说很陌生。非常感谢任何帮助)

2
没有足够的细节来回答......但是你的.NET程序有可能在后台启动你的控制台应用程序。
额外 作者 Keith Nicholas,
没有足够的细节来回答......但是你的.NET程序有可能在后台启动你的控制台应用程序。
额外 作者 Keith Nicholas,
没有足够的细节来回答......但是你的.NET程序有可能在后台启动你的控制台应用程序。
额外 作者 Keith Nicholas,
托盘应用程序可以启动该过程
额外 作者 Keith Nicholas,
托盘应用程序可以启动该过程
额外 作者 Keith Nicholas,
托盘应用程序可以启动该过程
额外 作者 Keith Nicholas,
@rodrigogq - 对不起男士。我可能给你了不好的建议。从他的问题来看,他只是想要能够从C程序中调用函数。如果你的答案适合他,那它肯定更简单,你应该得到答案。无论如何,我赞成你的回答。
额外 作者 Icemanind,
@HarryJohnston - 他甚至不需要将它重建为DLL。您仍然可以在EXE文件中导出函数。但它作为DLL确实更有意义
额外 作者 Icemanind,
@HarryJohnston - 他甚至不需要将它重建为DLL。您仍然可以在EXE文件中导出函数。但它作为DLL确实更有意义
额外 作者 Icemanind,
@HarryJohnston - 他甚至不需要将它重建为DLL。您仍然可以在EXE文件中导出函数。但它作为DLL确实更有意义
额外 作者 Icemanind,
我认为为了做到这一点,必须使用 _declspec(dllexport)之类的东西导出C程序中的函数。
额外 作者 Icemanind,
我认为为了做到这一点,必须使用 _declspec(dllexport)之类的东西导出C程序中的函数。
额外 作者 Icemanind,
我认为为了做到这一点,必须使用 _declspec(dllexport)之类的东西导出C程序中的函数。
额外 作者 Icemanind,
@rodrigogq - 从他的问题,他说“我希望能够创建一个调用我现有程序中的函数的线程”。
额外 作者 Icemanind,
@rodrigogq - 对不起男士。我可能给你了不好的建议。从他的问题来看,他只是想要能够从C程序中调用函数。如果你的答案适合他,那它肯定更简单,你应该得到答案。无论如何,我赞成你的回答。
额外 作者 Icemanind,
@rodrigogq - 对不起男士。我可能给你了不好的建议。从他的问题来看,他只是想要能够从C程序中调用函数。如果你的答案适合他,那它肯定更简单,你应该得到答案。无论如何,我赞成你的回答。
额外 作者 Icemanind,
@rodrigogq - 从他的问题,他说“我希望能够创建一个调用我现有程序中的函数的线程”。
额外 作者 Icemanind,
@rodrigogq - 从他的问题,他说“我希望能够创建一个调用我现有程序中的函数的线程”。
额外 作者 Icemanind,
是的,最好的方法是将你的C程序重建为导出一个或多个函数的DLL。我很确定你可以从C#调用任意DLL,虽然我不熟悉这个方法。
额外 作者 Harry Johnston,
是的,最好的方法是将你的C程序重建为导出一个或多个函数的DLL。我很确定你可以从C#调用任意DLL,虽然我不熟悉这个方法。
额外 作者 Harry Johnston,
是的,最好的方法是将你的C程序重建为导出一个或多个函数的DLL。我很确定你可以从C#调用任意DLL,虽然我不熟悉这个方法。
额外 作者 Harry Johnston,
@rodrigogq似乎我会重建为DLL。 Rodrigogq你提到我可能刚刚开始并退出这个过程,我怎么能在语法上做到这一点,因为这对我来说就像最简单的选择?或者这不是一个好主意?
额外 作者 Luke,
@icemanind您好我可能会导出到DLL。但是,有任何理由不能仅仅能够启动和退出该过程。我确实说我想从一个线程调用我的函数,但是如果可以在后台启动C应用程序(不打开终端),并用系统应用程序关闭它我看不清楚为什么我会不这样做......谢谢
额外 作者 Luke,
@icemanind您好我可能会导出到DLL。但是,有任何理由不能仅仅能够启动和退出该过程。我确实说我想从一个线程调用我的函数,但是如果可以在后台启动C应用程序(不打开终端),并用系统应用程序关闭它我看不清楚为什么我会不这样做......谢谢
额外 作者 Luke,
@icemanind您好我可能会导出到DLL。但是,有任何理由不能仅仅能够启动和退出该过程。我确实说我想从一个线程调用我的函数,但是如果可以在后台启动C应用程序(不打开终端),并用系统应用程序关闭它我看不清楚为什么我会不这样做......谢谢
额外 作者 Luke,
Encase任何一个感兴趣的人:我实施了rodrigogq和icemanind解决方案; -rodrigogq解决方案使用Process.Start非常容易实现(一个有用的相关链接 stackoverflow.com/questions/3847330/… 开始 - 但在正确关闭进程时受到限制。 -icemanind解决方案难以实现,在控制方面具有优势(例如,如果写入文件需要)我在这种情况下使用了rodrigogq解决方案但是肯定有类似情况使用DLL更合适
额外 作者 Luke,
Encase任何一个感兴趣的人:我实施了rodrigogq和icemanind解决方案; -rodrigogq解决方案使用Process.Start非常容易实现(一个有用的相关链接 stackoverflow.com/questions/3847330/… 开始 - 但在正确关闭进程时受到限制。 -icemanind解决方案难以实现,在控制方面具有优势(例如,如果写入文件需要)我在这种情况下使用了rodrigogq解决方案但是肯定有类似情况使用DLL更合适
额外 作者 Luke,
icemanind和rodrigogq都提出了很好的答案,看起来它们将成为解决我问题的方法。我将在周一更新并说明我选择了哪个选项以及实施起来有多容易。
额外 作者 Luke,
icemanind和rodrigogq都提出了很好的答案,看起来它们将成为解决我问题的方法。我将在周一更新并说明我选择了哪个选项以及实施起来有多容易。
额外 作者 Luke,
icemanind和rodrigogq都提出了很好的答案,看起来它们将成为解决我问题的方法。我将在周一更新并说明我选择了哪个选项以及实施起来有多容易。
额外 作者 Luke,
@rodrigogq似乎我会重建为DLL。 Rodrigogq你提到我可能刚刚开始并退出这个过程,我怎么能在语法上做到这一点,因为这对我来说就像最简单的选择?或者这不是一个好主意?
额外 作者 Luke,
@rodrigogq它不再指望任何类型的用户输入
额外 作者 Luke,
@rodrigogq它不再指望任何类型的用户输入
额外 作者 Luke,
@rodrigogq它不再指望任何类型的用户输入
额外 作者 Luke,
让我重新说明一下。道歉。
额外 作者 Luke,
让我重新说明一下。道歉。
额外 作者 Luke,
C程序太模糊了。我猜你的意思是用C 编写的控制台应用程序,在这种情况下答案是 no ,控制台应用程序无法在没有修改的情况下作为托盘应用程序运行;它必须至少有一个窗口句柄和一个消息循环,以便接收控制台应用程序没有的通知。
额外 作者 Ken White,
C程序太模糊了。我猜你的意思是用C 编写的控制台应用程序,在这种情况下答案是 no ,控制台应用程序无法在没有修改的情况下作为托盘应用程序运行;它必须至少有一个窗口句柄和一个消息循环,以便接收控制台应用程序没有的通知。
额外 作者 Ken White,
@Keith:这不是一个托盘应用程序,这就是问题所在。
额外 作者 Ken White,
@Keith:这不是一个托盘应用程序,这就是问题所在。
额外 作者 Ken White,
@Keith:这不是一个托盘应用程序,这就是问题所在。
额外 作者 Ken White,
如果他想要开始并退出这个过程,我不明白为什么他需要走到这么远的地方。只需启动..并在用户要求退出时退出。我在这里错过了什么吗?关于框不必询问终端版本或类似的东西。他们是分开的东西。
额外 作者 rodrigogq,
卢克,您的C程序是否期望任何击键王,用户输入?
额外 作者 rodrigogq,
卢克,您的C程序是否期望任何击键王,用户输入?
额外 作者 rodrigogq,
如果他想要开始并退出这个过程,我不明白为什么他需要走到这么远的地方。只需启动..并在用户要求退出时退出。我在这里错过了什么吗?关于框不必询问终端版本或类似的东西。他们是分开的东西。
额外 作者 rodrigogq,
如果他想要开始并退出这个过程,我不明白为什么他需要走到这么远的地方。只需启动..并在用户要求退出时退出。我在这里错过了什么吗?关于框不必询问终端版本或类似的东西。他们是分开的东西。
额外 作者 rodrigogq,
@icemanind没关系!我也从你的代码中学到了! :)
额外 作者 rodrigogq,
@icemanind谢谢。然后我删除了我的答案。无论如何,出口是一个很好的选择。
额外 作者 rodrigogq,
@icemanind谢谢。然后我删除了我的答案。无论如何,出口是一个很好的选择。
额外 作者 rodrigogq,
@Luke我取消了我的答案以供参考。如果你没有打电话,只需跑步,试试吧。
额外 作者 rodrigogq,
@Luke我取消了我的答案以供参考。如果你没有打电话,只需跑步,试试吧。
额外 作者 rodrigogq,
@Luke我取消了我的答案以供参考。如果你没有打电话,只需跑步,试试吧。
额外 作者 rodrigogq,
@icemanind没关系!我也从你的代码中学到了! :)
额外 作者 rodrigogq,
@icemanind没关系!我也从你的代码中学到了! :)
额外 作者 rodrigogq,

7 答案

我不确定这是不是你问的问题,但是如果你问你是否可以从C#应用程序调用C程序中的函数,那么你可以。只要你有C程序的源代码。为了使C语言中的函数可用于C#程序,必须导出它们。我会告诉你一个例子:

MyAddDll.h

#include 

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

这里重要的是你的函数包含在 extern“C”块中。基本上,这告诉编译器不要破坏你的函数名称。另一个重要的部分是 __ declspec(dllexport)。这告诉编译器您要导出此函数,以便可以从另一个程序(如C#程序)调用它。

MyAddDll.cpp

#include 
#include "MyAddDll.h"

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

同样,您的代码包含在 extern“C”块中,您需要将 __ declspec(dllexport)添加到该函数中。现在您可以将其编译为DLL文件或EXE文件。现在从C#调用它,它很直接:

MyProgram.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位。它们必须使用相同的位长度。

4
额外
@Luke - 包含您希望能够在C#中调用的函数的任何C文件都需要打包
额外 作者 Icemanind,
@Luke - 另一件事。我假设您的C程序是使用Microsoft的Visual Studio编译的。如果这不正确,请告诉我,我会更新我的答案。 __ declspec(dllexport)仅存在于Microsoft的编译器中。对于任何其他编译器,我们必须创建一个export.def文件。
额外 作者 Icemanind,
嗨,谢谢你非常有帮助。如果我有多个C文件,它们都需要包装在DLL中,或者如果我将main包装为DLL,它可以调用其他C文件吗?
额外 作者 Luke,
谢谢。这应该有助于实施变更。干杯
额外 作者 Luke,
我正在使用Microsoft Visual Studio的最新免费版本。
额外 作者 Luke,

如上所述,您可以使用C#应用程序托盘中的 Process.Start

   //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-我们/库/ 53ezey2s(v = vs.110)的.aspx

You could try launching it on a hidden state: http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle(v=vs.110).aspx

一些程序员告诉要小心。如果需要任何输入,那么您的过程可能会停止。确保没有真正停止你的程序。

您可以尝试使用 Process.Start 启动 cmd 命令,但我会说它太多了。如果没有C#托盘应用程序控件,这将启动另一个进程:

 Process.Start("start /min cmd /c mycommand");
3
额外
我并非100%确定他想要调用他的可执行文件。我想他可能想调用特定的函数或编译成可执行文件的特定函数。
额外 作者 Icemanind,
@rodrigogq我认为对我的问题更好的解决方案是创建一个调用DLL函数的线程。虽然您的答案我可以用于稍微不同的应用程序,但我也需要自动化。干杯
额外 作者 Luke,

如上所述,您可以使用C#应用程序托盘中的 Process.Start

   //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-我们/库/ 53ezey2s(v = vs.110)的.aspx

You could try launching it on a hidden state: http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle(v=vs.110).aspx

一些程序员告诉要小心。如果需要任何输入,那么您的过程可能会停止。确保没有真正停止你的程序。

您可以尝试使用 Process.Start 启动 cmd 命令,但我会说它太多了。如果没有C#托盘应用程序控件,这将启动另一个进程:

 Process.Start("start /min cmd /c mycommand");
3
额外
我并非100%确定他想要调用他的可执行文件。我想他可能想调用特定的函数或编译成可执行文件的特定函数。
额外 作者 Icemanind,
@rodrigogq我认为对我的问题更好的解决方案是创建一个调用DLL函数的线程。虽然您的答案我可以用于稍微不同的应用程序,但我也需要自动化。干杯
额外 作者 Luke,

如上所述,您可以使用C#应用程序托盘中的 Process.Start

   //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-我们/库/ 53ezey2s(v = vs.110)的.aspx

You could try launching it on a hidden state: http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle(v=vs.110).aspx

一些程序员告诉要小心。如果需要任何输入,那么您的过程可能会停止。确保没有真正停止你的程序。

您可以尝试使用 Process.Start 启动 cmd 命令,但我会说它太多了。如果没有C#托盘应用程序控件,这将启动另一个进程:

 Process.Start("start /min cmd /c mycommand");
3
额外
我并非100%确定他想要调用他的可执行文件。我想他可能想调用特定的函数或编译成可执行文件的特定函数。
额外 作者 Icemanind,
@rodrigogq我认为对我的问题更好的解决方案是创建一个调用DLL函数的线程。虽然您的答案我可以用于稍微不同的应用程序,但我也需要自动化。干杯
额外 作者 Luke,

您可以通过System.Diagnostics.Process从.NET代码启动您的C程序。它将在一个单独的过程中运行。

您也可以从.NET代码中删除该进程

1
额外
该问题询问系统托盘应用程序,它与通过 Process 启动的控制台应用程序不同。
额外 作者 Ken White,

您可以通过System.Diagnostics.Process从.NET代码启动您的C程序。它将在一个单独的过程中运行。

您也可以从.NET代码中删除该进程

1
额外
该问题询问系统托盘应用程序,它与通过 Process 启动的控制台应用程序不同。
额外 作者 Ken White,

您可以通过System.Diagnostics.Process从.NET代码启动您的C程序。它将在一个单独的过程中运行。

您也可以从.NET代码中删除该进程

1
额外
该问题询问系统托盘应用程序,它与通过 Process 启动的控制台应用程序不同。
额外 作者 Ken White,