Page Index Toggle Pages: [1] 2  Send TopicPrint
Very Hot Topic (More than 25 Replies) GDI+ and Network Service (Read 23273 times)
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
GDI+ and Network Service
Jul 4th, 2011 at 10:32pm
Print Post  
I spent a whole day trying to solve this without success:

The Chart.SaveToBitmap(pngfile) function doesn't work (no file is created) when the process is running as a Network Service (IIS process) on Windows 2008 Server.

The exact same code works just fine when I run it through Apache as a SYSTEM user (different machine though), or as a normal exe process as a normal windows user on the same machine. I initialize the gdi+ engine the same way in all cases.

It's not a folder/file permission because the same process manages to create and write to a temp file in the same location - only the Chart fails to create the file in that location.

Any ideas? Something to check? Could you reproduce this on your end?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #1 - Jul 5th, 2011 at 6:53am
Print Post  
Could you check what number of encoders is returned if you call the GDI+ GetImageEncodersSize function from the service?
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #2 - Jul 5th, 2011 at 11:34am
Print Post  
It returns 5 encoders and size=1040, just like with the normal app version.

This has become a critical issue for a customer that wants to present a demo tomorrow, so any speedy response would be greatly appreciated.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #3 - Jul 5th, 2011 at 12:08pm
Print Post  
Does saving a .bmp image work, with GDI+ turned off?
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #4 - Jul 5th, 2011 at 12:10pm
Print Post  
Yes it does, first thing I tried. Which is why I narrowed down the problem to GDI+.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #5 - Jul 5th, 2011 at 12:16pm
Print Post  
Try running this conversion code on the bitmap:
http://www.jose.it-berater.org/smfforum/index.php?topic=1862.0

If it does not work, you might at least get some error code from GDI+ with more information about the problem.
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #6 - Jul 5th, 2011 at 12:24pm
Print Post  
I'm running VB code so to run that code would mean porting it to the VB equivalent somehow.

I'm currently attempting to do this, but in the meantime, I have a couple of questions.

1. Is this what your code does? I.e. save to bitmap then convert? I'm trying to understand if this is close to the real thing.

2. Does the Chart code use any temporary work folder or any resources that may require windows permissions. It may be a permission thing because you are running as a restricted 'network service'.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #7 - Jul 5th, 2011 at 12:37pm
Print Post  
1. The control directly saves an in-memory GDI+ Bitmap object, using the png encoder in this case. Here's our code:

Code
Select All
bool GdiPlusEngine::saveBitmap(
	const wchar_t* fileName, HBITMAP bitmapHandle)
{
	// create GDI+ image for the bitmap handle
	Gdiplus::Bitmap image(bitmapHandle, 0);

	// determine which encoder to use from the fileName extension
	CLSID clsid;
	if (getEncoderClsidForFileName(fileName, &clsid))
	{
		if (image.Save(fileName, &clsid, 0) == Gdiplus::Ok)
			return true;
	}

	return false;
} 



2. There are no temporary files used, unless the png encoder tries to create some. By the way, have you tried saving in a different format, such as gif or jpeg?
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #8 - Jul 5th, 2011 at 1:47pm
Print Post  
OK I made the code work with the help of this:
http://read.pudn.com/downloads158/sourcecode/multimedia/708159/BatteryMonitor/Cl...

It converts to PNG and works, but obviously this can only be a temporary solution since it has to save two files and work harder.

I also tested bmp/gif/jpg/png and all four don't work. Only bmp works when GDI+ is off.

So it seems that the problem is only with the combination of Chart component and GDI+.

What's next?
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #9 - Jul 5th, 2011 at 1:55pm
Print Post  
In case you want to compare my code that works, here is what I used:

Code
Select All
Private Function pvGetEncoderClsID(strMimeType As String, ClassID() As Long) As Long
  Dim Num      As Long
  Dim Size     As Long
  Dim lIdx     As Long
  Dim ICI()    As ImageCodecInfo
  Dim Buffer() As Byte

    pvGetEncoderClsID = -1 ' Failure flag

    Call GdipGetImageEncodersSize(Num, Size)
    If (Size = 0&) Then Exit Function ' Failed!

    ReDim ICI(1 To Num) As ImageCodecInfo
    ReDim Buffer(1 To Size) As Byte

    Call GdipGetImageEncoders(Num, Size, Buffer(1))
    Call CopyMemory(ICI(1), Buffer(1), (Len(ICI(1)) * Num))

    For lIdx = 1& To Num
        If (StrComp(pvPtrToStrW(ICI(lIdx).MimeType), strMimeType, vbTextCompare) = 0) Then
            CopyMemory ClassID(0), ICI(lIdx).ClassID(0), 16& ' Save the Class ID
            pvGetEncoderClsID = lIdx      ' Return the index number for success
            Exit For
        End If
    Next lIdx
    Erase ICI
    Erase Buffer
End Function

Private Function pvPtrToStrW(ByVal lpsz As Long) As String
String Pointer to String
  Dim sOut As String
  Dim lLen As Long

    lLen = lstrlenW(lpsz)

    If (lLen > 0&) Then
        sOut = StrConv(String$(lLen, vbNullChar), vbUnicode)
        Call CopyMemory(ByVal sOut, ByVal lpsz, lLen * 2&)
        pvPtrToStrW = StrConv(sOut, vbFromUnicode)
    End If

End Function

Public Function ConvertToPng(FileName As String) As String

   Dim hStatus As Long
   Dim token As Long
   Dim StartupInput As GdiplusStartupInput
   Dim EncoderClsid As String
   Dim pImage As Long
   Dim nWidth As Long
   Dim nHeight As Long
   Dim transformation As Long
   Dim strFileName As String
   Dim ClassID() As Long
   ReDim ClassID(0 To 3) As Long

   StartupInput.GdiplusVersion = 1
   hStatus = GdiplusStartup(token, StartupInput)
   If hStatus Then
      PutToLog 0, "Error initializing GDI+", ""
      Exit Function
   End If

   hStatus = GdipLoadImageFromFile(StrPtr(FileName), pImage)

   EncoderClsid = pvGetEncoderClsID("image/png", ClassID)

   strFileName = GetPath(FileName) & GetFileNameWithoutExtention(FileName) & ".png"
   hStatus = GdipSaveImageToFile(pImage, StrPtr(strFileName), ClassID(0&), 0)
   If hStatus = 0 Then
   Else
      PutToLog 0, "Error:", CStr(hStatus) & " ---- " & CStr(Err.LastDllError)
   End If

   If pImage Then GdipDisposeImage (pImage)
   ConvertToPng = strFileName

   GdiplusShutdown token

End Function

 

  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #10 - Jul 5th, 2011 at 2:28pm
Print Post  
There's nothing next, we'll leave it at this for now.
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #11 - Jul 5th, 2011 at 2:32pm
Print Post  
Some strange news: I figured out how to change the windows user that my process runs as from 'Network Service' to 'administrator' and it still doesn't work.

So what's left? What does IIS do that's unique when running the process? Whatever it is, it breaks the Chart component's ability to call GDI+. The code works fine without GDI+ under the exact same circumstances. Any ideas?
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #12 - Jul 5th, 2011 at 2:35pm
Print Post  
I can't leave it at this - I need to optimize performance and saving two files (a huge BMP file at that) is too slow to live with for long.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: GDI+ and Network Service
Reply #13 - Jul 5th, 2011 at 2:38pm
Print Post  
No idea. Our developers will investigate this when they have time, you will have to use the conversion code for now.
  
Back to top
 
IP Logged
 
baron
YaBB Newbies
*
Offline


1001001001

Posts: 42
Joined: Dec 2nd, 2007
Re: GDI+ and Network Service
Reply #14 - Jul 5th, 2011 at 2:42pm
Print Post  
OK thanks for the quick replies. I'll be monitoring this topic for updates. If you have any theories you'd like me to test, let me know.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: [1] 2 
Send TopicPrint