我正在使用DllImport从我自己的.net类中调用c包装器库中的方法.c dll中的此方法创建一个字符串变量并返回该字符串的指针.
像这样的东西;
_declspec(dllexport) int ReturnString()
{
char* retval = (char *) malloc(125);
strcat(retval, "SOMETEXT");
strcat(retval, "SOMETEXT MORE");
return (int)retval;
}
Run Code Online (Sandbox Code Playgroud)
然后我使用Marshall.PtrToStringAnsi(ptr)读取字符串.在我得到字符串的副本后,我只需调用另一个c方法HeapDestroy,该方法位于调用free(ptr)的c包装器库中.
这是个问题; 最近虽然它像魅力一样工作,但我开始"尝试读取或写入受保护的内存区域"例外.经过深入分析,我想通了,我相信,虽然我为这个指针调用了自由方法,指针的值没有被清除,并且这填充了无人看管的堆并使我的iis工作进程抛出此异常.顺便说一句,它是一个在c库中调用此方法的网站项目.
你能帮我解决这个问题吗?
当然,这是C#代码;
[DllImport("MyCWrapper.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private extern static int ReturnString();
[DllImport("MyCWrapper.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private extern static void HeapDestroy(int ptr);
public static string GetString()
{
try
{
int i = ReturnString();
string result = String.Empty;
if (i > 0)
{
IntPtr ptr = new IntPtr(i);
result = Marshal.PtrToStringAnsi(ptr);
HeapDestroy(i); …Run Code Online (Sandbox Code Playgroud) 由于在绘制小圆角矩形时在GDI +中使用DrawArc函数不是很准确,所以我使用的是RoundRect.
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim hDC As IntPtr = e.Graphics.GetHdc
Dim rc As New Rectangle(10, 10, 64, 24)
Dim hPen As IntPtr = Win32.CreatePen(Win32.PenStyle.PS_SOLID, 0, _
ColorTranslator.ToWin32(Color.Green))
Dim hOldPen As IntPtr = Win32.SelectObject(hDC, hPen)
Call Win32.RoundRect(hDC, rc.Left, rc.Top, rc.Right, rc.Bottom, 10, 10)
Win32.SelectObject(hDC, hOldPen)
Win32.DeleteObject(hPen)
e.Graphics.ReleaseHdc(hDC)
MyBase.OnPaint(e)
End Sub
Run Code Online (Sandbox Code Playgroud)
这将绘制一个漂亮的圆角矩形,但它也会用白色画笔填充它,擦除我不想删除的东西.
如何在不擦除矩形内部的情况下绘制它?
我在 C# 中使用 PInvoke,尝试使用已知处理程序读取窗口中可见的工具提示,但是我尝试以这种方式检查的窗口应用程序因内存访问冲突错误而崩溃,或者根本不显示工具提示文本lpszText TOOLINFO 成员。
我正在使用回调调用EnumWindows,然后向该函数中的工具提示窗口发送一条消息:
public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);
static void Main(string[] args)
{
callBackPtr = new CallBackPtr(Report);
IntPtr hWnd = WindowFromPoint(<mouse coordinates point>);
if (hWnd != IntPtr.Zero)
{
Console.Out.WriteLine("Window with handle " + hWnd +
" and class name " +
getWindowClassName(hWnd));
EnumWindows(callBackPtr, hWnd);
Console.Out.WriteLine();
}
public static bool Report(IntPtr hWnd, IntPtr lParam)
{
String windowClassName = getWindowClassName(hWnd);
if (windowClassName.Contains("tool") &&
GetParent(hWnd) == lParam)
{
string szToolText = new string(' ', 250); …Run Code Online (Sandbox Code Playgroud) 我在delphi中有一个嵌入式记录,如下所示:
TKernel = packed record
State: Integer;
end;
TKernels = array[0..19] of TKernel;
TShell = packed record
Kernels: TKernels;
end;
Run Code Online (Sandbox Code Playgroud)
在这,
SizeOf(TShell) = 20 * SizeOf(TKernel).
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用C#:
struct Shell
{
Kernel[] Kernels;
public Shell(int i = 20)
{
Kernels = new Kernel[20];
}
}
Run Code Online (Sandbox Code Playgroud)
然后:Marshal.SizeOf(Shell)== 4
这意味着内核只是一个指针.我想互操作C#与德尔福,所以我需要有存储结构是一样的,所以我应该如何申报在C#中的结构,除了写20个喜欢内核KernelOne的; 内核内核两个......
我有一个C++ Dll"TheFoo.dll",方法是"Foo()"
我可以通过简单地调用以下方法访问使用此方法的其他C++代码:
Foo();
Run Code Online (Sandbox Code Playgroud)
我相信该方法确实具有:
__declspec( dllexport )
Run Code Online (Sandbox Code Playgroud)
所以,随着我对P/Invoke的阅读,我想我应该能够简单地从我的C#代码中调用相同的方法:
namespace PInvokeExample1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport(@"C:\MyFolder\TheFoo.dll")]
public static extern
void Foo();
private void button1_Click(object sender, RoutedEventArgs e)
{
Foo();
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我收到一个错误:
Unable to find an entry point named 'Foo' in DLL 'C:\MyFolder\TheFoo.dll'.
Run Code Online (Sandbox Code Playgroud)
任何想法为什么没有找到?
我正在将一些Win32代码移植到C#,并且已经有几个具有相同名称并使用相同结构的函数,除了它们以A和W结尾
例如:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("shell32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool Shell_NotifyIconA(uint dwMessage, ref NOTIFYICONDATAA lpData);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("shell32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool Shell_NotifyIconW(uint dwMessage, ref NOTIFYICONDATAW lpData);
Run Code Online (Sandbox Code Playgroud)
我在C#中看到了一些实现,它们省略了函数名和相关结构中的A和W,如下所示:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("shell32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool Shell_NotifyIcon(uint dwMessage, ref NOTIFYICONDATA lpData);
Run Code Online (Sandbox Code Playgroud)
我想知道的是:
A和W表示什么?
在C#中,我应该使用A和W来实现上面显示的函数,还是更好的做法是省略A和W以支持单个实现?
我怎样才能在c#中使用这个dll函数?我尝试了以下但我得到错误."外部组件引发的异常."
我第一次用C#和Delphi做这个PInvoke的东西.
function HTTPGET(location:string):string; stdcall;
var
HTTP:TIdHttp;
begin
HTTP := TidHttp.Create(nil);
try
result := HTTP.Get(location);
finally
FreeAndNil(HTTP);
end;
end;
exports
HTTPGET;
begin
end.
namespace Test
{
class Program
{
[DllImport("project1.dll")]
public static extern string HTTPGET(string location);
static void Main(string[] args)
{
Console.WriteLine(HTTPGET("http://www.reuters.com/"));
}
}
}
Run Code Online (Sandbox Code Playgroud) 如何将文件的所有者更改为Everyone并允许该Everyone对象Full Access?
有没有可用的API?我必须使用P/Invoke吗?
我到处搜索,但找不到任何可以做到这一点.
如何使父进程设置为我的应用程序的控件“弹出”我的应用程序并成为顶级窗口?
我试过使用SetParent(WindowHandle, null);但 IntPtr 它说它是一个不可为空的类型。
我知道这个问题被问过1000次,但我不想使用任何外部工具(例如DotNetZip或SharpZipLib)。
我目前有这段工作代码:
string _from = Path.Combine(apk, "*.*") + '\0';
string _to = destination + '\0' + Path.Combine(destination, "*.*") + '\0';
NativeMethods.SHFILEOPSTRUCT fileop = new NativeMethods.SHFILEOPSTRUCT();
fileop.pFrom = _from;
fileop.pTo = _to;
fileop.wFunc = NativeMethods.FO_Type.FO_COPY;
fileop.fFlags = NativeMethods.FOF_Flag.FOF_WANTNUKEWARNING;
NativeMethods.SHFileOperation(ref fileop);
Run Code Online (Sandbox Code Playgroud)
我的问题是我无法提取/复制单个文件/文件夹。如果我*.*用res\\drawable\\icon.png它替换例如,它将什么都不做。
有人可以告诉我如何使用来提取单个文件/文件夹SHFILEOPSTRUCT吗?我想念什么吗?
该代码支持:
框架版本:.Net Client 4
操作系统:WinXP,8,8.1,10
编辑(通知):
当您在C#线程中使用这段代码时,总会出现“超出路径长度”错误……在这种情况下,您需要使用“分派器”。