我想将一个dll导入到我的C#项目中,使用DllImport调用它的函数。 我的dll需要作为我的.msi文件的一部分导入。
当我指定DLL的完整路径时,它确实有效,但这是在.msi文件之外。
我正面临dllNotFoundException问题。
<Binary Id="CustomAction2.CA.dll"
src="../artifacts/CustomAction2.CA.dll" />
<CustomAction Id="Install"
Execute="deferred"
BinaryKey="CustomAction2.CA.dll"
DllEntry="CustomAction1" />
<CustomAction Id="InstallWithProperty"
Property="Install"
Value="location=[DEFAULT_INSTALLDIR]$FULL_NAME;name=myDll.dll"
Execute="immediate"/>
<InstallExecuteSequence>
<Custom Action="InstallWithProperty" After="InstallFiles"/>
<Custom Action="Install" After="InstallWithProperty" />
</InstallExecuteSequence>
调用自定义操作时,它说 我得到以下异常
Exception thrown by custom action: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.DllNotFoundException: Unable to load DLL 'myDll.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) at CustomAction2.CustomActions.ConfigDriver(IntPtr hwndParent, UInt16 fRequest, String lpszDriver, String lpszArgs, String lpszMsg, UInt16 cbMsgMax, Int64& pcbMsgOut) at CustomAction2.CustomActions.CustomAction1(Session session) --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) at Microsoft.Deployment.WindowsInstaller.CustomActionProxy.InvokeCustomAction(Int32 sessionHandle, String entryPoint, IntPtr remotingDelegatePtr) CustomAction Install returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
有人可以提供帮助吗?我想使用myDll.dll进行进一步安装,这是.msi文件的一部分。
答案 0 :(得分:0)
如果我理解正确,你有MSI文件里面有.DLL,你想要发送它吗?
无论你做什么,听起来都不错。你可能会重新思考你的方法, 但是,对于一个实际的答案:
为了帮助您入门,这里有一些C#代码:
String inputFile = @"C:\\Install1.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(inputFile, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM Property WHERE Property = 'ProductVersion'");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
// Get the version from the data
string version = record.get_StringData(2);
现在请注意,它不会从MSI中提取文件,但这是一个好的开始。为了从MSI中实际提取,您需要稍微更改一下代码。
这是执行此操作的VB代码,请注意SQL语法,如查询。
Function ExtractIcon(IconName, OutputFile)
Const msiReadStreamAnsi = 2
Dim oDatabase
Set oDatabase = Session.Database
Dim View
Set View = oDatabase.OpenView("SELECT * FROM Icon WHERE
Name = '" & IconName & "'")
View.Execute
Dim Record
Set Record = View.Fetch
Dim BinaryData
BinaryData = Record.ReadStream(2, Record.DataSize(2),
msiReadStreamAnsi)
Dim FSO
Set FSO = CreateObject("Scripting.FileSystemObject")
Dim Stream
Set Stream = FSO.CreateTextFile(OutputFile, True)
Stream.Write BinaryData
Stream.Close
Set FSO = Nothing
End Function
你需要将它转换为C#,这将是一件容易的事。 之后,您需要实际使用动态pInvoke。如果将DLL解压缩到项目文件夹中,并使用相对路径,也可以使用普通的pInvoke。
使用动态pInvoke:
按照这篇文章; http://blogs.msdn.com/b/jmstall/archive/2007/01/06/typesafe-getprocaddress.aspx
这是一个很简洁的代码:
using(UnmanagedLibrary lib = new UnmanagedLibrary("kernel32") // becomes call to LoadLibrary
{
Action<String> function = lib.GetUnmanagedFunction<Action<String>>("DeleteFile"); // GetProcAddress
function(@"c:\tmp.txt");
} // implict call to lib.Dispose, which calls FreeLibrary.
如果您觉得自己像上帝,可以将DLL加载到内存中,而不是在任何地方提取它。如果您拥有应始终对任何人隐藏的令人惊叹的DLL,这将非常有用。这只是为了获取信息 - 这很难^ _ ^