执行从 C# 到 EuroTruck 的密钥输出不起作用(PostMessage、user32.dll)

Posted

技术标签:

【中文标题】执行从 C# 到 EuroTruck 的密钥输出不起作用(PostMessage、user32.dll)【英文标题】:Performing Key Output from C# to EuroTruck not working (PostMessage, user32.dll) 【发布时间】:2019-08-02 02:49:02 【问题描述】:

我正在尝试让我的 C# 脚本输出到 ets2 以便它为我驱动 (wasd)。为了测试,我使用空格键。我已经在 chrome 和记事本中测试了代码,它可以在其中工作并留出空间。有人知道出了什么问题吗?

更新: 我使用键盘模块为 python 编写了一些测试代码,并让它工作。是否可以将“空格”变成我可以从 C# 更改的变量?

Python 代码:

import keyboard, time
time.sleep(5)
keyboard.press_and_release("space")

Spy++ 中的线程和窗口:

我使用以下代码:

    public const int WM_KEYDOWN = 0x0100;
    const int VK_SPACE = 0x20;
    static void Main(string[] args)
    
        System.Threading.Thread.Sleep(2000); // gives user time to switch tabs
        IntPtr programloc = WindowHelper.GetForegroundWindow();
        // I also tried using (from Spy++) FindWindow("Euro Truck Simulator 2", "prism3d");
        if (programloc == IntPtr.Zero) throw new SystemException();
        WindowHelper.PostMessage(programloc, WM_KEYDOWN, VK_SPACE, 0);
    

以及以下模块 WindowHelper(多个 *** 和 docs.microsoft 页面的组合):

class WindowHelper

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern IntPtr FindWindow(
        string lpClassName,
        string lpWindowName);

    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern IntPtr FindWindowEx(
                IntPtr hwndParent,
                IntPtr hwndChildAfter,
                string lpszClass,
                string lpszWindos);

    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    [DllImport("User32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
    public static extern IntPtr GetForegroundWindow();

【问题讨论】:

【参考方案1】:

我自己已经找到了一个(临时)修复方法。但是,此修复对性能不是很友好。欢迎大家有更好的建议。

使用我在问题中描述的键盘功能,我制作了一个使用参数的 python 脚本。此 python 脚本由 C# 脚本使用以下代码启动:

static public string run_python(string cmd, string args)
    
        ProcessStartInfo start = new ProcessStartInfo();
        start.FileName = @"C:\Users\Stijn\AppData\Local\Programs\Python\Python36\python.exe";
        start.Arguments = string.Format("\"0\" \"1\"", cmd,args);
        start.UseShellExecute = false;// Do not use OS shell
        start.CreateNoWindow = true; // We don't need new window
        start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
        start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
        using (Process process = Process.Start(start))
        
            using (StreamReader reader = process.StandardOutput)
            
                string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
                string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
                return result + stderr;
            
        
    

python代码包括:

from keyboard import press_and_release
from sys import argv as args
for i in range(len(args)-1):
    press_and_release(args[i+1])

使用可在https://pypi.org/project/keyboard/ 找到的键盘模块

【讨论】:

【参考方案2】:

您的代码将立即退出。这是故意的吗?在 main 结束时调用 Console.Readline() 以阻止,直到您提供控制台输入。

【讨论】:

我会试试这个,但是网站上显示的代码是一个简化版本,我已经删除了很多不必要的代码。例如,Windows 窗体也会在尝试按空格键后启动。因此,它在尝试按空格键后不会很快终止。

以上是关于执行从 C# 到 EuroTruck 的密钥输出不起作用(PostMessage、user32.dll)的主要内容,如果未能解决你的问题,请参考以下文章

C# RSA 公钥输出不正确

使用 C# 从 Azure Blob 复制到 AWS S3

C# 将私有/公共 RSA 密钥从 RSACryptoServiceProvider 导出到 PEM 字符串

通过 C# 在 Redis 中放置一个密钥

如何从 C# 中的 Azure 函数在设备中执行方法?

如何从 C# 代码轮换 Azure 存储帐户访问密钥?