c # BeginUpdateResource - PullRequest
3 голосов
/ 24 мая 2011

Я хотел бы добавить строковый ресурс в исполняемый файл программно .Просто для примера, допустим, я пытаюсь добавить строку с именем «String SO», которая содержит значение «stringVal»

Если это кому-нибудь поможет - если бы я делал это через VS.net Я мог бы просто щелкнуть правой кнопкой мыши на моем Project => Resources => Add New String Resource и т.д ..

Я использую следующие Win32 API:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr BeginUpdateResource(string pFileName,
[MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool UpdateResource(IntPtr hUpdate, uint lpType, uint lpName, ushort wLanguage, byte[] lpData, uint cbData);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);

Итак, я нашел пару страниц в Интернете, но ни одна из них, похоже, не помогает мне в том, что я пытаюсь сделать.Если кто-нибудь из вас сможет найти что-либо, я был бы очень признателен.

В противном случае, я был бы очень признателен за любые фрагменты, которые могут помочь.Спасибо, Эван

Ответы [ 4 ]

2 голосов
/ 28 ноября 2011

Существует очень полезная библиотека для многих ресурсных задач в github .

Многие классы и функции переносят эти вызовы window-api вокруг UpdateResource(...) и т. Д.

Надеюсь, это поможет.

1 голос
/ 19 июля 2012

Я внедряю байт приложения [] в качестве ресурса для его выполнения во время выполнения. Вот мой кусок кода, надеюсь, он поможет:

class AddResource
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr BeginUpdateResource(string pFileName,
       [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
private static IntPtr ToPtr(object data)
{
    GCHandle h = GCHandle.Alloc(data, GCHandleType.Pinned);
    IntPtr ptr;
    try
    {
        ptr = h.AddrOfPinnedObject();
    }
    finally
    {
        h.Free();
    }
    return ptr;

}

public static bool InjectResource(string filename, byte[] bytes, string resourceName)
{
    try
    {
        IntPtr handle = BeginUpdateResource(filename, false);
        byte[] file1 = bytes;
        IntPtr fileptr = ToPtr(file1);
        bool res = UpdateResource(handle, resourceName,
            //"RT_RCDATA",
            "0", 0, fileptr, Convert.ToUInt32(file1.Length));
        EndUpdateResource(handle, false);
    }
    catch
    {
        return false;
    }
    return true;

}

public static void CopyStream(Stream input, Stream output,long sz)
{
    // Insert null checking here for production
    byte[] buffer = new byte[sz];

    int bytesRead;
    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, bytesRead);
    }
}

}

Вот как я это использую:

using (Stream input = Assembly.GetExecutingAssembly().GetManifestResourceStream("AppLicensing.Resources.SAppStarter.exe"))
                        using (Stream output = File.Create(outputFilePath))
                        {
                            long sz = input.Length;
                            AddResource.CopyStream(input, output, sz);
                        }
                        //inject crypted bytes
                        AddResource.InjectResource(outputFilePath, Encryptor.cryptedbytes, "RT_RCDATA");

А вот как я извлекаю ресурс (обратите внимание на «RT_RCDATA» -> это имя ресурса):

   class ReadResource 
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);

        [DllImport("Kernel32.dll", EntryPoint = "SizeofResource", SetLastError = true)]
        private static extern uint SizeofResource(IntPtr hModule, IntPtr hResource);

        [DllImport("Kernel32.dll", EntryPoint = "LoadResource", SetLastError = true)]

        private static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResource);


       public static  byte[] GetFromResource(String resourceName)
    {
        try
        {
            IntPtr hModule = GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName);
            IntPtr loc = FindResource(hModule, "0", resourceName);
            uint size = SizeofResource(hModule, loc);
            IntPtr x = LoadResource(hModule, loc);
            byte[] bPtr = new byte[size];
            Marshal.Copy(x, bPtr, 0, (int)(size));
            return bPtr;
        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.ToString());
            System.Environment.Exit(0);
            return null;
        }        
    }            
  }

  byte[] encryptedData = ReadResource.GetFromResource("RT_RCDATA");

Код становится немного грязным ... надеюсь, это поможет.

0 голосов
/ 02 августа 2015

Код от Samson работает с String lpType, это означает, что вы не можете фактически добавлять ресурс RT_RCDATA, либо читая из него, он только создает и читает lpType только с именем "RT_RCDATA". Если вы хотите, чтобы он считывал реальные данные RT, вам нужно изменить lpType со строки на uint, а это таблица RT API:

private const uint RT_CURSOR = 0x00000001;
private const uint RT_BITMAP = 0x00000002;
private const uint RT_ICON = 0x00000003;
private const uint RT_MENU = 0x00000004;
private const uint RT_DIALOG = 0x00000005;
private const uint RT_STRING = 0x00000006;
private const uint RT_FONTDIR = 0x00000007;
private const uint RT_FONT = 0x00000008;
private const uint RT_ACCELERATOR = 0x00000009;
private const uint RT_RCDATA = 0x0000000a;
private const uint RT_MESSAGETABLE = 0x0000000b;
0 голосов
/ 11 апреля 2012

Хотя автор сейчас занимается собственной проблемой, вопрос SO Сбой функции UpdateResource содержит фрагмент кода для использования этих вызовов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...