Inno 설치 스크립트에서 .NET DLL을 어떻게 호출할 수 있나요?
-
09-06-2019 - |
문제
Inno 설치 스크립트의 .NET DLL(C#으로 코딩됨)에서 함수를 호출하고 싶습니다.
나는 가지고있다:
- 표시했다 COM interop에 등록 프로젝트 속성의 옵션
- 변경 컴비저블 에서 설정 AssemblyInfo.cs 파일,
- ISS 스크립트에 다음 줄을 추가했습니다.
[파일]
원천:c: emp\1\MyDLL.dll;플래그:복사하지 마세요
[암호]
함수 MyFunction():끈;
external 'MyFunction@files:MyDLL.dll stdcall setuponly';
하지만 여전히 다음과 같은 오류가 발생합니다.
런타임 오류(-1:0):
dll:C:\DOCUME~1\foo\LOCALS~1 emp\is-LRL3E.tmp\MyDLL.dll을 가져올 수 없습니다.
내가 도대체 뭘 잘못하고있는 겁니까?
해결책
이런, 미안해요. 파스칼을 읽은 지 너무 오래 됐어요!따라서 가치를 얻으려면 다음과 같은 몇 가지 가능성이 있습니다.
- C/C++로 기능을 작성하고 함수를 내보내면 확실히 지원됩니다.
- Managed C++ dll을 사용하여 .NET dll로 심을 실행하고 호출을 C 인터페이스 포인트로 노출합니다(이 방법은 작동하지만 지저분해집니다).
- .exe를 사용하여 코드 결과를 .INI 파일, 레지스트리 또는 임시 파일에 저장하고 설정 코드 섹션에서 결과를 읽습니다. (이제는 적절하지 않습니다.)
InnoSetup을 마지막으로 작업했을 때 시나리오를 직접 지원하지 않았습니다(설정에서 .NET 코드 호출).
다른 팁
Intenta de esta manera(이 방법을 시도해 보세요):
Var
obj: Variant
va: MyVariableType;
Begin
//Starting
ExtractTemporaryFile('MyDll.dll');
RegisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
obj := CreateOleObject('MyDll.MyClass');
//Using
va := obj.MyFunction();
//Finishing
UnregisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
DeleteFile('{tmp}\MyDll.dll');
End;
Suerte (행운을 빌어요)
이에 대해 조금 더 읽었습니다. 이제 C 스타일 함수 가져오기와 OLE 개체 만들기의 차이점을 알 수 있습니다.
다음과 같은 것이 나에게 효과적입니다.
[Code]
procedure MyFunction();
var
oleObject: Variant;
begin
oleObject := CreateOleObject('MyDLL.MyDLL');
MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
end;
하지만 DLL 파일을 등록해야 합니다.
DLL에서 함수를 호출하려면 명령줄 응용 프로그램을 만들어야 할 것 같습니다.
.NET dll에서 C 스타일 함수를 가져오려고 합니다. 이것은 실제로 COM 상호 운용성과 관련이 없습니다.COM interop을 사용하면 .NET 개체를 COM 개체로 활성화할 수 있지만 C/C++에서 내보낸 함수/유형으로 노출되지는 않습니다.
함수가 데이터를 반환할 필요가 없다면 함수를 호출하는 간단한 .exe를 만들어 설정에서 실행해 보는 것은 어떨까요?
또한:참조 innosetup 지원 뉴스그룹 더 나은 지원을 받을 수 있는 곳.
사용 관리되지 않는 내보내기 라이브러리 Inno 설정에서 호출할 수 있는 방식으로 C# 어셈블리에서 함수를 내보내는 것입니다.
- C# 클래스 라이브러리에서 정적 메서드 구현
- 추가 관리되지 않는 내보내기 NuGet 패키지를 프로젝트에 추가
- 세트 플랫폼 대상 당신의 프로젝트의 x86
- 추가
DllExport
당신의 방법에 귀속 - 필요한 경우 함수 인수에 대한 마샬링을 정의합니다(특히 문자열 인수의 마샬링을 정의해야 함).
- 짓다
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace MyNetDll
{
public class MyFunctions
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static bool RegexMatch(
[MarshalAs(UnmanagedType.LPWStr)]string pattern,
[MarshalAs(UnmanagedType.LPWStr)]string input)
{
return Regex.Match(input, pattern).Success;
}
}
}
Inno 설정 측에서:
[Files]
Source: "MyNetDll.dll"; Flags: dontcopy
[Code]
function RegexMatch(Pattern: string; Input: string): Boolean;
external 'RegexMatch@files:MyNetDll.dll stdcall';
이제 다음과 같이 기능을 사용할 수 있습니다.
if RegexMatch('[0-9]+', '123456789') then
begin
Log('Matched');
end
else
begin
Log('Not matched');
end;
또한보십시오:
.NET dll은 COM 개체로 노출하여 다른 프로그래밍 언어에서 가장 잘 호출할 수 있습니다.이 예를 살펴보십시오. http://support.microsoft.com/kb/828736.이는 "관리되지 않는 C++"에서 ".NET dll"을 호출하는 방법을 보여줍니다."관리되지 않은 C++"를 COM 클라이언트로 사용할 수 있는 다른 프로그래밍 언어로 바꿀 수 있습니다.
지연로드를 사용해 보십시오. 런타임에 존재하지 않을 수 있는 dll에 사용됩니다.이것으로 문제가 해결됩니다.
예를 들어:
[Files]
Source: odbccp32.dll; Flags: dontcopy
[Code]
procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';
닷넷 프레임워크 및 이전 버전을 감지하는 Innosetup 스크립트 좀 유용할 수도 있습니다.