SHGetFileInfo for lnk file without lnk overlay arrow - c#

I'm trying to get the icon out of a .lnk file without the .lnk overlay appearing. The documentation has information about a flag SHGFI_ADDOVERLAYS which can be set to add an overlay, but I am looking to remove the overlay.
I have read this question, as well as the links inside of it, but I am still unable to get it working in c#.
Here is the code I have tried:
SHFILEINFO shFileInfo = new SHFILEINFO();
SHGetFileInfo(
pathToLnk,
0,
ref shFileInfo,
(uint)Marshal.SizeOf(shFileInfo),
SHGFI_ICON & ~SHGFI_LINKOVERLAY);
As well as some other configurations of the flags.
Thanks in advance for the help.

The solution is as follows:
[DllImport("Comctl32.dll")]
public static extern IntPtr ImageList_GetIcon(IntPtr himl, int i, uint flags);
SHFILEINFO fileInfo = new SHFILEINFO();
IntPtr list = SHGetFileInfo(
pathToLnk,
FileAttributes,
ref fileInfo,
(uint)Marshal.SizeOf(fileInfo),
SHGFI_SYSICONINDEX);
var iconHandle = ImageList_GetIcon(list, fileInfo.iIcon.ToInt32(), FileFlags);
Icon icn = Icon.FromHandle(iconHandle);

Related

C# PInvoke I can't open the volume with CreateFile

I have to open the volume with CreateFile from PInvoke:
[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, FileOptions dwFlagsAndAttributes, IntPtr hTemplateFile);
But when I use it:
var fileName = #"C:\Users\myuser\Desktop\file.txt"
var root = Path.GetPathRoot(fileName);
var volumePath = #"\\.\" + root.Substring(0, root.Length - 1);
var volume = CreateFile(volumePath, GENERIC_READ, FileShare.Read, IntPtr.Zero, FileMode.Open, FileOptions.None, IntPtr.Zero);
if (volume.IsInvalid)
throw new Win32Exception(Marshal.GetLastWin32Error());
It prints:
Access is denied
However, if I open it with elevated privileges, it prints:
The process cannot access the file because it is being used by another process
I've been trying everything, even picking up code from a lot of places but I can't make it work.
Using the PInvoke code taken from here:
var volume = CreateFile(volumePath, EFileAccess.GenericRead, EFileShare.Read|EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, 0, IntPtr.Zero);
I have managed to get it working.

SendMessage to Notepad++ to open a file

I am trying to programmatically open a file in notepad++ using SendMessage but I'am having no luck.
I figured that because I can drag and drop a file onto Notepad++ and it will open it, that a SendMessage would work.
Declarations:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
Method:
I launch Notepad++ using Process.Start:
IntPtr cHwnd = FindWindowEx(pDocked.MainWindowHandle, IntPtr.Zero, "Scintilla", null);
SendMessage(cHwnd, WM_SETTEXT, 0, "C:\Users\nelsonj\Desktop\lic.txt");
When SendMessage executes it will send my text into the 'edit' section of Notepad++ instead of opening the file.
Any help would be great.
If you simply want to open a file in Notepad++, you can just start a new Process:
set the path of the file you want to open to the Arguments property of the ProcessStartInfo class.
the FileName property is set to the path of the program you want to open.
UseShellExecute and CreateNoWindow are irrelevant here, leave the default.
using System.Diagnostics;
Process process = new Process();
ProcessStartInfo procInfo = new ProcessStartInfo()
{
FileName = #"C:\Program Files\Notepad++\notepad++.exe",
Arguments = Path.Combine(Application.StartupPath, "[Some File].txt"),
};
process.StartInfo = procInfo;
process.Start();
if (process != null) process.Dispose();

C# open file dialog; specify name and extension?

In C#, you can specify a filter on an OpenFileDialog object.
var dlg = new OpenFileDialog();
dlg.DefaultExt = ".xml";
dlg.Filter = "XML Files|*.xml";
Is there a way to automatically select files by name? For example, if I navigated to a folder of xml files, is there any filtering option that would automatically target "myxml.xml"?
Yes, just set the FileName property of the OpenFileDialog like this:
dlg.FileName = "myxml.xml";
However, it would be more appropriate if you use the name in the filter. Just place it instead of the star which acts as a wildcard:
dlg.Filter = "XML Files|myxml.xml";
And always remember you can have multiple filters like this: (It may be useful in the future):
"Image Files (*.bmp, *.jpg)|*.bmp;*.jpg"
// -- OR --
"Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
More documentation on filters at MSDN.
Yes, you can actually set the filter to a complete filename:
dlg.Filter = "myxml Files|myxml.xml";
Note that when this filter is selected, you won't be able to select other XML files. If you simply want to default to that filename while showing and allowing selection of any XML file, go with Fᴀʀʜᴀɴ Aɴᴀᴍ's (original) answer. And now that he copied my answer into his, you can just go with his.
What you can do is either set the FileName property like this:
dlg.FileName = "myxml.xml";
or set the Filter property like this:
dlg.Filter = "XML files|file.xml";
(it's important to check that there's no space at the end like this "file.xml ", because if there is, your file won't show up, in other words OpenFileDialog doesn't trim the Filter property)
if you don't know what the file name is beforehand, you can use DirectoryInfo and FileInfo like this:
DirectoryInfo dir = new DirectoryInfo("PATHHERE");
FileInfo[] files = dir.GetFiles();
and loop through the files to find the one you are looking for
Step 1: Add this method to your code:
[DllImport("shell32.dll", SetLastError = true)]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);
[DllImport("shell32.dll", SetLastError = true)]
public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);
public static void OpenFolderAndSelectItem(string folderPath, string file)
{
IntPtr nativeFolder;
uint psfgaoOut;
SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);
if (nativeFolder == IntPtr.Zero)
return;
IntPtr nativeFile;
SHParseDisplayName(System.IO.Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);
IntPtr[] fileArray;
if (nativeFile == IntPtr.Zero)
{
fileArray = new IntPtr[0];
}
else
{
fileArray = new IntPtr[] { nativeFile };
}
SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);
Marshal.FreeCoTaskMem(nativeFolder);
if (nativeFile != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(nativeFile);
}
}
Step 2: Call the method OpenFolderAndSelectItem(string folderPath, string file) to use.
Step 3: Enjoy!

How to print QR Code using Commands with Zebra RW 420 thermal printer via USB in C#

Before you go on and flag my question as a duplicate, believe me, its
not. I have gone through virtually every solution provided here and I
still can't get to get my app to work, so please will you just be nice
and take some time to help me.
Scenario: I have a Zebra RW 420 thermal printer which I would like to use for printing vouchers with a QR Code on them. I am using C# and have followed all the help as given by Scott Chamberlain here and the code here for sending the commands to the printer. I have the EPL2 manual as well as the CPCL, and ZPL reference manuals with a whole lot of stuff on how to format my commands.
Problem:
All the commands I am sending are either printing as plain text replicas of the commands or the printer just hangs with the small message icon showing on its display. I have tried sending the same commands using the Zebra Utilitis and still getting the same result as with my sample app.
Below is the code snippets I have, please do advise me if there are any reference libraries I may require to get this to work.
private void btnPrint_Click(object sender, RoutedEventArgs e)
{
string s = "! 0 200 200 500 1\nB QR 10 100 M 2 U 10\nMA,QR code ABC123\nENDQR\nFORM\nPRINT";
// Have also tried \r\n for the line feeds with the same result.
// Allow the user to select a printer.
PrintDialog pd = new PrintDialog();
if ((bool)pd.ShowDialog())
{
var bytes = Encoding.ASCII.GetBytes(s);
// Send a printer-specific to the printer.
RawPrinterHelper.SendBytesToPrinter(pd.PrintQueue.FullName, bytes, bytes.Length);
}
}
PrinterHelper class as modified by Scott here
public class RawPrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter,
IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level,
[In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten);
// SendBytesToPrinter()
// When the function is given a printer name and an unmanaged array
// of bytes, the function sends those bytes to the print queue.
// Returns true on success, false on failure.
public static bool SendBytesToPrinter(string szPrinterName, byte[] pBytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
di.pDocName = "Zebra Label";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// Start a document.
if (StartDocPrinter(hPrinter, 1, di))
{
// Start a page.
if (StartPagePrinter(hPrinter))
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
throw new Win32Exception(dwError);
}
return bSuccess;
}
}
I did a lot of work on Zebra ZT230 and GX430t printers last year, and the thing I found out about them was using the ZPL instructions over TCP sockets via port 9100 was a LOT more reliable.
I know this is taking your conversation in a very different direction, but having tried the spool / Win32 approach I can tell you using sockets was a lot more reliable. Let me know if you need some sample code.
Wrote a kiosk application using a KR403 last year. I was able to
successfully print and poll the status of the printer to see if there
was a paper jam low paper etc via usb using the blog post below.
http://danielezanoli.blogspot.com/2010/06/usb-communications-with-zebra-printers.html
Using print spooler (Print only)
https://sharpzebra.codeplex.com/SourceControl/latest#src/Com.SharpZebra/Printing/RawPrinter.cs
I used the ZebraDesigner to do my initial layout. On the print screen
inside the zebra designer there is a print to file option that will
save your design as a txt file with ZPL in it. I then took that file
broke it up into sections and created a helper class that uses a
StringBuilder internally so I could focus on certain pieces of the zpl
since it can be overwhelming to look at more than 1-2 lines.
var kioskTicketBuilder = new KioskTicketBuilder();
kioskTicketBuilder.SetPrinterDefaults();
kioskTicketBuilder.DisplayTicketHeader();
kioskTicketBuilder.DisplayInformationHeading(data.Name, data.todaysDate, data.ClientName, data.ClientCode);
kioskTicketBuilder.DisplayMoreStuff()
kioskTicketBuilder.DisplayBarcode(data.TrackingId);
kioskTicketBuilder.EndOfJob();
return kioskTicketBuilder.GetPrintJobToArray();
Also if you go to the the printer properties > Printing Defaults > Tools
Tab There is an option to send a file of zpl to the printer or send
individual commands. This is really good for testing your zpl seperate
from your application.

scan & save as PDF in c#

IM using the TWAIN Scanner & gdiplus.dll.
i scanned the file , and can save as image format like *.jpg, *.bmp
but it is not allow to save as in PDF format. Showing an error unknown format picture.
this is the code,
public static bool SaveDIBAs(string picname, IntPtr bminfo, IntPtr pixdat)
{
SaveFileDialog sd = new SaveFileDialog();
sd.FileName = picname;
sd.Title = "Save bitmap as...";
sd.Filter = "PDF (*.pdf)|*.pdf";
sd.Filter = "Bitmap file (*.bmp)|*.bmp|TIFF file (*.tif)|*.tif|JPEG file (*.jpg)|*.jpg|PNG file (*.png)|*.png|PDF file (*.pdf)|*.pdf|All files (*.*)|*.*";
sd.FilterIndex = 1;
if (sd.ShowDialog() == DialogResult.OK)
return false;
Guid clsid;
if (!GetCodecClsid(sd.FileName, out clsid))
{
//MessageBox.Show("Unknown picture format for extension " + Path.GetExtension(sd.FileName),
"Image Codec", MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
IntPtr img = IntPtr.Zero;
int st = GdipCreateBitmapFromGdiDib( bminfo, pixdat, ref img );
if( (st != 0) || (img == IntPtr.Zero) )
return false;
st = GdipSaveImageToFile(img, sd.FileName, ref clsid, IntPtr.Zero);
GdipDisposeImage(img);
return st == 0;
}
[DllImport("gdiplus.dll", ExactSpelling=true)]
internal static extern int GdipCreateBitmapFromGdiDib( IntPtr bminfo, IntPtr pixdat, ref IntPtr image );
[DllImport("gdiplus.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
internal static extern int GdipSaveImageToFile( IntPtr image, string filename, [In] ref Guid clsid, IntPtr encparams );
[DllImport("gdiplus.dll", ExactSpelling=true)]
internal static extern int GdipDisposeImage( IntPtr image );
}
****The above code doesnt allow to save as in PDF format.****
first you'd need to acquire the image using either TWAIN or WIA and then once you've captured that image you need to convert it to PDF using something like abcPDF
Not entirely sure what you are talking about, but this library: http://sourceforge.net/projects/pdflibrary/ is excellent for saving a PDF.
For scanning (from a TWAIN Scanner?) check out http://www.codeproject.com/KB/dotnet/twaindotnet.aspx Ive done that before, and it seems to work pretty well.
It will not save as PDF at all, because GDI library of Microsoft doesnt have PDF facility, the best way to do is save your file as JPEG first in temporary file. And then use iTextSharp library or PDFSharp library to create PDF out of JPEG, you can embed your JPG/Bitmap any sort of file inside PDF using these two libraries.
if you're using GDI. Print directly to a PDF printer (I use bullzip pdf myself because it's free and has a silent print feature)

Categories