UpdateResource being weird

N

Nak

Hi there,

It's probably me being weird more than the function but I'm having
problems with it doing as it should.

I have a C++ application with 2 resources of custom types,

RT_INIFILE @ 2000 (INI file)

and

IDR_MSISETUP @ 3000 (MSI file)

The declaration of my UpdateResource call is as follows,

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, ByVal lpType
As String, ByVal lpID As Integer, ByVal wLanguage As Integer, ByVal lpData()
As Byte, ByVal cbData As Integer) As Integer
End Function

Right, so here's the problem. When calling the above method to update
the 2 resources I get no errors returned, unfortunately further inspection
using a resource viewer shows that the MSI file is being updated (although
the resource viewer has trouble reading the data) and the INI file is not
updated, but kind of modified, it becomes 2 resource files within an item
called 2000, 1 the original INI file and 1 the new updated file (strange).

Now if I try the above method by changing the lpID parameter to a string
it says it's worked, but hasn't, which is rather strange too. So I'm
beginning to wonder if I'm getting the declaration wrong or something, but
if that's the case how comes it even attempts to update? Anyway, this is my
code that updates the resource

--- Start of file ---

Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.IO

Public Class resourceUpdater

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function BeginUpdateResource(ByVal pFileName As String, ByVal
bDeleteExistingResources As Boolean) As IntPtr
End Function

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, ByVal lpType
As String, ByVal lpID As String, ByVal wLanguage As Integer, ByVal lpData()
As Byte, ByVal cbData As Integer) As Integer
End Function

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function EndUpdateResource(ByVal hUpdate As IntPtr, ByVal
fDiscard As Boolean) As Boolean
End Function

Private cStrFileName As String

Public Function updateResourceFromBuffer(ByVal iType As String, ByVal iID As
Integer, ByVal iBuffer() As Byte) As Boolean
Dim pIPrUpdating As IntPtr = BeginUpdateResource(cStrFileName, False)
If (Not pIPrUpdating.Equals(IntPtr.Zero)) Then
If (UpdateResource(pIPrUpdating, iType, iID.ToString, 0, iBuffer,
iBuffer.Length) = 1) Then
If (EndUpdateResource(pIPrUpdating, False)) Then
Return (True)
Else
Throw New Exception("Failed to end updating of resource '" &
iID.ToString & "' of type '" & iType & "'.")
End If
Else
Throw New Exception("Failed to update resource '" & iID.ToString
& "' of type '" & iType & "'.")
End If
Else
Throw New Exception("Failed to begin updating resource '" &
iID.ToString & "' of type '" & iType & "'.")
End If
End Function

Public Shared Function fromFile(ByVal iFileName As String) As
resourceUpdater
If (File.Exists(iFileName)) Then
Dim pWRDResource As New resourceUpdater()
pWRDResource.cStrFileName = iFileName
Return (pWRDResource)
Else
Throw New FileNotFoundException("The Win32 resource file could not
be found.", iFileName)
End If
End Function

End Class

--- End of file ---

Not much too it really, to update my resources I'm calling it like this,

Dim pRUrUpdater As resourceUpdater =
resourceUpdater.fromFile("c:\fubar.exe")
Call pRUrUpdater.updateResourceFromBuffer("RT_MSIINSTALLER", 3000,
pBytMSIInstaller)
Call pRUrUpdater.updateResourceFromBuffer("RT_INIFILE", 2000,
pBytINIConfig)

Obviously the passed byte arrays contain the correct data, as I can see
in the resource viewer 1 of the INI files are correct, the other shouldn't
actually be there. The MSI installer seems to have been updated correctly
as I'm even extracting it from the executable again and then running it, but
the INI file is messing me arround.

Any tips on how to use this function or reasons as to why it isn't
working correctly? Thanks loads in advance, much appreciated!

Nick.
 
N

Nak

Hi again,

Ignore the part about the resource viewer not being able to read the
updated MSI file, it turns out it's just a bug with the resource viewer, I'm
using ResHacker now and it's viewing it fine. But obviously my problem is
still here.

Nick.
 
M

Mick Doherty

That's funny, I was working on updateresource just yesterday, only i was
working with png files in the RCDATA section.
This is how I declared UpdateResource:

\\\
<DllImport("kernel32", CallingConvention:=CallingConvention.Cdecl, _
setlasterror:=True)> _
Public Function UpdateResource(ByVal hUpdate As IntPtr, _
ByVal lpType As IntPtr, _
ByVal lpName As System.Text.StringBuilder, _
ByVal wLanguage As Int16, _
ByVal lpData As Byte(), _
ByVal cbData As Int32) As Int32
End Function
///

and then I called it like this:

\\\
BeginUpdateResource(...
....
Dim ResID As New System.Text.StringBuilder(somestring.ToUpper)
'ToUpper was crucial for extracting again using LoadResource
....
UpdateResource(hUpdateRes, _
New IntPtr(RT_RCDATA), _
ResID, _
1033, _
someArray, _
someArray.Length)
....
EndUpdateResource(...
///

You may need to add 'CharSet:=CharSet.Unicode' in the DllImport attribute
for String Types.
 
N

Nak

Hi Mick,

Thanks for the info, I shall go and give it a try now. I've been having
numerous problems with the DLLImports, I'm probably missing most of the
attributes that are crucial to getting it working. Anyway, thanks again!
:)

Nick.

"Mick Doherty"
 
N

Nak

At bl00dy last, this is my declaration,

<DllImport("kernel32", CallingConvention:=CallingConvention.Cdecl,
setlasterror:=True)> _
Public Shared Function UpdateResource(ByVal hUpdate As IntPtr, ByVal lpType
As StringBuilder, ByVal lpID As IntPtr, ByVal wLanguage As Int16, ByVal
lpData As Byte(), ByVal cbData As Int32) As Int32
End Function

It never ceases to amaze my how much you can twist these declarations and
end up with a working solution!

Nick.

"Mick Doherty"
 
M

Mick Doherty

I had this free webspace for years and never had Anything to put on it, so
one day, when I was bored, I put Nothing on it.
 
M

Mick Doherty

I use several overloaded versions depending on what I want to add.

I never managed to get EnumResources working, but I suppose that's because I
wasn't persistant enough.
 
N

Nak

Hi Mick,
It's annoying seeing just how close I was.

That's the law of the sod for you, spend 3 days trying to do something
and end up back where you started with only a slight modification. Don't
you love it when that happens?

Nick.
 
M

Mick Doherty

I only spent a couple of hours on this, but I know what you mean.
Only 3 days would be nice though. I spent months (on and off) trying to
resolve this solution:
http://dotnetrix.co.uk/misc.html --> Get Alpha Bitmap from 32 bit Icon, just
to end up finding that it was so simple.
 
N

Nak

Hi Mick,
http://dotnetrix.co.uk/misc.html --> Get Alpha Bitmap from 32 bit Icon,
just to end up finding that it was so simple.

Aah, actually I have a question regarding that, does it mean that you
can put nice XP icons into an image list and then have them loaded
correctly? Or you have to set the icons for each item at run-time? I've
always wanted to up my icons like this but don't really wan't to set the
icons at runtime (although it's not particularly difficult), can the
ImageList be inherited from? Just wondering.

Nick.
 
M

Mick Doherty

Unfortunately, ImageLists flatten the Alpha Channel.
I have reported this as a Bug and it has been fixed in VS2005, (but not in
the Beta1 release).
 
N

Nak

Hi Mick,
Unfortunately, ImageLists flatten the Alpha Channel.
I have reported this as a Bug and it has been fixed in VS2005, (but not in
the Beta1 release).

Aah right, fair enough. I suppose I should get on with my 1001 other
things then ;-)

Nick.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top