C# 如何在运行时指定[DllImport]路径(嵌入在.msi文件中)

C# 如何在运行时指定[DllImport]路径(嵌入在.msi文件中),c#,wix,windows-installer,dllimport,custom-action,C#,Wix,Windows Installer,Dllimport,Custom Action,我想将一个dll导入到我的C#项目中,使用DllImport调用它的函数。 我有需要作为.msi文件一部分导入的dll 当我指定DLL的完整路径时,它确实起作用,但这在.msi文件之外 我面临dllNotFoundException问题 <Binary Id="CustomAction2.CA.dll" src="../artifacts/CustomAction2.CA.dll" /> <CustomAction Id="Install"

我想将一个dll导入到我的C#项目中,使用DllImport调用它的函数。 我有需要作为.msi文件一部分导入的dll

当我指定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>

当调用自定义操作时,它会显示 我得到以下例外


自定义操作引发的异常:System.Reflection.TargetInvocationException:调用的目标已引发异常。-->System.DllNotFoundException:无法加载DLL“myDll.DLL”:找不到指定的模块。CustomAction2.CustomActions.ConfigDriver(IntPtr hwndParent、UInt16 fRequest、字符串lpszDriver、字符串lpszArgs、字符串lpszMsg、UInt16 cbMsgMax、Int64和pcbMsgOut)的CustomAction2.CustomActions.CustomAction1(会话)处的(HRESULT:0x8007007E异常)---内部异常堆栈跟踪的结尾---在System.RuntimeMethodHandle处。\ u在System.RuntimeMethodHandle.InvokeMethodFast处调用MethodFast(IRuntimeMethodInfo方法、对象目标、对象参数、SignatureStruct&sig、MethodAttributes方法属性、RuntimeType类型所有者)在System.Reflection.RuntimeMethodInfo.Invoke(对象对象对象、BindingFlags invokeAttr、绑定绑定器、对象参数、CultureInfo区域性、布尔skipVisibilityChecks)的System.Reflection.RuntimeMethodInfo.Invoke(对象对象对象、BindingFlags invokeAttr、Binder Binder、对象参数、CultureInfo区域性、布尔skipVisibilityChecks)中Microsoft.Deployment.WindowsInstaller.CustomActionProxy.InvokeCustomAction(Int32 sessionHandle,String entryPoint,IntPtr remotingDelegatePtr)CustomAction安装返回的实际错误代码为1603(注意,如果翻译发生在沙盒内部,则可能无法100%准确)


有人能帮忙吗。我想使用myDll.dll进行进一步安装,它是.msi文件的一部分。

如果我理解正确,您的msi文件中有.dll,您想pInvoke它吗

不管你做这件事是为了什么,听起来很糟糕。你可能会重新思考你的方法, 然而,对于实际答案:

首先,这里有一点C代码:

现在请注意,它不会从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 = '" &amp; IconName &amp; "'") 

                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#,这将是一项简单的任务。 之后,您需要实际使用dynamic pInvoke.Ps。如果您将DLL提取到项目文件夹中,并使用相对路径,则也可以使用普通pInvoke

要使用动态pInvoke,请执行以下操作:

遵循本文

这是一个简洁的代码:

 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.
using(UnmanagedLibrary lib=newunmanagedlibrary(“kernel32”)//成为对LoadLibrary的调用
{ 
Action function=lib.GetUnmanagedFunction(“DeleteFile”);//GetProcAddress
函数(@“c:\tmp.txt”);
}//隐式调用lib.Dispose,它调用FreeLibrary。
如果你觉得自己是上帝,你可以将DLL加载到内存中,而不在任何地方提取它。如果你有一个神奇的DLL,它应该总是对任何人隐藏,这是很有用的。它只是为了提供信息-这是相当困难的^_^

 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.