Не рандомизируйте порядок списка, просто выберите случайное число из возможного диапазона индексов для списка. Затем измените поведение соответствующим образом, чтобы убедиться, что он не воспроизводит один и тот же звук снова и снова (поскольку это небольшой список, это, скорее всего, произойдет).
P/Invoke использует LoadLibrary для загрузки DLLs, и если уже будет библиотека, загруженная именем, то LoadLibrary возвратит его. Таким образом, если можно дать обе версии DLL то же имя, но поместить их в различные каталоги, можно сделать что-то вроде этого просто однажды первый вызов к функции из scilexer.dll, не будучи должен копировать объявления экстерна:
string platform = IntPtr.Size == 4 ? "x86" : "x64";
string dll = installDir + @"\lib-" + platform + @"\scilexer.dll";
if (LoadLibrary(dll) == IntPtr.Zero)
throw new IOException("Unable to load " + dll + ".");
Можно поместить dll в system32. 32 бита в syswow64 и 64 бита в реальном system32. Для приложения на 32 бита, когда thay доступ system32 они перенаправляются к Syswow64.
Можно создать запись в реестре. Программный ключ имеет подраздел по имени Wow6432Node, который приложение на 32 бита рассматривает как программный ключ.
Вот то, что делает powershell установщик.
Лучшее, которое я придумал, следующее:
File.Delete(Application.StartupPath + @"\scilexer.dll"); { // Check for 64 bit and copy the proper scilexer dll if (IntPtr.Size == 4) { File.Copy(Application.StartupPath + @"\scilexer32.dll", Application.StartupPath + @"\scilexer.dll"); } else { File.Copy(Application.StartupPath + @"\scilexer64.dll", Application.StartupPath + @"\scilexer.dll"); } }
К сожалению, я ничего не знаю об этом конкретном DLL. Однако, когда Вы делаете P/Invoke сами, и можно справиться с небольшим дублированием, возможно создать один прокси для каждой платформы.
Например, предположите, что у Вас есть следующий интерфейс, который должен быть реализован любым DLL на 32 или 64 бита:
public interface ICodec {
int Decode(IntPtr input, IntPtr output, long inputLength);
}
Вы создаете прокси:
public class CodecX86 : ICodec {
private const string dllFileName = @"Codec.x86.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
и
public class CodecX64 : ICodec {
private const string dllFileName = @"Codec.x64.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
И наконец сделайте фабрику, которая выбирает правильный для Вас:
public class CodecFactory {
ICodec instance = null;
public ICodec GetCodec() {
if (instance == null) {
if (IntPtr.Size == 4) {
instance = new CodecX86();
} else if (IntPtr.Size == 8) {
instance = new CodecX64();
} else {
throw new NotSupportedException("Unknown platform");
}
}
return instance;
}
}
Поскольку DLLs загружаются лениво в первый раз, когда они вызываются, это на самом деле работает, несмотря на каждую платформу только способность загрузить версию, которая является собственной к ней. См. эту статью для более подробного объяснения.
Неуправляемый dlls может быть установлен в GAC бок о бок с их управляемыми дубликатами. Эта статья должна объяснить, как она работает.