- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在构建一个非常简单的 win32 控制台应用程序,该应用程序用 C 编码并使用 Visual Studio 2010/2013 编译。它将有一个消息队列在与主线程不同的线程中运行。控制台将从 VBA 启动,然后通过 API 函数 PostThreadMessage
发送用户定义的消息。 .
我找到了一种根据控制台的进程 ID 获取所有线程 ID 的方法。但是,我还没有找到一种方法来识别正确的方法。我目前正在做的是将消息发送到所有控制台线程。在那条消息中,我通过VarPtr
传递一个指向我的VBA变量之一的指针作为LPARAM参数。功能。
线程正在接收消息,但应用程序在尝试将 id 写入 VBA 变量时崩溃。我知道可以将 VBA 变量指针传递给 DLL 函数。我过去曾在 API 函数 EnumWindows
中使用过这种方法。 。但是,我对 C 编程完全陌生,无法弄清楚如何在控制台代码中执行相同的操作。
以下是我为解决此问题所采取的步骤:
将以下代码添加到 Shell.c
#include <stdio.h>
#include <Windows.h>
#define WM_GET_ID WM_USER + 1
DWORD WINAPI MessageQueue(LPVOID n) {
MSG msg;
int *pVar;
BOOL MsgReturn;
DWORD dwThreadId = GetCurrentThreadId();
while (1) {
MsgReturn = GetMessage(&msg, NULL, WM_GET_ID, WM_GET_ID);
if (MsgReturn) {
switch (msg.message) {
case WM_GET_ID:
pVar = (int*)msg.lParam;
// Access violation writing location 0x0026F470
*pVar = (int)dwThreadId;
}
}
}
return 0;
}
int main() {
CreateThread(NULL, 0, MessageQueue, NULL, 0, NULL);
// Pause the console window to keep thread running
getchar();
return 0;
}
将代码编译为 ConsoleTest.exe
将以下代码添加到 PointerTest 模块
Option Explicit
Private Type THREADENTRY32
dwSize As Long
cntUsage As Long
th32ThreadID As Long
th32OwnerProcessID As Long
tpBasePri As Long
tpDeltaPri As Long
dwFlags As Long
End Type
Private Const WM_USER As Long = &H400
Private Const WM_GET_ID As Long = WM_USER + 1
Private Const WM_TERMINATE As Long = WM_USER + 2
Private Const TH32CS_SNAPPROCESS As Long = &H2
Private Const TH32CS_SNAPTHREAD As Long = &H4
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Private Declare Function PostThreadMessage Lib "user32" Alias "PostThreadMessageA" (ByVal idThread As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Boolean
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function Thread32First Lib "kernel32" (ByVal hSnapshot As Long, ByRef lpte As THREADENTRY32) As Boolean
Private Declare Function Thread32Next Lib "kernel32" (ByVal hSnapshot As Long, ByRef lpte As THREADENTRY32) As Boolean
Private Sub SendConsoleMsg()
Dim PID As Long
Dim tHandle As Long
Dim dwThreadId As Long
Dim PName As String
Dim Success As Boolean
Dim tEntry As THREADENTRY32
PName = "C:\My Stuff\Visual Studio" & _
"\ConsoleTest\Debug\ConsoleTest.exe"
PID = Shell(PName, vbNormalFocus)
Sleep 250
tHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0&)
If tHandle = -1 Then
Debug.Print "Could not obtain thread handle"
Exit Sub
End If
tEntry.dwSize = Len(tEntry)
Success = Thread32First(tHandle, tEntry)
If Success Then
Do
If tEntry.th32OwnerProcessID = PID Then
PostThreadMessage tEntry.th32ThreadID, _
WM_GET_ID, 0, VarPtr(dwThreadId)
End If
Loop While Thread32Next(tHandle, tEntry)
End If
CloseHandle tHandle
Sleep 10
Debug.Print dwThreadId
End Sub
当我运行SendConsoleMsg
时VBA 中的程序,控制台加载,然后在几秒钟内崩溃。当我进入 Debug模式时,我在 C 代码示例中看到了访问冲突注释。请让我知道我需要做什么才能使其正常工作。我已经寻找解决方案好几天了,但仍然一无所获。
我能够使用 code example 让它工作Frankie_C 链接到选项 1。但是,我最终更改了 DLL 函数调用约定 __declspec(dllexport)
至__stdcall
并包含用于函数导出的 DEF 文件。另外,我向 DLL 添加了另一个函数,这样我就可以在 VBA 中以 DWORD 形式返回线程 id -
DWORD __stdcall GetConsoleThreadId() {
WCHAR Buf[5];
GetSharedMem(Buf, 5);
SetSharedMem(TEXT("0"));
return (DWORD)wcstod(Buf, '\0');
}
在我的MessageQueue
函数中,我添加了以下代码来将线程 id 加载到共享内存中 -
WCHAR Buf[5];
HMODULE hDLL;
FARPROC SetSharedMem;
hDLL = LoadLibrary(TEXT("C:\\My Stuff\\Visual Studio\\SharedMem\\Debug\\SharedMem.dll"));
if (hDLL != NULL) {
SetSharedMem = GetProcAddress(hDLL, "SetSharedMem");
if (SetSharedMem) {
swprintf_s(Buf, 5, L"%d", GetCurrentThreadId());
SetSharedMem(Buf);
}
FreeLibrary(hDLL);
}
最佳答案
首先,不同的进程有不同的内存空间,彼此之间是隔离的。这是当今操作系统的主要特征之一:进程私有(private)内存。
如果您想从在 2 个或更多不同进程中运行的代码访问共享内存,则不能使用 GlobalAlloc()。该函数来自 16 位 Windows 操作系统中本地和全局进程内存之间的旧区别。因此,尽管它的名称是全局的,但这并不意味着可以从不同的进程访问。
要实现这个技巧,你基本上有两种方法:
在第一种情况下,您只需在第一个进程中创建一个内存映射文件,然后在第二个进程中打开该文件,然后操作共享内存。请参阅this sample ,或this one 。最后将映射文件和服务例程放在需要访问公共(public)数据的所有进程之间共享的 DLL 中。
对于第二种情况,您必须创建一个 DLL,在 DLL 内您将使用 SECTION
command 创建一个共享部分。在 DLL 的 .def
文件中。您还可以使用#pragma 部分来关联共享属性。在共享部分中创建的所有数据在加载 dll 的任何进程中都是可见的。
//Use pragma to create a section named 'MySharedSection', readable, writable and shared
#pragma section( "MySharedSection", read, write, shared)
//Allocate the section, all data after this spec will be allocated in the new section
__declspec(allocate("MySharedSection"))
__declspec(dllexport) char CommonBuffer[1024];
在上面的示例中,我创建了一个 1024 字节的共享缓冲区,该缓冲区可供所有加载 DLL 的进程使用。该符号也会被导出,以便可以从链接 DLL 的代码中访问它。
这个系统已经过时了,是从Win3.1时代开始使用的。今天首选的方法是使用 CreateFileMapping()
关于c - LPARAM 作为指向 VBA 变量的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31730591/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!