Discussion:
Hosting Preview Handler In DotNet Application?
(too old to reply)
nickname
2008-01-20 18:21:00 UTC
Permalink
Raw Message
I have found some sample code for how to do this on the site:

http://blogs.microsoft.co.il/blogs/eyal/

This seems to work for the Word preview handler but the adobe one fails to
load with exception:

"Creating an instance of the COM component with CLSID
{DC6EFB56-9CFA-464D-8880-44885D7DC193} from the IClassFactory failed due to
the following error: 80040154."

Could somebody explain why this is?

Source Code Below:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices.ComTypes;
using System.IO;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
//http://blogs.microsoft.co.il/blogs/eyal/
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public Rectangle ToRectangle() { return Rectangle.FromLTRB(left,
top, right, bottom); }
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("fc4801a3-2ba9-11cf-a229-00aa003d7352")]
public interface IObjectWithSite
{
void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out
object ppvSite);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
interface IPreviewHandler
{
void SetWindow(IntPtr hwnd, ref RECT rect);
void SetRect(ref RECT rect);
void DoPreview();
void Unload();
void SetFocus();
void QueryFocus(out IntPtr phwnd);
[PreserveSig]
uint TranslateAccelerator(ref MSG pmsg);
}

[StructLayout(LayoutKind.Sequential)]
internal struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int pt_x;
public int pt_y;
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b7d14566-0509-4cce-a71f-0a554233bd9b")]
interface IInitializeWithFile
{
void Initialize([MarshalAs(UnmanagedType.LPWStr)] string
pszFilePath, uint grfMode);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
interface IInitializeWithStream
{
void Initialize(IStream pstream, uint grfMode);
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

public void PreView(Guid guid, string file)
{
//get type by clsid
Type previewerType = Type.GetTypeFromCLSID(guid);

//create instance
object instance = Activator.CreateInstance(previewerType);

//now we need to querry interface for the required interfaces.
IObjectWithSite ows = (IObjectWithSite)instance;
IPreviewHandler ph = (IPreviewHandler)instance;
IInitializeWithFile iwf = instance as IInitializeWithFile;
IInitializeWithStream iws = instance as IInitializeWithStream;

//now we need to initialize the object
if (iwf != null)
{
iwf.Initialize(file, 0);
}
else
{
if (iws != null)
{
StreamWrapper stream = new StreamWrapper(File.Open(file,
FileMode.Open));
iws.Initialize(stream, 0);
}
}

//set the current form (implements IPreviewHandlerFrame)
ows.SetSite(this);

//set size
RECT rect = new RECT();
rect.left = 0;
rect.top = 0;
rect.bottom = this.Height;
rect.right = this.Width;

ph.SetWindow(this.Handle, ref rect);
ph.SetRect(ref rect);

//perform the preview
ph.DoPreview();
ph.SetFocus();
}

private void Form1_Load(object sender, EventArgs e)
{
//Word (Works Fine)
//PreView(new Guid("{84F66100-FF7C-4fb4-B0C0-02CD7FB668FE}"),
"c:\\test.docx");
//PDF (Does not work)
PreView(new Guid("{DC6EFB56-9CFA-464D-8880-44885D7DC193}"),
"c:\\test.pdf");
}

}
}

internal class StreamWrapper : IStream
{
~StreamWrapper()
{
if (stream != null)
{
stream.Close();
stream.Dispose();
stream = null;
}
}
Stream stream = null;
public StreamWrapper(Stream stream)
{
this.stream = stream;
}

#region IStream Members

public void Clone(out IStream ppstm)
{
ppstm = null;
}

public void Commit(int grfCommitFlags)
{
}

public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr
pcbWritten)
{
}

public void LockRegion(long libOffset, long cb, int dwLockType)
{
}

public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int actual = stream.Read(pv, 0, cb);
Marshal.WriteInt32(pcbRead, actual);
}

public void Revert()
{
}

public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long actual = stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
}

public void SetSize(long libNewSize)
{
}

public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG
pstatstg, int grfStatFlag)
{
pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG();
}

public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
}

public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
}

#endregion
}
Walter Wang [MSFT]
2008-01-21 06:31:25 UTC
Permalink
Raw Message
Hi nickname,

Searching the clsid you mentioned reveals that it's "Adobe PDF Preview
Handler for Vista". The error 0x80040154 means REGDB_E_CLASSNOTREG (class
not registered). Either this preview handler is not registered on your
system or it's Vista only (if your current system is not on Vista).


Regards,
Walter Wang (***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
nickname
2008-01-21 09:08:03 UTC
Permalink
Raw Message
Thank you for the reply. My current system is vista and it must be registered
as it is working in outlook and windows explorer. Any ideas why it is now
working here?

Thanks
Post by Walter Wang [MSFT]
Hi nickname,
Searching the clsid you mentioned reveals that it's "Adobe PDF Preview
Handler for Vista". The error 0x80040154 means REGDB_E_CLASSNOTREG (class
not registered). Either this preview handler is not registered on your
system or it's Vista only (if your current system is not on Vista).
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT]
2008-01-22 06:33:02 UTC
Permalink
Raw Message
Hi,

Are you running Vista 32-bit or 64-bit version? If you are running 64-bit
version, is your WinForm application compiled as 32-bit or 64-bit version?
(For "Any CPU" configuration, it will JIT compiled as 64-bit when it's run
on a 64-bit version os)


Regards,
Walter Wang (***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
nickname
2008-01-25 11:21:01 UTC
Permalink
Raw Message
Thank you for your reply, I was trying it on a 64bit version of vista. I have
now tested it on a 32bit version but now get the following error:

"Error HRESULT E_FAIL has been returned from a call to a COM component."

at the line:

iws.Initialize(stream, 0);

Any idea why it is raising this exception, and how can i resolve it?

Thanks for your help
Post by Walter Wang [MSFT]
Hi,
Are you running Vista 32-bit or 64-bit version? If you are running 64-bit
version, is your WinForm application compiled as 32-bit or 64-bit version?
(For "Any CPU" configuration, it will JIT compiled as 64-bit when it's run
on a 64-bit version os)
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT]
2008-01-28 06:04:34 UTC
Permalink
Raw Message
Hi,

Do you mean you're trying this on a 32-bit os or compiling a 32-bit version
(use Build Configuration Manager to create a new build configuration that
is based on x86) application on the same 64-bit version Vista that we were
talking about?

Also, are you running the application "As Administrator" or not? Is UAC
enabled on your Vista?

E_FAIL is a general COM error code, I cannot tell much about it now. Could
you please give me more information about the detailed steps to reproduce
the issue?

By the way, so far I'm not sure if this issue is specific to Adobe Acrobat
Reader or not. If yes, we might need to refer to Adobe's support for more
information.

Thanks.


Regards,
Walter Wang (***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
nickname
2008-01-29 22:40:01 UTC
Permalink
Raw Message
Hello,

Thanks for the reply, I am running it now on a 32-bit os, and its compiling
a 32-bit version. UAC is turned off, so is running with full administrator
rights.

As far as replicating the issue goes, it stops at the line:

iws.Initialize(stream, 0);

I'm not sure if there is any more information I can give you?

Thanks
Post by Walter Wang [MSFT]
Hi,
Do you mean you're trying this on a 32-bit os or compiling a 32-bit version
(use Build Configuration Manager to create a new build configuration that
is based on x86) application on the same 64-bit version Vista that we were
talking about?
Also, are you running the application "As Administrator" or not? Is UAC
enabled on your Vista?
E_FAIL is a general COM error code, I cannot tell much about it now. Could
you please give me more information about the detailed steps to reproduce
the issue?
By the way, so far I'm not sure if this issue is specific to Adobe Acrobat
Reader or not. If yes, we might need to refer to Adobe's support for more
information.
Thanks.
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT]
2008-01-30 13:05:45 UTC
Permalink
Raw Message
Hi,

Thanks for the information. I have been able to reproduce the issue as you
described on Vista.

I'm currently performing further researching on it. I'll keep you updated.


Regards,
Walter Wang (***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Walter Wang [MSFT]
2008-01-31 09:01:18 UTC
Permalink
Raw Message
Hi,

I've contacted product group on this.

Unfortunately, they told me that currently hosting preview handlers in user
applications is not supported. We only support creating preview handlers
for Office 2007 and Vista.

The approach you mentioned on the blog is not from Microsoft product group
and will not be supported by Microsoft Customer Support and Service.

Sorry for not clarifying this at first and thanks for your understanding.


Regards,
Walter Wang (***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Sherlock Holmes
2010-09-20 03:21:39 UTC
Permalink
Raw Message
First you need to get GUID of the preview handler for .pdf documents. It's just simple that you can look in registry. After a time searching in the the Registry Editor, I notified that GUID of the preview handler for some file can be found in the following registry path:
HKCR\(file ext)\ShellEx\{8895b1c6-b41f-4c1c-a562-0d564250836f}\(Default Value)

public static Guid GetPreviewHandlerId(string ext)
{
Guid result = Guid.Empty;
RegistryKey key = Registry.ClassesRoot.OpenSubKey(ext + "\\ShellEx\\{8895b1c6-b41f-4c1c-a562-0d564250836f}");
if (key != null)
{
object defaultValue = key.GetValue(String.Empty);
if (defaultValue != null)
result = new Guid(defaultValue.ToString());
}
return result; // returns Guid.Empty if no preview handler found for this file extension
}

And some modification for showing preview handler for .PDF document. Because PDF Preview Handler using IInitializeWithStream, not IInitializeWithFile (I don't know why) so I think your implementation StreamWrapper of IStream interface has many problems (as simple to see almost all of your implementation is nothing). So I modify as follow and get the result as expected. Let's see it yourself.

public static IPreviewHandler GetPreviewHandler(Control parent, Guid previewHandlerId, string fileName, byte[] fileData)
{
//get type by clsid
Type previewerType = Type.GetTypeFromCLSID(previewHandlerId); // previewHandlerId returned by GetPreviewHandlerId(Path.GetExtension(fileName))

//create instance
object instance = Activator.CreateInstance(previewerType);

//now we need to querry interface for the required interfaces.
IObjectWithSite ows = instance as IObjectWithSite;
IPreviewHandler ph = instance as IPreviewHandler;
IInitializeWithFile iwf = instance as IInitializeWithFile;
IInitializeWithStream iws = instance as IInitializeWithStream;

//now we need to initialize the object
if (iwf != null)
{
string tempFolder = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);
fileName = tempFolder + "\\" + fileName;
FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate);
try
{
new BinaryWriter(stream).Write(fileData);
}
finally
{
stream.Close();
stream = null;
}
iwf.Initialize(fileName, 0);
}
else if (iws != null)
{
IStream stream;
IntPtr hGlobal = Marshal.AllocHGlobal(fileData.Length);
Marshal.Copy(fileData, 0, hGlobal, fileData.Length);
CreateStreamOnHGlobal(hGlobal, true, out stream);
if (stream != null)
iws.Initialize(stream, 0);
}

//set the current form (implements IPreviewHandlerFrame)
ows.SetSite(parent);

//set size
RECT rect = new RECT();
rect.left = parent.ClientRectangle.Left;
rect.top = parent.ClientRectangle.Top;
rect.bottom = parent.ClientRectangle.Bottom;
rect.right = parent.ClientRectangle.Right;

ph.SetWindow(parent.Handle, ref rect);
ph.SetRect(ref rect);

//perform the preview
ph.DoPreview();
ph.SetFocus();
return ph;
}

Regards,
Sherlock
Post by nickname
http://blogs.microsoft.co.il/blogs/eyal/
This seems to work for the Word preview handler but the adobe one fails to
"Creating an instance of the COM component with CLSID
{DC6EFB56-9CFA-464D-8880-44885D7DC193} from the IClassFactory failed due to
the following error: 80040154."
Could somebody explain why this is?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices.ComTypes;
using System.IO;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
//http://blogs.microsoft.co.il/blogs/eyal/
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public Rectangle ToRectangle() { return Rectangle.FromLTRB(left,
top, right, bottom); }
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("fc4801a3-2ba9-11cf-a229-00aa003d7352")]
public interface IObjectWithSite
{
void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out
object ppvSite);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
interface IPreviewHandler
{
void SetWindow(IntPtr hwnd, ref RECT rect);
void SetRect(ref RECT rect);
void DoPreview();
void Unload();
void SetFocus();
void QueryFocus(out IntPtr phwnd);
[PreserveSig]
uint TranslateAccelerator(ref MSG pmsg);
}
[StructLayout(LayoutKind.Sequential)]
internal struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int pt_x;
public int pt_y;
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b7d14566-0509-4cce-a71f-0a554233bd9b")]
interface IInitializeWithFile
{
void Initialize([MarshalAs(UnmanagedType.LPWStr)] string
pszFilePath, uint grfMode);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
interface IInitializeWithStream
{
void Initialize(IStream pstream, uint grfMode);
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void PreView(Guid guid, string file)
{
//get type by clsid
Type previewerType = Type.GetTypeFromCLSID(guid);
//create instance
object instance = Activator.CreateInstance(previewerType);
//now we need to querry interface for the required interfaces.
IObjectWithSite ows = (IObjectWithSite)instance;
IPreviewHandler ph = (IPreviewHandler)instance;
IInitializeWithFile iwf = instance as IInitializeWithFile;
IInitializeWithStream iws = instance as IInitializeWithStream;
//now we need to initialize the object
if (iwf != null)
{
iwf.Initialize(file, 0);
}
else
{
if (iws != null)
{
StreamWrapper stream = new StreamWrapper(File.Open(file,
FileMode.Open));
iws.Initialize(stream, 0);
}
}
//set the current form (implements IPreviewHandlerFrame)
ows.SetSite(this);
//set size
RECT rect = new RECT();
rect.left = 0;
rect.top = 0;
rect.bottom = this.Height;
rect.right = this.Width;
ph.SetWindow(this.Handle, ref rect);
ph.SetRect(ref rect);
//perform the preview
ph.DoPreview();
ph.SetFocus();
}
private void Form1_Load(object sender, EventArgs e)
{
//Word (Works Fine)
//PreView(new Guid("{84F66100-FF7C-4fb4-B0C0-02CD7FB668FE}"),
"c:\\test.docx");
//PDF (Does not work)
PreView(new Guid("{DC6EFB56-9CFA-464D-8880-44885D7DC193}"),
"c:\\test.pdf");
}
}
}
internal class StreamWrapper : IStream
{
~StreamWrapper()
{
if (stream != null)
{
stream.Close();
stream.Dispose();
stream = null;
}
}
Stream stream = null;
public StreamWrapper(Stream stream)
{
this.stream = stream;
}
#region IStream Members
public void Clone(out IStream ppstm)
{
ppstm = null;
}
public void Commit(int grfCommitFlags)
{
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr
pcbWritten)
{
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int actual = stream.Read(pv, 0, cb);
Marshal.WriteInt32(pcbRead, actual);
}
public void Revert()
{
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long actual = stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
}
public void SetSize(long libNewSize)
{
}
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG
pstatstg, int grfStatFlag)
{
pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG();
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
}
#endregion
}
Post by Walter Wang [MSFT]
Hi nickname,
Searching the clsid you mentioned reveals that it's "Adobe PDF Preview
Handler for Vista". The error 0x80040154 means REGDB_E_CLASSNOTREG (class
not registered). Either this preview handler is not registered on your
system or it's Vista only (if your current system is not on Vista).
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by nickname
Thank you for the reply. My current system is vista and it must be registered
as it is working in outlook and windows explorer. Any ideas why it is now
working here?
Thanks
Post by Walter Wang [MSFT]
Hi,
Are you running Vista 32-bit or 64-bit version? If you are running 64-bit
version, is your WinForm application compiled as 32-bit or 64-bit version?
(For "Any CPU" configuration, it will JIT compiled as 64-bit when it's run
on a 64-bit version os)
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by nickname
Thank you for your reply, I was trying it on a 64bit version of vista. I have
"Error HRESULT E_FAIL has been returned from a call to a COM component."
iws.Initialize(stream, 0);
Any idea why it is raising this exception, and how can i resolve it?
Thanks for your help
Post by Walter Wang [MSFT]
Hi,
Do you mean you're trying this on a 32-bit os or compiling a 32-bit version
(use Build Configuration Manager to create a new build configuration that
is based on x86) application on the same 64-bit version Vista that we were
talking about?
Also, are you running the application "As Administrator" or not? Is UAC
enabled on your Vista?
E_FAIL is a general COM error code, I cannot tell much about it now. Could
you please give me more information about the detailed steps to reproduce
the issue?
By the way, so far I'm not sure if this issue is specific to Adobe Acrobat
Reader or not. If yes, we might need to refer to Adobe's support for more
information.
Thanks.
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by nickname
Hello,
Thanks for the reply, I am running it now on a 32-bit os, and its compiling
a 32-bit version. UAC is turned off, so is running with full administrator
rights.
iws.Initialize(stream, 0);
I'm not sure if there is any more information I can give you?
Thanks
Post by Walter Wang [MSFT]
Hi,
Thanks for the information. I have been able to reproduce the issue as you
described on Vista.
I'm currently performing further researching on it. I'll keep you updated.
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Walter Wang [MSFT]
Hi,
I've contacted product group on this.
Unfortunately, they told me that currently hosting preview handlers in user
applications is not supported. We only support creating preview handlers
for Office 2007 and Vista.
The approach you mentioned on the blog is not from Microsoft product group
and will not be supported by Microsoft Customer Support and Service.
Sorry for not clarifying this at first and thanks for your understanding.
Regards,
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Submitted via EggHeadCafe - Software Developer Portal of Choice
Auto-Generate Code for LINQ to SQL Repository Pattern using T4
http://www.eggheadcafe.com/tutorials/aspnet/a7ee34d2-c297-4ec8-a933-69254242b21b/autogenerate-code-for-linq-to-sql-repository-pattern-using-t4.aspx
Loading...