0

Я пытаюсь использовать последнее связывание функции CreateProcess в kernel32.dll, однако он возвращает нулевое значение, в отличие от любой другой функции.Позднее связывание с CreateProcess с C# возвращает нулевое значение

Вот код, я использую для позднего связывания

public abstract class LateBinding 
{ 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, BestFitMapping = false, SetLastError = true), SuppressUnmanagedCodeSecurity()] 
    private static extern LBHandle LoadLibrary(string fileName); 

    [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity()] 
    private static extern IntPtr GetProcAddress(LBHandle hModule, string procname); 

    private Delegate Result = default(Delegate); 

    public Delegate Call(string library, string method, Type type) 
    { 
     LBHandle Lib = LoadLibrary(library); 
     if (!Lib.IsInvalid && !Lib.IsClosed) 
     { 
      Result = Marshal.GetDelegateForFunctionPointer(GetProcAddress(Lib, method), type);     
      Lib.Close(); 
     } 
     return Result; 
    } 
} 

[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] 
public sealed class LBHandle : SafeHandleZeroOrMinusOneIsInvalid 
{ 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool FreeLibrary(IntPtr hModule); 

    private LBHandle() : base(true) { } 

    protected override bool ReleaseHandle() 
    { 
     return FreeLibrary(handle); 
    } 
} 

и это, как я вызываю функцию

private delegate bool dCreateProcess(string applicationName, string commandLine, IntPtr processAttributes, IntPtr threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref STARTUP_INFORMATION startupInfo, ref PROCESS_INFORMATION processInformation); 
dCreateProcess CreateProcess = Call("kernel32.dll", "CreateProcess", typeof(dCreateProcess)) as dCreateProcess; 
+0

'LoadLibrary' возвращает' IntPtr', который является дескриптор модуля, не знаю, как вы разворачивать его в этом классе или если он работает именно так. Вы пробовали увидеть, какая последняя ошибка после запуска? Вы установили последнюю ошибку в true, чтобы вы могли ее проверить. –

+0

Проверьте это: [link] (http://blogs.msdn.com/b/jmstall/archive/2007/01/06/typesafe-getprocaddress.aspx) – PavilionVI

ответ

1

В ядре32 нет функции с именем CreateProcess. Он существует в двух версиях: CreateProcessA (ANSI) и CreateProcessW (Unicode). Вы можете видеть, что на кнопке documentation for CreateProcess on MSDN.

Это не уникально для CreateProcess почти каждая функция Win32 API, которая принимает строку, будет иметь A и W.

Ниже то, что вы хотите:

dCreateProcess CreateProcess = Call("kernel32.dll", "CreateProcessW", typeof(dCreateProcess)) as dCreateProcess; 

Смотрите также What is the difference between CreateProcess and CreateProcessA?

+0

Вы также не должны называть 'FreeLibrary' до тех пор, пока вы не закончите вызов функции. 'FreeLibrary' выгрузит DLL из вашего процесса. Вы не видите проблему с kernel32, так как она уже загружена, но если вы вызываете функцию пользовательского Dll после вызова 'FreeLibrary', вы будете терпеть крах. – shf301

+0

Кажется, что все это было проблемой, спасибо за разъяснение этого мне. – PavilionVI

1

kernel32.dll фактически не экспортировать точку входа функции с именем CreateProcess - это либо CreateProcessA, либо в вашем случае CreateProcessW для аргументов unicode (Wide).

Смежные вопросы