C#判断程序是由Windows服务启动还是用户启动

      在Windows系统做网络开发,很多时候都是使用Windows服务的模式,但在调度阶段,我们更多的是使用控制台的模式。在开发程序的时候,我们在Program的Main入口进行判断。最初开始使用Environment.UserInteractive属性,在系统不系统服务的交互模式时,程序运行是正常的,但试过有Win7下,系统允许交互模式,结果在服务启动的时候,跳转到控制台的模式了,服务启动不起来。只能在服务的调用方式下带参数,然后在Main的参数中判断是否为服务方式。这在一般的情况下是可以解决问题的。

      后来有好几个项目,使用了开源的Socket框架,框架本身是通过配置来启动服务的,这样,就没有经过用户的Main方法了,启动带参数的方法不行了,如果为了判断启动模式而加单独的配置,不是很好的做法,通过Program加全局标识是可以解决程序自身启动同框架启动的判断,但服务如果是通过自身的Main启动,又只能靠加参数的方法了,整个实现感觉都是有点别扭。

      在几次的服务程序开发中,遇到一个写文件的路径问题,即取路径总是不对,通过分析,Windows服务启动时的环境默认路径是从System32目录,可能是Windows服务的宿主程序是从这开始的吧,这就有了解决如何判断启动模式的方法了。主要是通过宿主程序是程序集所在的目录来判断。具体如下 :

  string curPath = System.Environment.CurrentDirectory;
  string basePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
  bool isRunWinService = (curPath != basePath);

如果两个路径不相同,我就认为是启动Windows服务了。我们只要在程序的开始做判断,这样Environment.CurrentDirectory的路径还是宿主程序,一般来说,开发人员很少去改动Environment.CurrentDirectory的。这样我们做好的Exe程序支持用户启动,服务启动,或框架自动的服务管理等模式了。

 

2024-08-13 08:52:01【出处】:https://www.cnblogs.com/Yjianyong/p/5560442.html

=======================================================================================

C# 当前进程是否为控制台窗口

WPF应用程序,在VS的项目属性中,可以设置输出类型:

那我们在代码中,如何判断应用的类型呢。有没有控制台?是否Windows应用程序还是控制台应用程序?

Kernel32下函数GetConsoleWindow可以解决这个问题:

[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();

复制代码
1     var consoleWindowHandle = GetConsoleWindow();
2     if (consoleWindowHandle == IntPtr.Zero)
3     {
4         Debug.WriteLine("输出类型为 Windows应用程序");
5     }
6     else
7     {
8         Debug.WriteLine("输出类型为 控制台应用程序");
9     }
复制代码

另外,如果需要判断控制台应用程序内,主窗口是否为控制台,可以根据窗口句柄来确认:

复制代码
 1     var consoleWindowHandle = GetConsoleWindow();
 2     var mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
 3 
 4     if (consoleWindowHandle == IntPtr.Zero)
 5     {
 6         Debug.WriteLine("输出类型为 Windows应用程序");
 7     }
 8     else if (consoleWindowHandle == mainWindowHandle)
 9     {
10         Debug.WriteLine("输出类型为 控制台应用程序,主窗口也是控制台窗口");
11     }
12     else
13     {
14         Debug.WriteLine("输出类型为 控制台应用程序,但主窗口为Windows窗口");
15     }
复制代码

我们设置输出类型为控制台应用,并在ShowMainWindow前后,输出结果,验证okay:

注:这里输出到VS控制台,是因为使用了Debug类型。如果是Console.Write,程序会优先输出到控制台窗口内。

 

如果需要在Windows应用程序下,使用控制台窗口输出日志。可以使用AllocConsole:

    [DllImport("kernel32.dll")]
    static extern bool AllocConsole();

AllocConsole,可以创建控制台窗口。bool返回值,true表示之前没有控制台窗口、创建成功,false表示已经有控制台窗口、创建失败。

 

 

2024-08-13 08:52:30【出处】:https://www.cnblogs.com/kybs0/p/17273872.html

=======================================================================================

c#如何判断是Windows应用程序还是控制台应用程序

在C#中,您可以通过检查当前应用程序的Main方法的参数来判断是Windows应用程序还是控制台应用程序。对于控制台应用程序,Main 方法通常有一个 string[] args 参数;而对于Windows应用程序,Main 方法位于一个形为 Application 的类中,并且通常没有参数。

以下是一个简单的示例代码,用于判断当前应用程序是控制台应用程序还是Windows应用程序:

using System;
namespace AppTypeChecker
{
class Program
{
static void Main(string[] args)
{
if (args != null && args.Length > 0)
{
Console.WriteLine("这是一个控制台应用程序。");
}
else
{
Console.WriteLine("这是一个Windows应用程序。");
}
}
}
}

如果您的应用程序是通过命令行启动的,并且带有参数,那么它是控制台应用程序。否则,它可能是Windows应用程序。需要注意的是,这种方法并不完美,因为某些情况下可能需要更复杂的检查。但对于大多数简单的场景,上述代码应该足够使用。

提示:AI自动生成,仅供参考

=======================================================================================

另外,还有一些其他的方式方法进行判断,以下供参考:

-------------------------------------------------------

可能需要尝试Process对象的SessionId属性。根据我的经验,如果进程正在运行服务,则将SessionId设置为0。

-------------------------------------------------------

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;

IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

if (iStdOut == IntPtr.Zero)

{
app.RunAsWindowsService = true;

}

// Run as Service
if (runAsWindowsService)
{
// .....
ServiceBase.Run(myService);
}
else
{
// Run as Console
// Register Ctrl+C Handler...
}
-------------------------------------------------------
使用this answer中关于查找父进程的ParentProcessUtilities结构,您可以执行以下操作:
static bool RunningAsService() {
var p = ParentProcessUtilities.GetParentProcess();
return ( p != null && p.ProcessName == "services" );
}
请注意,父进程的进程名称不包括扩展名".exe“。

-------------------------------------------------------
我不知道这是否有效,但您可能想尝试在this代码中使用PInvoke,并检查父对象是否为"services.exe“。
-------------------------------------------------------
我最终通过检查Console.IsErrorRedirected来检测我是否在控制台应用程序中。对于控制台应用程序,它返回"false“,对于我测试的非控制台应用程序,它返回"true”。我也可以使用IsOutputRedirected。
我想在某些情况下,这些并不准确,但这对我来说效果很好。

 

 

出处:https://cloud.tencent.com/developer/ask/sof/102504823

======================================================================

c# 在Windowns应用程序如何使用console

在Windows应用程序中使用Console通常是指在Windows Forms或WPF应用程序中模拟控制台输入输出。这可以通过AllocConsole函数在程序启动时分配一个新的控制台,并通过FreeConsole在需要时释放它。

以下是一个简单的示例,展示如何在Windows Forms应用程序中使用控制台:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
public class ConsoleInWPF : Form
{
    [DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
 
    [DllImport("kernel32.dll")]
    private static extern bool FreeConsole();
 
    public ConsoleInWPF()
    {
        // 分配控制台
        AllocConsole();
 
        // 写入到控制台
        Console.WriteLine("Hello, Console!");
 
        // 在此处添加其他初始化代码...
    }
 
    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        base.OnFormClosed(e);
        // 窗体关闭时释放控制台
        FreeConsole();
    }
 
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new ConsoleInWPF());
    }
}

在这个例子中,AllocConsole在窗体构造函数中被调用,从而在应用程序启动时为它分配一个控制台。然后,你可以使用Console.WriteLine等方法来写入到这个控制台。在窗体关闭时,通过FreeConsole释放控制台资源。

请注意,这种方法并不是在所有情况下都适用,例如,如果你的应用程序是基于.NET Core的,或者你正在使用更现代的项目模板,可能需要不同的方法来实现控制台输入输出。

提示:AI自动生成,仅供参考
 
 

posted on 2024-08-13 08:54  jack_Meng  阅读(25)  评论(0编辑  收藏  举报

导航