在获得有关从存储设备检索.MBR的大量信息之后,结论是使用P/Invoke来调用CreateFile.
但是如何在C#中完成这项工作?请说明!对你的帮助表示感谢!!!
我试图将一个结构从C#传递到C++库.我将结构作为对象传递,C++函数将它作为指针(void*).
我有问题通过结构.
[DllImport("MockVadavLib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr TheFunction([MarshalAs(UnmanagedType.LPStruct)] UserRec userRec);
Run Code Online (Sandbox Code Playgroud)
这是我得到的运行时异常文本:
"无法封送'参数#1':无效的托管/非托管类型组合(此值类型必须与Struct配对)."
虽然我发现了一篇在这种情况下使用LPStruct的MSDN文章.
这是我试图编组的结构:
[StructLayout(LayoutKind.Sequential)]
public struct UserRec {
[MarshalAs(UnmanagedType.I4)]
public int userParam1;
}
Run Code Online (Sandbox Code Playgroud)
这是C++函数:
MOCKVADAVLIB_API tVDACQ_CallBackRec * TheFunction(void * userParams) {...
Run Code Online (Sandbox Code Playgroud) 我试图找出一个具有特定功能的窗口是否已被进程打开.这个过程产生了多个窗口,我需要检查它们.
我毫不费力地找到了这个过程
foreach (Process p in Process.GetProcesses())
{
if (p.MainModule.FileName.ToLower().EndsWith("foo.exe"))
FindChildWindowWithText(p); //do work
Run Code Online (Sandbox Code Playgroud)
问题是接下来要做什么.我不能使用Process' MainWindowText,因为它会随着激活的窗口而改变.
然后我试图使用Windows函数EnumChildWindows和GetWindowText,但我不知道如果我传递一个正确的句柄EnumChildWindows.在EnumChildWindows通过MainWindowHandle的时候,但当然,MainWindowHandle与活动窗口的变化按预期工作.所以我通过了Process.Handle,但是在切换应用程序的窗口时,我得到了不同的句柄和不同的结果.(据我所知,EnumChildWindows返回的句柄,不仅窗户,但控制在.NET讲,这是没有问题的,如果我能得到窗口的标题太)
也许我这样做是错误的,我需要一个不同的方法 - 再次,我的问题就像找到一个文本与特定正则表达式匹配的窗口一样简单.所以我可能需要一个枚举所有窗口的函数,这些窗口在任务栏中都是可见的.
谢谢
我的直觉反应是否定的,因为托管和非托管内存是截然不同的,但我不确定.NET Framework是否在幕后操作Marshaling.
我认为发生的是:从我的非托管DLL获取结构时,它与使调用获取IntPtr然后使用它和Marshal类将结构复制到托管内存(以及对托管中的结构所做的更改)相同记忆不要起泡).
我似乎无法在MSDN上的任何地方找到此文档.任何链接将不胜感激.
这是我的代码的样子:
[DllImport("mydll.dll", BestFitMapping=false, CharSet=CharSet.Ansi)]
private static extern int GetStruct(ref MyStruct s);
[StructLayout(LayoutKind.Sequential, Pack=0)]
struct MyStruct
{
public int Field1;
public IntPtr Field2;
}
public void DoSomething()
{
MyStruct s = new MyStruct();
GetStruct(ref s);
s.Field1 = 100; //does unmanaged memory now have 100 in Field1 as well?
s.Field2 = IntPtr.Zero; //does unmanaged memory now have a NULL pointer in field Field2 as well?
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试在F#应用程序中使用P/Invoke设置一个低级键盘钩子.Win32函数SetWindowsHookEx接受HOOKPROC第二个参数,我将其表示为委托(int * IntPtr * IntPtr) -> IntPtr,类似于在C#中处理它的方式.在调用方法时,我得到一个MarshalDirectiveException声明,委托参数无法封送,因为
通用类型无法编组
我不确定如何涉及泛型,因为具体指定了所有类型.任何人都可以对此有所了解吗?代码如下.
编辑
这可能与F#编译器处理类型签名的方式有关 - Reflector指示委托LowLevelKeyboardProc实现为接受一个类型的参数的方法Tuple<int, IntPtr, IntPtr>- 并且将存在不可编组的泛型类型.有没有办法解决这个问题,或者F#函数是不是能够被编组到本机函数指针?
let WH_KEYBOARD_LL = 13
type LowLevelKeyboardProc = delegate of (int * IntPtr * IntPtr) -> IntPtr
[<DllImport("user32.dll")>]
extern IntPtr SetWindowsHookEx(int idhook, LowLevelKeyboardProc proc, IntPtr hMod, UInt32 threadId)
[<DllImport("kernel32.dll")>]
extern IntPtr GetModuleHandle(string lpModuleName)
let SetHook (proc: LowLevelKeyboardProc) =
use curProc = Process.GetCurrentProcess ()
use curMod = curProc.MainModule
SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curMod.ModuleName), 0u)
Run Code Online (Sandbox Code Playgroud) 我正在使用第三方专有DLL,我无法获得源代码.但是,使用SWIG 1.3.39自动生成的包装代码可供我使用.包装器代码包含一个C++文件,该文件编译(使用一些描述DLL的头文件)到DLL和一个C#项目,它使PInvoke调用C++包装器DLL.
根据我对供应商文档的解释,我已将解决方案中的所有内容编译为x86或x64,具体取决于目标平台.供应商提供专有DLL的32位和64位版本,并且我确保我使用正确的版本给定构建.我的机器是32位的.在我的机器上,在发布版本或调试版本中测试我的应用程序的x86版本似乎工作正常.但是,在64位上,应用程序在调试模式下工作,但在发布模式下因System.AccessViolationException而失败.
我已经阅读了这篇很好的博客文章,似乎很好地描述了调试与发布问题,以及引发博客文章的这个问题和答案.但是,我不确定如何在这种情况下解决问题.
AccessViolationException似乎是在第一次从C++包装器返回(或尝试返回)任何实际长度的字符串时发生的.这是违规的C#代码:
// In one file of the C# wrapper:
public string GetKey()
{
// swigCPtr is a HandleRef to an object already created
string ret = csWrapperPINVOKE.mdMUHybrid_GetKey(swigCPtr);
return ret;
}
// In the csWrapperPINVOKE class in another file in the C# wrapper:
[DllImport("csWrapper.dll", EntryPoint="CSharp_mdMUHybrid_GetKey")]
public static extern StringBuilder mdMUHybrid_GetKey(HandleRef jarg1);
Run Code Online (Sandbox Code Playgroud)
来自C++包装器的麻烦的C++代码:
SWIGEXPORT char * SWIGSTDCALL CSharp_mdMUHybrid_GetKey(void * jarg1) {
char * jresult ;
mdMUHybrid *arg1 = (mdMUHybrid *) 0 ; …Run Code Online (Sandbox Code Playgroud) 可能重复:
Windows API和.net语言
我想从.NET Framework调用本机Windows API.我希望有一个简单的方法,我可以像其他.NET API一样从高级层调用本机API.请参阅您知道的任何资源.任何帮助将不胜感激.
我需要在C++和C#之间创建一个包装器.我有一个非常类似的功能:
virtual SOMEINTERFACE* MethodName(ATTRIBUTE_TYPE attribType = ATTRIBUTE_TYPE::ATTRIB_STANDARD) = 0;
Run Code Online (Sandbox Code Playgroud)
该enum声明如下:
enum class ATTRIBUTE_TYPE {
ATTRIB_STANDARD,
ATTRIB_LENGTH
};
Run Code Online (Sandbox Code Playgroud)
如何包装ATTRIBUTE_TYPE枚举?
约束执行区域是C#/ .Net的一个特性,它允许开发人员尝试从关键的代码区域中提升"三大"异常--OutOfMemory,StackOverflow和ThreadAbort.
CER通过推迟ThreadAborts,准备调用图中的所有方法来实现这一点(因此不会发生JIT,这可能导致分配),并确保有足够的堆栈空间来适应随后的调用堆栈.
典型的不间断区域可能如下所示:
public static void GetNativeFlag()
{
IntPtr nativeResource = new IntPtr();
int flag;
// Remember, only the finally block is constrained; try is normal.
RuntimeHelpers.PrepareConstrainedRegions();
try
{ }
finally
{
NativeMethods.GetPackageFlags( ref nativeResource );
if ( nativeResource != IntPtr.Zero ) {
flag = Marshal.ReadInt32( nativeResource );
NativeMethods.FreeBuffer( nativeResource );
}
}
}
Run Code Online (Sandbox Code Playgroud)
上述内容大部分都很好,因为CER内部没有任何规则被破坏 - 所有.Net分配都在CER之外,Marshal.ReadInt32()具有兼容性ReliabilityContract,我们假设我的NativeMethods被类似地标记,以便VM可以正确地考虑他们在准备CER时.
因此,除了所有这些之外,您如何处理分配必须在CER内部发生的情况?分配违反规则,因为很有可能获得OutOfMemoryException.
在查询本机API(SSPI的QuerySecurityPackageInfo)时,我遇到了这个问题,这会迫使我违反这些规则.本机API确实执行自己的(本机)分配,但如果失败,我只得到一个空的结果,所以没有什么大不了的.但是,在它分配的结构中,它存储了一些未知大小的C字符串.
当它返回指向它所分配的结构的指针时,我必须复制整个事物,并分配空间来存储这些c字符串作为.Net字符串对象.毕竟,我应该告诉它释放分配.
但是,由于我在CER中执行.Net分配,我违反规则并可能泄漏一个句柄.
处理这个问题的正确方法是什么?
对于它的价值,这是我天真的方法:
internal static SecPkgInfo GetPackageCapabilities_Bad( string packageName )
{
SecPkgInfo info; …Run Code Online (Sandbox Code Playgroud) 我一直在尝试在ClickOnce应用程序上禁用DPI感知.
我很快发现,无法在清单中指定它,因为ClickOnce不支持清单文件中的asm.v3.
我找到的下一个选项是调用新的Windows函数SetProcessDpiAwareness.
根据本教程,
在创建应用程序窗口之前调用SetProcessDpiAwareness.
而本教程中,
您必须在任何Win32API调用之前调用SetProcessDpiAwareness
你必须尽早调用这个函数.所以,为了测试,我创建了一个完全空白的WPF应用程序,并将其作为我的整个App类:
[DllImport("SHCore.dll", SetLastError = true)]
private static extern bool SetProcessDpiAwareness(PROCESS_DPI_AWARENESS awareness);
[DllImport("SHCore.dll", SetLastError = true)]
private static extern void GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS awareness);
private enum PROCESS_DPI_AWARENESS
{
Process_DPI_Unaware = 0,
Process_System_DPI_Aware = 1,
Process_Per_Monitor_DPI_Aware = 2
}
static App()
{
var result = SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
var setDpiError = Marshal.GetLastWin32Error();
MessageBox.Show("Dpi set: " + result.ToString());
PROCESS_DPI_AWARENESS awareness;
GetProcessDpiAwareness(Process.GetCurrentProcess().Handle, out awareness);
var getDpiError = Marshal.GetLastWin32Error();
MessageBox.Show(awareness.ToString());
MessageBox.Show("Set DPI error: …Run Code Online (Sandbox Code Playgroud)