Inno Setup 中的 C# DLL 访问冲突
C# DLL in Inno Setup Access Violation
我正在尝试在我的 InnoSetup 项目中引用 C# DLL。我需要的是一个带有一个字符串参数和一个字符串 return 值的简单函数。但即使按照示例并尝试不同类型的封送处理,我总是以访问冲突告终。
这是我的 C# class:
public class NKToolbox
{
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
{
File.WriteAllText(@"C:\temp\test.txt", password);
return password.Length.ToString();
}
}
我放置了 File.WriteAllText
以查看是否甚至调用了该方法。但不是。我使用 Robert Giesecke 的 UnmanagedExports 包。
以及 Inno 设置代码:
function EncryptPassword(pw: WideString): WideString;
external 'EncryptPassword@files:nktoolbox.dll stdcall';
function InitializeSetup: Boolean;
var
str: WideString;
begin
str := EncryptPassword('sdvadfva');
log(str);
result := False;
end;
在线 str := EncryptPassword('sdvadfva')
我得到一个 'Access violation at address ...... Write of address .....' 我正在使用 Inno Setup 5.5.9 Unicode。
我已经尝试使用在其他线程中找到的不同封送处理语句,我已经使用 out
关键字、普通 string
类型和 WideString
进行了尝试绝望。
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
在 Delphi 代码中,这映射到:
function EncryptPassword(password: PAnsiChar): PAnsiChar; stdcall;
另请注意,C# 代码 return 是通过调用 CoTaskMemAlloc
分配的字符串。您的代码应该通过调用 CoTaskMemFree
.
来释放该缓冲区
导入此函数的代码试图将文本视为 COM BSTR
字符串。事实并非如此。
使用 COM BSTR
,又名 WideString
是个好主意。但请注意,对于 return 值,C# 和 Inno 假设的 ABI 之间可能存在不匹配。最好使用 out
参数。参见 Why can a WideString not be used as a function return value for interop?
换句话说,我会这样声明 C#:
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static void EncryptPassword(
[MarshalAs(UnmanagedType.BStr)]
string input
[MarshalAs(UnmanagedType.BStr)]
out string output
)
{
output = ...;
}
Inno 会是这样的:
procedure EncryptPassword(input: WideString; out output: WideString);
external 'EncryptPassword@files:nktoolbox.dll stdcall';
我对 Inno 一无所知,所以我的部分回答有点依赖猜测。
我正在尝试在我的 InnoSetup 项目中引用 C# DLL。我需要的是一个带有一个字符串参数和一个字符串 return 值的简单函数。但即使按照示例并尝试不同类型的封送处理,我总是以访问冲突告终。
这是我的 C# class:
public class NKToolbox
{
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
{
File.WriteAllText(@"C:\temp\test.txt", password);
return password.Length.ToString();
}
}
我放置了 File.WriteAllText
以查看是否甚至调用了该方法。但不是。我使用 Robert Giesecke 的 UnmanagedExports 包。
以及 Inno 设置代码:
function EncryptPassword(pw: WideString): WideString;
external 'EncryptPassword@files:nktoolbox.dll stdcall';
function InitializeSetup: Boolean;
var
str: WideString;
begin
str := EncryptPassword('sdvadfva');
log(str);
result := False;
end;
在线 str := EncryptPassword('sdvadfva')
我得到一个 'Access violation at address ...... Write of address .....' 我正在使用 Inno Setup 5.5.9 Unicode。
我已经尝试使用在其他线程中找到的不同封送处理语句,我已经使用 out
关键字、普通 string
类型和 WideString
进行了尝试绝望。
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static string EncryptPassword([MarshalAs(UnmanagedType.LPStr)] string password)
在 Delphi 代码中,这映射到:
function EncryptPassword(password: PAnsiChar): PAnsiChar; stdcall;
另请注意,C# 代码 return 是通过调用 CoTaskMemAlloc
分配的字符串。您的代码应该通过调用 CoTaskMemFree
.
导入此函数的代码试图将文本视为 COM BSTR
字符串。事实并非如此。
使用 COM BSTR
,又名 WideString
是个好主意。但请注意,对于 return 值,C# 和 Inno 假设的 ABI 之间可能存在不匹配。最好使用 out
参数。参见 Why can a WideString not be used as a function return value for interop?
换句话说,我会这样声明 C#:
[DllExport("EncryptPassword", CallingConvention.StdCall)]
static void EncryptPassword(
[MarshalAs(UnmanagedType.BStr)]
string input
[MarshalAs(UnmanagedType.BStr)]
out string output
)
{
output = ...;
}
Inno 会是这样的:
procedure EncryptPassword(input: WideString; out output: WideString);
external 'EncryptPassword@files:nktoolbox.dll stdcall';
我对 Inno 一无所知,所以我的部分回答有点依赖猜测。