Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 01.06.10 19:04
Оценка:
Использую в программе WinAPI функцию UpdateResource:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);

Здесь, пятый параметр IntPtr lpData, цитирую, "The resource data to be inserted into the file indicated by hUpdate", т.е. указатель на данные собственно и представляющие собой ресурс. Мне надо вставить ресурс(bitmap) в файл. Как мне правильно получить этот указатель на bitmap-ресурс, что-бы все сработало
Re: Как получить IntPtr на файл ресурса ???
От: adontz Грузия http://adontz.wordpress.com/
Дата: 01.06.10 19:36
Оценка:
Здравствуйте, Аноним, Вы писали:

MemoryStream + Bitmap.Save + Marshal.AllocHGlobal + Marshal.Copy
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Как получить IntPtr на файл ресурса ???
От: Андрей Россия  
Дата: 02.06.10 06:10
Оценка:
Здравствуйте, Аноним, Вы писали:

skip

так будет правильнее
[DllImport("KERNEL32.DLL", EntryPoint="UpdateResourceW", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool UpdateResource(IntPtr hUpdate, UInt32 pType, UInt32 pName, UInt16 wLanguage, byte[] pData, UInt32 cbData);


// где-то в коде используется так:
//
using (BinaryReader reader = new BinaryReader(File.OpenRead(strResFile)))
{
  long nCount = new FileInfo(strResFile).Length;
  byte[] bytes = reader.ReadBytes((int)nCount);
  reader.Close();

  if (UpdateResource(hUpdate, nResType, nResID, 1049, bytes, (UInt32)nCount))
    Console.Write("Ресурс \"{0}\" успешно записан\n", strResFile);
}
Re: Как получить IntPtr на файл ресурса ???
От: Андрей Россия  
Дата: 02.06.10 06:16
Оценка:
Здравствуйте, Аноним, Вы писали:

skip

почитай вот это
Автор(ы): Алифанов Андрей
Дата: 25.02.2003
Данная статья описывает утилиту для записи Win32-ресурсов в файлы формата PE. Утилита в первую очередь предназначена для использования в проектах на Visual C# и VB.NET, хотя и не только :-)

там вполне рабочий код для работы с виндовыми ресурсами из под .NET
Re[2]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 12:36
Оценка:
Здравствуйте, Андрей, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>skip


А>почитай вот это
Автор(ы): Алифанов Андрей
Дата: 25.02.2003
Данная статья описывает утилиту для записи Win32-ресурсов в файлы формата PE. Утилита в первую очередь предназначена для использования в проектах на Visual C# и VB.NET, хотя и не только :-)

А>там вполне рабочий код для работы с виндовыми ресурсами из под .NET

Попробовал сделать как вы сказали. Тупо скопировал текст программы WinRes.exe, и подставил свои пути. Программа пишет, что ресурс "успешно записан", но в файле куда я его писал ресурса нет. В связи с этим у меня появилась пару вопросов.
Во-первых. Что в функции UpdateResource
public static extern bool UpdateResource(IntPtr hUpdate, string pType, UInt32 pName,
                                                 UInt16 wLanguage, byte[] pData, UInt32 cbData);

обозначает параметр pName. В статье написано, что это "числовой идентификатор ресурса". Но каким именно число должен быть этот идентификатор? В смысле, это какие-то предопределенные числа или я могу использовать любое число, которым будет помечен ресурс в файле, главное чтобы ресурса с таким-же идентификатором не было
Во-вторых. Я пытаюсь запихать ресурс в .exe-файл программы написанной на NET Framework v.4. Можно ли так делать? Точнее является-ли такой файл PE файлом
Re[3]: Как получить IntPtr на файл ресурса ???
От: adontz Грузия http://adontz.wordpress.com/
Дата: 02.06.10 13:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Во-первых. Что в функции UpdateResource

А>
А>public static extern bool UpdateResource(IntPtr hUpdate, string pType, UInt32 pName,
А>                                                 UInt16 wLanguage, byte[] pData, UInt32 cbData);
А>

А>обозначает параметр pName. В статье написано, что это "числовой идентификатор ресурса". Но каким именно число должен быть этот идентификатор? В смысле, это какие-то предопределенные числа или я могу использовать любое число, которым будет помечен ресурс в файле, главное чтобы ресурса с таким-же идентификатором не было

Любое

А>Во-вторых. Я пытаюсь запихать ресурс в .exe-файл программы написанной на NET Framework v.4. Можно ли так делать? Точнее является-ли такой файл PE файлом


Да, EXE файл .Net это PE файл. А какой тип ресурса-то? Строки и иконки хранятся особо. Вообще, может лучше обновлять managed ресурсы?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[4]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 13:37
Оценка:
Здравствуйте, adontz, Вы писали:

A>А какой тип ресурса-то? Строки и иконки хранятся особо.


Ресурс — bitmap. Но вообще нужно ещё добавлять/удалять текстовые файлы.

A>Вообще, может лучше обновлять managed ресурсы?


Хрен его знает. Вот я и хочу выяснить Модификации подвергается файл, в данный момент не исполняемый, поэтому какая ему разница. Наверное
Re[4]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 14:33
Оценка:
Здравствуйте, adontz, Вы писали:

A>Да, EXE файл .Net это PE файл. А какой тип ресурса-то? Строки и иконки хранятся особо. Вообще, может лучше обновлять managed ресурсы?


По идее, файл-то Window'ый и соответственно с помощью WinAPI функций можно с ним, что угодно делать.
А на практике использую код ниже, но он что-то работать не хочет. Хотя я уже все по сто раз проверил Посмотрите свежим глазом может чего увидете
    internal class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources);

        [DllImport("KERNEL32.DLL", EntryPoint = "UpdateResourceW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool UpdateResource(IntPtr hUpdate, string pType, UInt32 pName, UInt16 wLanguage, byte[] pData, UInt32 cbData);

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

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern int GetLastError();

        [STAThread]
        private static void Main()
        {
            using (OpenFileDialog openDialog = new OpenFileDialog())
            {
                openDialog.Multiselect = false;
                openDialog.Title = "Выберете PE-файл над которым будут проводиться операции...";
                openDialog.Filter = "Исполняемые файлы (*.exe)|*.exe|Все файлы (*.*)|*.*";
                if (openDialog.ShowDialog() != DialogResult.OK) return;

                string targetFile = openDialog.FileName;
                Assembly targetAssembly = Assembly.LoadFile(targetFile);

                openDialog.Title = "Выберете ресурс...";
                openDialog.Filter = "Растровое изображение (*.bmp)|*.bmp|Все файлы (*.*)|*.*";
                if (openDialog.ShowDialog() != DialogResult.OK) return;

                // Начинаем процесс записи ресурсов
                IntPtr hUpdate = BeginUpdateResource(openDialog.FileName, false);
                if (hUpdate != IntPtr.Zero)
                {
                    using (BinaryReader binary = new BinaryReader(File.OpenRead(openDialog.FileName)))
                    {
                        long fileLength = (uint)(new FileInfo(openDialog.FileName)).Length;
                        byte[] resourceBytes = binary.ReadBytes((int)fileLength);
                        binary.Close();

                        // Записываем ресурс
                        bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
                        if (!bSuccess) Console.WriteLine("Ошибка #" + GetLastError());

                        // Заканчиваем запись
                        EndUpdateResource(hUpdate, !bSuccess);
                    }
                }

                string[] resources = targetAssembly.GetManifestResourceNames();
                Console.WriteLine("Ресурсов в целевой сборке : {0}\n", resources.Length);
                for (int i = 0; i < resources.Length; i++)
                {
                    Console.WriteLine("{0}) {1}", i + 1, resources[i]);
                }
            }
            Console.ReadLine();
        }
    }
Re[5]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 14:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>// Записываем ресурс
А>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>

Это конечно, опечатка
Re[6]: Как получить IntPtr на файл ресурса ???
От: Jolly Roger  
Дата: 02.06.10 17:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>
А>>// Записываем ресурс
А>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>


Если имеется в виду стандартный тип ресурса BITMAP, то это не совсем то. Нужно объявить перегрузку bool UpdateResource(IntPtr hUpdate, Int32 pType, ...) и передать туда константу RT_BITMAP, которая равна 2.
"Нормальные герои всегда идут в обход!"
Re[7]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 17:50
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Аноним, Вы писали:


А>>>
А>>>// Записываем ресурс
А>>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>>


JR>Если имеется в виду стандартный тип ресурса BITMAP, то это не совсем то. Нужно объявить перегрузку bool UpdateResource(IntPtr hUpdate, Int32 pType, ...) и передать туда константу RT_BITMAP, которая равна 2.


Да тут ещё один косячек нашелся OpenFileDialog.FileName возвращает путь к файлу с двумя \ в строке пути(например, C:\\Users\\...). А BeginUpdateResource принимает путь с одним \(например, C:\Users\...). Вот как-то надо от этого избавиться. А я забыл как
Re[8]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 18:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Да тут ещё один косячек нашелся OpenFileDialog.FileName возвращает путь к файлу с двумя \ в строке пути(например, C:\\Users\\...). А BeginUpdateResource принимает путь с одним \(например, C:\Users\...). Вот как-то надо от этого избавиться. А я забыл как


Так пора отдохнуть. Гоню
Re[7]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 02.06.10 19:13
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Аноним, Вы писали:


А>>>
А>>>// Записываем ресурс
А>>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>>


JR>Если имеется в виду стандартный тип ресурса BITMAP, то это не совсем то. Нужно объявить перегрузку bool UpdateResource(IntPtr hUpdate, Int32 pType, ...) и передать туда константу RT_BITMAP, которая равна 2.


Нет, это не помогает
Re: Как получить IntPtr на файл ресурса ??? - OFFTOP
От: Аноним  
Дата: 02.06.10 19:22
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Использую в программе WinAPI функцию UpdateResource:

А>Как мне правильно получить этот указатель на bitmap-ресурс, что-бы все сработало

Вот чем мне нравятся отечественные программисты — спрашивают как сделать, им отвечают — "не надо так делать, это очень плохо, будут проблемы" (антивирус, файл залочится, не правильно это писать в exe файл и т.д.) и еще "есть простой, правильный, стандатный путь" (писать в AppData, в реестр, в UserData, в БД и т.д. и т.п.). Нет, они будут сидеть и решать совершенно левые проблемы, как же им все-таки заломать exe файл, потом таки решат и огребут проблем либо таки не решат, но в конце (месяца через два) наконец сделают так, как положено делать... И так как можно было бы сделать за пару дней... Я в восторге.
Re[6]: Как получить IntPtr на файл ресурса ???
От: Андрей Россия  
Дата: 03.06.10 03:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>
А>>// Записываем ресурс
А>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>

А>Это конечно, опечатка

что такое Convert.ToUInt32("resource")?
здесь надо просто передать числовой идентификатор твоей картинки

вроде в статье в свое время я все достаточно подробно расписал
правда, давно это было, я уж сам забыл про этот код
Re[7]: Как получить IntPtr на файл ресурса ???
От: Андрей Россия  
Дата: 03.06.10 03:42
Оценка: +1
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Аноним, Вы писали:


А>>>
А>>>// Записываем ресурс
А>>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>>


JR>Если имеется в виду стандартный тип ресурса BITMAP, то это не совсем то. Нужно объявить перегрузку bool UpdateResource(IntPtr hUpdate, Int32 pType, ...) и передать туда константу RT_BITMAP, которая равна 2.


Это он использует мою обертку, насколько я понял
правда, все равно неправильно

очень странная конструкция: Convert.ToUInt32("resource")
Re: Как получить IntPtr на файл ресурса ???
От: Pavel Dvorkin Россия  
Дата: 03.06.10 15:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Использую в программе WinAPI функцию UpdateResource:

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

А>Здесь, пятый параметр IntPtr lpData, цитирую, "The resource data to be inserted into the file indicated by hUpdate", т.е. указатель на данные собственно и представляющие собой ресурс. Мне надо вставить ресурс(bitmap) в файл. Как мне правильно получить этот указатель на bitmap-ресурс, что-бы все сработало

Небольшой офтопик.

Из всех этих дискуссий о добавлении ресурсов в управляемый код у меня сложилось впечатление, что самое простое решение — добавить их в неуправляемую DLL, положить ее рядом с EXE и не морочить себе голову. Для доступа использовать Win32 функции работы с ресурсами
With best regards
Pavel Dvorkin
Re[7]: Как получить IntPtr на файл ресурса ???
От: Аноним  
Дата: 03.06.10 20:21
Оценка:
Здравствуйте, Андрей, Вы писали:

А>>>
А>>>// Записываем ресурс
А>>>bool bSuccess = UpdateResource(hUpdate, "RT_BITMAP", Convert.ToUInt32("resource"), 1049, resourceBytes, (UInt32)fileLength);
А>>>

А>>Это конечно, опечатка

А>что такое Convert.ToUInt32("resource")?

А>здесь надо просто передать числовой идентификатор твоей картинки

А>вроде в статье в свое время я все достаточно подробно расписал

А>правда, давно это было, я уж сам забыл про этот код

Блин братан, за обертку спасибо Но двумя топиками выше, я уже написал, ЧТО ЭТО ОПЕЧАТКА
Я передавал туда числа и использовал всевозможные варианты UpdateResource, но толку нет. Мы тут в другом топике уже родили, что managet-ресурсы видимо, именно ВИДИМО, т.к. ни чего конкретного ни кто не сказал, не удастся править managet-ресурсы функциями WinAPI. Хотя вроде как .exe файл создаваемый VS, должен быть PE-файлом, т.е. правиться UpdateResource. Хочешь попробуй, здесь
Автор:
Дата: 03.06.10
точно описан порядок проведенного эксперимента.
Re[2]: Как получить IntPtr на файл ресурса ???
От: Pavel_Agurov Россия  
Дата: 04.06.10 07:50
Оценка:
PD>Небольшой офтопик.
PD>Из всех этих дискуссий о добавлении ресурсов в управляемый код у меня сложилось впечатление, что самое простое решение — добавить их в неуправляемую DLL, положить ее рядом с EXE и не морочить себе голову. Для доступа использовать Win32 функции работы с ресурсами

Тогда спрашивается зачем такие сложности-то? Записать в обычный XML или бинарник через сериализацию и т.д. и т.п. Зачем создавать себе сложности, делая DLL и потом ударно их решать?
Re[3]: Как получить IntPtr на файл ресурса ???
От: Pavel Dvorkin Россия  
Дата: 04.06.10 09:20
Оценка:
Здравствуйте, Pavel_Agurov, Вы писали:

PD>>Небольшой офтопик.

PD>>Из всех этих дискуссий о добавлении ресурсов в управляемый код у меня сложилось впечатление, что самое простое решение — добавить их в неуправляемую DLL, положить ее рядом с EXE и не морочить себе голову. Для доступа использовать Win32 функции работы с ресурсами

P_A>Тогда спрашивается зачем такие сложности-то? Записать в обычный XML или бинарник через сериализацию и т.д. и т.п. Зачем создавать себе сложности, делая DLL и потом ударно их решать?


Сложностей с работой с ресурсами Win32 в неуправляемых DLL никаких нет . Там все не просто, а очень просто.

А насчет XML или сериализации позволю себе поспорить. Если ты начнешь .bmp в XML переводить — объем возрастет прилично. Но не это главное

Хоть XML, хоть бинарник путем сериализации — как насчет произвольного доступа ? Win32 ресурсы — это ведь по сути библиотека ресурсов, в которых есть разные их типы, а для каждого типа может быть несколько ресурсов, и при этом всегда можно вытащить только тот ресурс, который нужен. Остальные даже не загружаются
With best regards
Pavel Dvorkin
Re[8]: Как получить IntPtr на файл ресурса ???
От: Pavel Dvorkin Россия  
Дата: 04.06.10 09:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я передавал туда числа и использовал всевозможные варианты UpdateResource, но толку нет. Мы тут в другом топике уже родили, что managet-ресурсы видимо, именно ВИДИМО, т.к. ни чего конкретного ни кто не сказал, не удастся править managet-ресурсы функциями WinAPI. Хотя вроде как .exe файл создаваемый VS, должен быть PE-файлом, т.е. правиться UpdateResource. Хочешь попробуй, здесь
Автор:
Дата: 03.06.10
точно описан порядок проведенного эксперимента.


Похоже, что да. PE-фацл тут ни при чем — в нем ничего не говорится, какие секции должны в нем быть.

Классическая секция ресурсов в неуправляемых Win32 PE называется .rsrc. В управляемых PE она есть (запусти dumpbin), но, похоже, embedded resources попадают не туда, а в секцию .text. Почему так — спроси MS.
With best regards
Pavel Dvorkin
Re[8]: Как получить IntPtr на файл ресурса ???
От: Андрей Россия  
Дата: 04.06.10 09:50
Оценка: +1
Здравствуйте, Аноним, Вы писали:

skip

чего тут пробовать-то?
я вроде ясно тебе написал еще пару дней назад (да и другие знающие люди тоже это говорили), что Win32 ресурсы не имеют ничего общего с .NET ресурсами (кроме схожего названия и назначения)
соответственно, бесполезно пытаться работать с .NET ресурсами через Win32 API (и наоборот)

так что не знаю, зачем ты продолжаешь биться головой о стену
Re[4]: Как получить IntPtr на файл ресурса ???
От: SaZ  
Дата: 04.06.10 12:12
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Хоть XML, хоть бинарник путем сериализации — как насчет произвольного доступа ? Win32 ресурсы — это ведь по сути библиотека ресурсов, в которых есть разные их типы, а для каждого типа может быть несколько ресурсов, и при этом всегда можно вытащить только тот ресурс, который нужен. Остальные даже не загружаются


Offtop: Да, особенно просто решается тривиальная задача выгрузки .bmp или строк из ресурса в файл.
Re[5]: Как получить IntPtr на файл ресурса ???
От: Pavel Dvorkin Россия  
Дата: 04.06.10 12:51
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Хоть XML, хоть бинарник путем сериализации — как насчет произвольного доступа ? Win32 ресурсы — это ведь по сути библиотека ресурсов, в которых есть разные их типы, а для каждого типа может быть несколько ресурсов, и при этом всегда можно вытащить только тот ресурс, который нужен. Остальные даже не загружаются


SaZ>Offtop: Да, особенно просто решается тривиальная задача выгрузки .bmp или строк из ресурса в файл.


Offtop так offtop

В начале 90-х заказали мне написать электронный учебник по теории вероятности. Интернета в Омске тогда не было, и про HTML я ничего не знал. Знал бы — наверное, хватило бы наглости написать свой броузер с HTML , но поскольку я не знал, то придумал свой язык разметки гипертекста, который ни за что не покажу сейчас никому . Написал гипертекстовую систему с двумя фреймами (для основного текста и для примеров), всплывающими окнами (для определений), закладки, историю вперед-назад и т.д. В общем, мне и сейчас не стыдно за то, что я тогда сделал, тем более. что делалось это на чистом Win16, потому что MFC тогда у нас не было и я про нее тоже не знал (а писал под BC 3.1, потом под BC 4.5 переводил в Win32).

И возник вопрос — где тексты хранить ? А также картинки. База данных — я и сейчас бы не стал, потому что в применении к этому учебнику прицепить даже Access или тогдашний Paradox/FoxPro — все равно, что к велосипеду пристроить ракетный двигатель. Хранить в виде текстовых файлов — так их несколько сот, а вдруг какой-то удалят по ошибке (а то и хуже — отредактируют ), мне что, проверять на целостность весь набор файлов ? Подумал я и слепил из них DLL с ресурсами нестандартного вида. Дальше все просто — FindResource, LoadResource, LockResource, SizeOfResource, и вот он у тебя как на ладони. А картинки еще проще — LoadBitmap и все.

Так что ресурсы Win API — дело хорошее. Зачем их убрали в .Net — понять не могу.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.