我有一个正在包装的 C dll,以便可以从 C# 调用它。当状态发生变化时,一个函数使用事件来通知您,并且需要进行一些挖掘才能找到处理它的方法。它似乎工作正常,但我很好奇是否有人比我有更多的经验并且可以提供任何建议。
该函数在 dll 的 .h 文件中定义为:
int NotifyStateChange(OVERLAPPED *overlapped);
typedef int (*NOTIFY_STATE_CHANGE_PROC)(OVERLAPPED *);
Run Code Online (Sandbox Code Playgroud)
调用它的示例 C 代码:
OVERLAPPED overlapped;
overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
fns.NotifyStateChange(&overlapped);
WaitForSingleObject(overlapped.hEvent, INFINITE);
// ...query for the new state or whatever...
Run Code Online (Sandbox Code Playgroud)
这就是我在 C# 中的处理方式:
[DllImport("myfuncs.dll")]
unsafe public static extern int NotifyStateChange(NativeOverlapped* lpOverlapped);
static private ManualResetEvent m_stateChangeEvent = new ManualResetEvent(false);
public static DeviceState WaitForStateChange()
{
unsafe
{
Overlapped overlapped = new Overlapped(0, 0,
m_stateChangeEvent.SafeWaitHandle.DangerousGetHandle(), null);
IOCompletionCallback callback = StateChangeCallback;
byte[] userData = new …Run Code Online (Sandbox Code Playgroud) 我正在尝试最小化标题位于string p(由用户在运行时指定)中的窗口。该窗口保证是主窗口,因为用户只能从主窗口中进行选择。我尝试过 showCmd、flags 以及两者的混合,但每次,无论窗口是否最小化,我都会显示一个声明 的对话框"Minimizing"。我该如何修复它?
private void button1_Click(object sender, EventArgs e)
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.MainWindowTitle.Contains(p))
{
IntPtr handle = proc.Handle;
Program.WINDOWPLACEMENT wp = new Program.WINDOWPLACEMENT();
Program.GetWindowPlacement(handle, ref wp);
if ((wp.showCmd & 2) == 2)
{
wp.showCmd = 9;
MessageBox.Show("Restoring");
}
else
{
wp.showCmd = 2;
MessageBox.Show("Minimizing");
}
wp.length = Marshal.SizeOf(wp);
Program.SetWindowPlacement(handle, ref wp);
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我用什么作为 p -
string p;
PictureBox i;
bool windowShowing = false;
bool minimized = …Run Code Online (Sandbox Code Playgroud) 是否可以在使用自定义封送拆收器的结构上使用Marshal.SizeOf()?
例如:
struct Abcde {
public int test1;
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyCustomMarshaler)]
public string customString1;
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话:
var size = Marshal.SizeOf(typeof(Abcde));
Run Code Online (Sandbox Code Playgroud)
抛出一个异常,表示无法计算有意义的大小或偏移量。我注意到ICustomMarshaler有一个名为GetNativeDataSize()的方法,但是无论我在那里返回什么都会抛出异常。
编辑:我已经根据@Hans Passant 的评论和@David Heffernan 的回答中的建议更新了代码。
这个论点c不再为空,但两者x并c仍然有一个长度,当它们被传递回CallbackFunction。
我正在尝试编写将函数指针(使用委托)传递给调用函数指针的 C++ 函数的 C# 代码。
代码如下。
我遇到的问题是,当 C++ 函数f调用时fnPtr(x,c),在 C# 函数中CallbackFunction,x有一个元素(正确值为 1.0),并且c为空。我不知道问题是什么。
我无法更改 MyCallback 的签名。
C#代码:
using System.Runtime.InteropServices;
namespace PInvokeTest
{
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate double MyCallback(
[In] double[] x,
[Out] double[] c);
private static double CallbackFunction(
[In] double[] x,
[Out] double[] c)
{
c[0] = x[0] + x[1] + x[2];
c[1] = x[0] …Run Code Online (Sandbox Code Playgroud) 我有一个 LZ4 c 实现的 dll,我想调用
LZ4_compress_default(const char* source,char* dest,int sourceLength,int maxdestLength);
Run Code Online (Sandbox Code Playgroud)
来自 ac# 代码的函数。该函数将源数组压缩为目标数组。这该怎么做?
我的 C# 代码:
DllImport(@"CXX.dll", CharSet = CharSet.Ansi, SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
internal static extern int LZ4_compress_default(
[MarshalAs(UnmanagedType.LPArray)] char[] source, out byte[] dest,
int sourceSize, int maxDestSize);
byte[] result= new byte[maxSize];
int x = LZ4_compress_default(array, out result, size, maxSize);
Run Code Online (Sandbox Code Playgroud) 我正在制作一个管理系统文件扩展名的应用程序,我遇到了问题。
系统扩展喜欢.jpg,.exe,.dll,.png,.txt,等有一个名为注册表值FriendlyTypeName,例如,FriendlyTypeName一个JPEG文件的是@%SystemRoot%\System32\shell32.dll,-30596。显示值取决于当前语言。
如何-30596使用 C#从资源 ID(例如:)中提取字符串值?。我想可以使用 p/invoke 提取字符串(我不确定)。
通过将此代码用于纯文本项目,我尝试并成功地做到了这一点:
var item = new MenuItemInfo
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
cch = (uint)label.Length,
dwTypeData = label,
fMask = 0x2 | 0x10, // MIIM_ID | MIIM_TYPE
fState = 0x0, // MFS_ENABLED
fType = 0x0, // MFT_STRING
wID = id
};
InsertMenuItem(hMenu, 0, true, ref item);
Run Code Online (Sandbox Code Playgroud)
对于基于图标的项目,我更改fMask并添加hbmpItem如下:
var item = new MenuItemInfo
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
cch = (uint)label.Length,
dwTypeData = label,
fMask = 0x80 | 0x2 | 0x100, // MIIM_BITMAP | MIIM_ID …Run Code Online (Sandbox Code Playgroud) 以下 C++ 代码会导致蓝屏。
#include "stdafx.h"
#include <iostream>
#include <string>
#include <Windows.h>
#pragma comment(lib, "ntdll.lib")
using namespace std;
EXTERN_C NTSTATUS NTAPI RtlAdjustPrivilege(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);
EXTERN_C NTSTATUS NTAPI NtRaiseHardError(NTSTATUS, ULONG, ULONG, PULONG_PTR, ULONG, PULONG);
int main(int argc, char **argv)
{
BOOLEAN bl;
RtlAdjustPrivilege(19, TRUE, FALSE, &bl);
unsigned long response;
NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, 0, 6, &response);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想为此使用 C#,所以我尝试使用 P/Invoke。但它不起作用。问题出在 NtRaiseHardError 签名上。我还没有在网上找到任何关于它的信息(例如 pinvoke.net 没有显示 NtRaiseHardError 因为它没有记录。)
这是我尝试过的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using …Run Code Online (Sandbox Code Playgroud) 这篇文章说:
如果应用程序必须阻止潜在的系统关闭,它可以调用 ShutdownBlockReasonCreate 函数。调用者提供将显示给用户的原因字符串。
在ShutdownBlockReasonCreate文档中,它清楚地表明在尝试关闭时将向用户显示一个带有原因字符串的对话框窗口:
表示系统无法关闭,并设置一个原因字符串,如果系统启动,则显示给用户
用户可以单击“仍然关闭”。此外,如果用户在几秒钟内没有采取任何行动,系统会假设“无论如何都要关闭”。
但是,在我调用ShutdownBlockReasonCreate传递当前应用程序的主窗口句柄后,确保该函数成功并通过调用ShutdownBlockReasonQuery函数来检索原因字符串来双重确保它,它不会阻止用户关闭系统和没有对话框窗口显示。
为什么它对我的系统没有影响?,我该如何解决这个问题?。
我使用管理员(内置)帐户在 Windows 10 x64 上运行,我使用的代码来自此GitHub 存储库:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Vanara.PInvoke;
using static Vanara.PInvoke.User32;
namespace Vanara.Windows.Forms.Forms
{
/// <summary>Used to define a set of operations within which any shutdown request will be met with a reason why this application is blocking it.</summary>
/// <remarks>This is to be used in either a 'using' statement or …Run Code Online (Sandbox Code Playgroud) 我想在 C++ 和 C# 中使用来自 DLL 的函数。
我将字符串数据存储在向量中。
我的 C++ 文件包含:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern "C" __declspec(dllexport) std::vector<std::string> GetProduct();
std::vector<std::string> GetProduct()
{
std::vector<std::string> vectProduct;
vectProduct.push_back("Citroen");
vectProduct.push_back("C5");
vectProduct.push_back("MOP-C5");
return vectProduct;
}
Run Code Online (Sandbox Code Playgroud)
在 C# 中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
[DllImport("ProductLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern StringBuilder GetProduct();
static void Main(string[] args)
{
StringBuilder vectProduct_impl = GetProduct();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何在c#中继续浏览数组。我不知道使用向量是否最佳。如果你有其他解决方案,我准备好了。 …