How to pass an array of integers as a property value in the Configuration object for MapReduce? - mapreduce

We can pass an integer as a Configuration property as below:
Configuration conf = new Configuration();
conf.set("size", 4);
Is there a way to send an array of integers as a property value?
conf.set("list.of.nums", {2, 4, 6, 8}); // one way is to pass them as a String but it doesn't look good

You can serialize the array object into a file and then move the file to HDFS.Then you can add the hdfs file path to Distributed cache using following.
DistributedCache.addCacheFile(new URI(dfsMetaPath + "#"
+ Constants.OBJSYMLINK0), conf);
DistributedCache.createSymlink(conf);
Serialization can be done as follows:-
public static <T> void serializeMetadata(T voObj,
String filePath) throws IOException,NullPointerException {
if(null==voObj){
throw new NullPointerException("NULL object found");
}
ObjectOutputStream oout = null;
FileOutputStream fsout = null;
try {
fsout = new FileOutputStream(filePath);
oout = new ObjectOutputStream(fsout);
oout.writeObject(voObj);
oout.close();
} finally {
if (null != fsout) {
fsout.close();
}
if (null != oout) {
oout.close();
}
}
}
You can use the filepath passed as arguments to the above method.Using this filepath you can move the file to HDFS filepath. Use the HDFS filepath to create the symlink.
To retireve in mapper you can use the following inside setup to get the object back.
File hdfsfilepath = new File(Constants.OBJSYMLINK0);
Integer[] youarray = MetadataSerDeUtils.deserializeMetadata(youarray ,
hdfsfilepath.getAbsolutePath());
For deserialization you can use following code:-
public static <T> T deserializeMetadata(T voObj,
String filePath) throws IOException,NullPointerException, ClassNotFoundException {
FileInputStream fsin = null;
ObjectInputStream oin = null;
try {
fsin = new FileInputStream(filePath);
oin = new ObjectInputStream(fsin);
voObj = (T) oin.readObject();
return voObj;
} finally {
if (null != fsin) {
fsin.close();
}
if (null != oin) {
oin.close();
}
}
}

Related

How to know file is from internal or external storage in android?

I want to know how to figure out file path is from internal or external storage.
I want to delete a file. Before deleting it i want to check whether it is from internal memory or external.
if file is from internal storage then i can simply delete it like this
file.delete();
But if file is from external storage (sdcard). Then i would first check permission then delete it through storage access framework.
I'm currently doing like this.
File selectedFile = Constant.allMemoryVideoList.get(fPosition).getFile().getAbsoluteFile();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (???????????? check if file is not from internal storage ???????????) {
List<UriPermission> permissions = getContentResolver().getPersistedUriPermissions();
if (permissions != null && permissions.size() > 0) {
sdCardUri = permissions.get(0).getUri();
deleteFileWithSAF();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Please select external storage directory (e.g SDCard)")
.setMessage("Due to change in android security policy it is not possible to delete or rename file in external storage without granting permission")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// call document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
} else {
deleteFile();
}
} else {
deleteFile();
}
deleteFileWithSAF()
private void deleteFileWithSAF() {
//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);
//Then we split file path into array of strings.
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
// There is a reason for having two similar names "MyFolder" in
//my exmple file path to show you similarity in names in a path will not
//distract our hiarchy search that is provided below.
String[] parts = (selectedFile.getPath()).split("\\/");
// findFile method will search documentFile for the first file
// with the expected `DisplayName`
// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
for (int i = 3; i < parts.length; i++) {
if (documentFile != null) {
documentFile = documentFile.findFile(parts[i]);
}
}
if (documentFile == null) {
// File not found on tree search
// User selected a wrong directory as the sd-card
// Here must inform user about how to get the correct sd-card
// and invoke file chooser dialog again.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Please select root of external storage directory (click SELECT button at bottom)")
.setMessage("Due to change in android security policy it is not possible to delete or rename file in external storage without granting permission")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// call for document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
} else {
// File found on sd-card and it is a correct sd-card directory
// save this path as a root for sd-card on your database(SQLite, XML, txt,...)
// Now do whatever you like to do with documentFile.
// Here I do deletion to provide an example.
if (documentFile.delete()) {// if delete file succeed
// Remove information related to your media from ContentResolver,
// which documentFile.delete() didn't do the trick for me.
// Must do it otherwise you will end up with showing an empty
// ImageView if you are getting your URLs from MediaStore.
getApplicationContext().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(selectedFile)));
// Methods.removeMedia(this,selectedFile.getPath());
if (deleteSingleFileCall){
Constant.allMemoryVideoList.remove(videoPosition);
adapter.notifyItemRemoved(videoPosition);
deleteSingleFileCall = false;
}
/*update the playback record to
* getFileName() contain file.getName()*/
for (int i = 0; i < Constant.filesPlaybackHistory.size(); i++) {
if ((selectedFile.getName()).equals(Constant.filesPlaybackHistory.get(i).getFileName())) {
Constant.filesPlaybackHistory.remove(i);
break;
}
}
//save the playback history
Paper.book().write("playbackHistory", Constant.filesPlaybackHistory);
}
}
}
This is how i load files of both internal and external storage.
StorageUtil is library https://github.com/hendrawd/StorageUtil
String[] allPath = StorageUtil.getStorageDirectories(this);
private File directory;
for (String path: allPath){
directory = new File(path);
Methods.load_Directory_Files(directory);
}
All Loaded files in following arraylist.
//all the directory that contains files
public static ArrayList<File> directoryList = null;
//list of all files (internal and external)
public static ArrayList<FilesInfo> allMemoryVideoList = new ArrayList<>();
FilesInfo: Contain all info about file like thumbnail, duration, directory, new or played before, if played then last playback position etc
LoadDirectoryFiles()
public static void load_Directory_Files(File directory) {
//Get all file in storage
File[] fileList = directory.listFiles();
//check storage is empty or not
if(fileList != null && fileList.length > 0)
{
for (int i=0; i<fileList.length; i++)
{
boolean restricted_directory = false;
//check file is directory or other file
if(fileList[i].isDirectory())
{
for (String path : Constant.removePath){
if (path.equals(fileList[i].getPath())) {
restricted_directory = true;
break;
}
}
if (!restricted_directory)
load_Directory_Files(fileList[i]);
}
else
{
String name = fileList[i].getName().toLowerCase();
for (String ext : Constant.videoExtensions){
//Check the type of file
if(name.endsWith(ext))
{
//first getVideoDuration
String videoDuration = Methods.getVideoDuration(fileList[i]);
long playbackPosition;
long percentage = C.TIME_UNSET;
FilesInfo.fileState state;
/*First check video already played or not. If not then state is NEW
* else load playback position and calculate percentage of it and assign it*/
//check it if already exist or not if yes then start from there else start from start position
int existIndex = -1;
for (int j = 0; j < Constant.filesPlaybackHistory.size(); j++) {
String fListName = fileList[i].getName();
String fPlaybackHisName = Constant.filesPlaybackHistory.get(j).getFileName();
if (fListName.equals(fPlaybackHisName)) {
existIndex = j;
break;
}
}
try {
if (existIndex != -1) {
//if true that means file is not new
state = FilesInfo.fileState.NOT_NEW;
//set playbackPercentage not playbackPosition
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(fileList[i].getPath());
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
retriever.release();
int duration = Integer.parseInt(time);
playbackPosition = Constant.filesPlaybackHistory.get(existIndex).getPlaybackPosition();
if (duration > 0)
percentage = 1000L * playbackPosition / duration;
else
percentage = C.TIME_UNSET;
}
else
state = FilesInfo.fileState.NEW;
//playbackPosition have value in percentage
Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
directory,videoDuration, state, percentage, storageType));
//directory portion
currentDirectory = directory.getPath();
unique_directory = true;
for(int j=0; j<directoryList.size(); j++)
{
if((directoryList.get(j).toString()).equals(currentDirectory)){
unique_directory = false;
}
}
if(unique_directory){
directoryList.add(directory);
}
//When we found extension from videoExtension array we will break it.
break;
}catch (Exception e){
e.printStackTrace();
Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
directory,videoDuration, FilesInfo.fileState.NOT_NEW, C.TIME_UNSET, storageType));
}
}
}
}
}
}
Constant.directoryList = directoryList;
}
Image So reader could easily understand what is going on.

Appending a pointer to a Qlist

this is my first post here!
I'm working on a code that parses Json to fill a struct that I append to a Qlist of tests to run.
My problem is with the payload inside my struct: when I send the first object in my list the payload it is not empty when it should be.
struct FrameTest {
QString protocol;
QString Length;
QByteArray *payload;
};
QList<FrameTest> _validTestLists;
FrameTest TxFrame;
Code of the JSON parser
void Cesa::JsonParser(QJsonObject _ScriptTestObject)
{
TxFrame.protocol = "00";
TxFrame.Length = "00";
TxFrame.payload = new QByteArray();
for(QJsonObject::iterator it = _ScriptTestObject.begin(); it!=_ScriptTestObject.end(); ++it)
{
TxFrame.protocol= "00";
TxFrame.Length = "00";
TxFrame.payload->clear();
_CmdObject = _ScriptTestObject.value(key).toObject(); // Get Json object
if (_CmdObject.contains("Board") && _CmdObject.value("Board") == "Exia")
{
QString payload;
TxFrame.protocol= "03";
TxFrame.Length = "06";
payload = QString("%1").arg(obj.value("hopPeriod").toInt(), 2, 16, QChar('0'));
}
else if (_CmdObject.contains("Board") && _CmdObject.value("Board") == "Cevee")
{
TxFrame.protocol= "03";
TxFrame.Length = "06";
}
_testLists.append(TxFrame);
}
Test(_testLists); // Test with only one object
Function for sending via port COM
bool Cesa::Test(FrameTest frame)
{
QByteArray txFrame;
/* Transmit command */
txFrame.insert(0, frame.protocol);
txFrame.insert(2, frame.Length);
txFrame.insert(4, *frame.payload);
_comPort->write(QByteArray::fromHex(txFrame));
}
I'm a student still learning coding, any help and advice will be appreciated :)

How to custom a classloader

I'm trying to implementing this function with a customer classloader: I have some class files in a alternatives.jar file, they provide different implementation than normal implementation. i.e., each class in this jar, has another version which in other jar file -- also get loaded in the classpath.
I know it's better to use instrument API to achieve same purpose. But now my concern is I need to understand why I'm failing.
So this is my method:
1. define a AlternativeClassLoader.java, in this file, I override findClass method. So if the class name can be found from alternatives.jar, then use the version from alternatives.jar.
2. in constructor, I have called super(null) so all these class loading work will be performed by my classloader, rather that system's.
3. This (seems to be true) also requires me to load other classes (if they're not system one). So I have to parse classpath, find all classes which indicated by the classpath.
My problem is, I can load my alternative class, everything seems to be fine...However, I'm using slf4j which yells the following error:
Failed to auto configure default logger context
Reported exception:
ch.qos.logback.core.joran.spi.JoranException: Parser configuration error occurred
Failed to instantiate [ch.qos.logback.classic.LoggerContext]
Reported exception:
java.lang.ExceptionInInitializerError
at java.util.ResourceBundle.getLoader(ResourceBundle.java:431)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:841)
I doubt this is caused by my bad classloader implementation. Would somebody help me out? Many thanks!
This is my classloader:
public class AlternativeClassLoader extends ClassLoader {
private static final String ALTERNATIVE_JAR_PROPERTY = "alternativejar";
private static final Logger logger = LoggerFactory
.getLogger(AlternativeClassLoader.class);
private Map<String, Class<?>> clzCache = new HashMap<String, Class<?>>();
private Map<String, String> others = new HashMap<String, String>();
private Set<String> alternativesRegistry;
private JarFile altjar;
public AlternativeClassLoader(ClassLoader parent) {
/*
* pass null so I can incept all class loading except system's. By doing
* this you'll need to override findClass
*/
super(null);
registerAlternatives();
registerOthers();
}
/**
* This method will parse classpath and get all non-system class name, and
* build classname - jar_file_path/file_system_path mappings
*/
private void registerOthers() {
String[] paths = System.getProperty("java.class.path").split(":");
URL[] urls = new URL[paths.length];
for (String path : paths) {
if (path.endsWith("*.jar")) {
registerClass(path, others);
} else {
File f = new File(path);
if (!f.isDirectory())
continue;
File[] classFiles = f.listFiles(new FileFilter() {
#Override
public boolean accept(File arg0) {
if (arg0.getName().endsWith(".class")) {
return true;
} else {
return false;
}
}
});
for (File file : classFiles) {
String fileName = file.getName();
String className = fileName.substring(0,
fileName.lastIndexOf("."));
others.put(className, file.getPath());
}
}
}
showRegistry(
"Me will also be responsible for loading the following classes:",
others);
}
private void registerClass(String path, Map<String, String> registry) {
try {
JarInputStream jis = new JarInputStream(new FileInputStream(path));
for (JarEntry entry = jis.getNextJarEntry(); entry != null; entry = jis
.getNextJarEntry()) {
if (entry.getName().endsWith(".class") && !entry.isDirectory()) {
StringBuilder className = new StringBuilder();
for (String part : entry.getName().split("/")) {
if (className.length() != 0)
className.append(".");
className.append(part);
if (part.endsWith(".class"))
className.setLength(className.length()
- ".class".length());
}
registry.put(className.toString(), path);
}
}
} catch (Exception e) {
e.printStackTrace(System.out);
logger.error(
"Failed when read/parse jar {}. Your class file may not been replaced by alternative implementation",
path, e);
}
}
/**
* Try to find alternative class implementation from jar file specified by
* ALTERNATIVE_JAR_PROPERTY. If it's not specified, then use same jar file
* where this classloader is loaded.
*/
private void registerAlternatives() {
String jarFilePath = System.getProperty(ALTERNATIVE_JAR_PROPERTY);
if (jarFilePath == null || jarFilePath.isEmpty()) {
URL url = getClass().getProtectionDomain().getCodeSource()
.getLocation();
System.out.println(url + ":" + url.toString());
jarFilePath = url.getPath();
}
try {
altjar = new JarFile(jarFilePath);
} catch (IOException e) {
logger.error("cannot read jar {}", jarFilePath);
return;
}
Map<String, String> registry = new HashMap<String, String>();
registerClass(jarFilePath, registry);
alternativesRegistry = registry.keySet();
showRegistry("===Found the following alternative class:===", registry);
}
private void showRegistry(String string, Map<String, String> registry) {
System.out.println(string);
for (String clzName : registry.keySet()) {
System.out.printf("Class:%30s ->%s\n", clzName,
registry.get(clzName));
}
}
private Class<?> myLoadClass(String name) throws IOException,
ClassFormatError {
logger.debug("myload class {}", name);
System.out.printf("myload class %s\n", name);
if (alternativesRegistry.contains(name) && altjar != null) {
JarEntry entry = altjar.getJarEntry(name + ".class");
InputStream is = altjar.getInputStream(entry);
return readClassData(name, is);
}
String path = others.get(name);
if (path == null || path.isEmpty()) {
return null;
}
if (path.endsWith(".jar")) {
JarFile jar = new JarFile(path);
JarEntry entry = jar.getJarEntry(name + ".class");
InputStream is = jar.getInputStream(entry);
return readClassData(name, is);
} else {// it's a folder, need to read clz from .class file
System.out.printf("file path for %s is %s\n", name, path);
InputStream is = new FileInputStream(new File(path));
return readClassData(name, is);
}
}
private Class<?> readClassData(String name, InputStream is)
throws IOException, ClassFormatError {
byte[] buffer = new byte[4096];
ByteArrayOutputStream out = new ByteArrayOutputStream(buffer.length);
int len = is.read(buffer);
while (len > 0) {
out.write(buffer, 0, len);
len = is.read(buffer);
}
Class<?> clz = defineClass(name, out.toByteArray(), 0, out.size());
if (clz != null) {
System.out.printf("loaded %s by me\n", name);
clzCache.put(name, clz);
}
return clz;
}
protected Class<?> findCachedClass(String name)
throws ClassNotFoundException {
Class<?> clz = clzCache.get(name);
if (clz == null) {
clz = findLoadedClass(name);
}
return clz;
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("findClass: " + name);
Class<?> cls = findCachedClass(name);
if (cls == null) {
try {
cls = myLoadClass(name);
} catch (ClassFormatError | IOException e) {
logger.error("failed to load class {}", name, e);
System.out.printf("failed to load class %s\n", name);
e.printStackTrace();
}
}
return cls;
}
}
I have tried to override findResource(), but it's never called.
This is how I put my classloader into use:
java -Djava.system.class.loader=AlternativeClassLoader -classpath=.:./alternatives.jar:./slf4j-xxx.jar Test
OK, I solved the problem. The tricky is:
Never use any package other than java.*. Otherwise, it will cause recursively loading ...IllegalState error.
In your classloader constructor, load all the alternative class and cache them.
In your constructor, call super(parent) other than super(null), then you don't need to do all the class loading stuff, the parent classloader can do it for you.
in override findClass(), if the class can be found from cache (means they have alternative implementation), then return it, otherwise let super.findClass do the rest for you.
so the following is the source code:
public class AlternativeClassLoader extends ClassLoader {
private static final String ALTERNATIVE_JAR_PROPERTY = "alternativejar";
private Map<String, Class<?>> clzCache = new HashMap<String, Class<?>>();
public AlternativeClassLoader(ClassLoader parent) {
super(parent);
loadAlternativeClasses();
}
private void loadAlternativeClasses() {
String jarFilePath = System.getProperty(ALTERNATIVE_JAR_PROPERTY);
if (jarFilePath == null || jarFilePath.isEmpty()){
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
System.out.println(url + ":" + url.toString());
jarFilePath = url.getPath();
}
JarInputStream jis;
try {
jis = new JarInputStream(new FileInputStream(jarFilePath));
JarEntry entry;
while ((entry = jis.getNextJarEntry()) != null){
String className = entry.getName();
className = className.substring(0, className.length() - ".class".length());
System.out.printf("loading class from %s: %s\n", jarFilePath, className);
readClassData(className, jis);
}
} catch (IOException e) {
e.printStackTrace();
}
} private Class<?> readClassData(String name, InputStream is) throws IOException,
ClassFormatError {
byte[] buffer = new byte[4096];
ByteArrayOutputStream out = new ByteArrayOutputStream(buffer.length);
int len = is.read(buffer);
while (len > 0) {
out.write(buffer, 0, len);
len = is.read(buffer);
}
Class<?> clz = defineClass(name, out.toByteArray(), 0, out.size());
if (clz != null) {
System.out.printf("loaded %s by myself\n", name);
clzCache.put(name, clz);
}
return clz;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("findClass: " + name);
Class<?> cls = clzCache.get(name);
if (cls == null)
cls = super.findClass(name);
return cls;
}
}

How to convert zip file containing xml into byte array without not using zipfile entries in java

I have a zip file containing xml file generated in Java.And I will send the zip file to Web Service in byte array format.The code snippet to convert zip file into byte array is
public static byte[] FileToArrayOfBytes(ZipFile file) throws IOException {
final Enumeration<? extends ZipEntry> entries = file.entries();
final ZipEntry entry = entries.nextElement();
BufferedInputStream istream = new BufferedInputStream(
file.getInputStream(entry));
int file_size = (int) entry.getCompressedSize();
byte[] blob = new byte[file_size];
int bytes_read = 0;
int offset = 0;
while ((bytes_read = istream.read(blob, 0, file_size)) != -1) {
offset += bytes_read;
}
file.close();
istream.close();
return blob;
}
When I send the byte array returned from above method,web service is returning an error message as 'invalid file extensions'.Normally we know web service accepts zip file.
Can you help me how can I handle the problem ?
I handled the my problem as following
public static byte[] convertFileIntoArrayOfBytes(String zipFilePath) {
FileInputStream fileInputStream = null;
File file = new File(zipFilePath);
byte[] bFile = new byte[(int) file.length()];
try {
// convert file into array of bytes
fileInputStream = new FileInputStream(zipFilePath);
fileInputStream.read(bFile);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}

Shell Extension DLL - how to capture the folder path, if user clicks inside the folder empty area?

Using shell extension dll, how to capture the folder path, if user clicks inside the folder empty area?
If you're implementing a shell extension dll, then you get the path in your IShellExtInit::Initialize() method as the pidlFolder parameter.
To make sure your extension is also registered for folder backgrounds, you have to create the appropriate entries also under HKCR\Directory\Background\shellex\ContextMenuHandlers
With VC++ language please reference Winmerge souce code
http://sourceforge.net/p/winmerge/code/HEAD/tree/trunk/ShellExtension/
With C# please reference this article
http://www.codeproject.com/Articles/174369/How-to-Write-Windows-Shell-Extension-with-NET-Lang
and update some place bellow:
At FileContextMenuExt.cs file:
...............
#region Shell Extension Registration
[ComRegisterFunction()]
public static void Register(Type t)
{
try
{
ShellExtReg.RegisterShellExtContextMenuHandler(t.GUID, "Directory",
"CSShellExtContextMenuHandler.FileContextMenuExt Class");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // Log the error
throw; // Re-throw the exception
}
}
[ComUnregisterFunction()]
public static void Unregister(Type t)
{
try
{
ShellExtReg.UnregisterShellExtContextMenuHandler(t.GUID, "Directory");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // Log the error
throw; // Re-throw the exception
}
}
#endregion
...............
public void Initialize(IntPtr pidlFolder, IntPtr pDataObj, IntPtr hKeyProgID)
{
if (pDataObj == IntPtr.Zero && pidlFolder == IntPtr.Zero)
{
throw new ArgumentException();
}
FORMATETC fe = new FORMATETC();
fe.cfFormat = (short)CLIPFORMAT.CF_HDROP;
fe.ptd = IntPtr.Zero;
fe.dwAspect = DVASPECT.DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED.TYMED_HGLOBAL;
STGMEDIUM stm = new STGMEDIUM();
try
{
if (pDataObj != IntPtr.Zero)
{
// The pDataObj pointer contains the objects being acted upon. In this
// example, we get an HDROP handle for enumerating the selected files
// and folders.
IDataObject dataObject = (IDataObject)Marshal.GetObjectForIUnknown(pDataObj);
dataObject.GetData(ref fe, out stm);
// Get an HDROP handle.
IntPtr hDrop = stm.unionmember;
if (hDrop == IntPtr.Zero)
{
throw new ArgumentException();
}
// Determine how many files are involved in this operation.
uint nFiles = NativeMethods.DragQueryFile(hDrop, UInt32.MaxValue, null, 0);
// This code sample displays the custom context menu item when only
// one file is selected.
if (nFiles == 1)
{
// Get the path of the file.
StringBuilder fileName = new StringBuilder(260);
if (0 == NativeMethods.DragQueryFile(hDrop, 0, fileName,
fileName.Capacity))
{
Marshal.ThrowExceptionForHR(WinError.E_FAIL);
}
this.selectedFile = fileName.ToString();
}
else
{
Marshal.ThrowExceptionForHR(WinError.E_FAIL);
}
}
if (pidlFolder != IntPtr.Zero) {
StringBuilder folderName = new StringBuilder(260);
if (0 == NativeMethods.SHGetPathFromIDList(pidlFolder, folderName))
{
Marshal.ThrowExceptionForHR(WinError.E_FAIL);
}
this.selectedFile = folderName.ToString();
}
}
finally
{
NativeMethods.ReleaseStgMedium(ref stm);
}
}
At ShellExtLib.cs file Add folowing source:
[DllImport("shell32.dll")]
public static extern Int32 SHGetPathFromIDList(
IntPtr pidl, // Address of an item identifier list that
// specifies a file or directory location
// relative to the root of the namespace (the
// desktop).
StringBuilder pszPath); // Address of a buffer to receive the file system
And update RegisterShellExtContextMenuHandler and UnregisterShellExtContextMenuHandler function at ShellExtLib.cs file
public static void RegisterShellExtContextMenuHandler(Guid clsid,
string fileType, string friendlyName)
{
if (clsid == Guid.Empty)
{
throw new ArgumentException("clsid must not be empty");
}
if (string.IsNullOrEmpty(fileType))
{
throw new ArgumentException("fileType must not be null or empty");
}
// If fileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (fileType.StartsWith("."))
{
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
{
if (key != null)
{
// If the key exists and its default value is not empty, use
// the ProgID as the file type.
string defaultVal = key.GetValue(null) as string;
if (!string.IsNullOrEmpty(defaultVal))
{
fileType = defaultVal;
}
}
}
}
else {
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
string keyName1 = string.Format(#"{0}\Background\shellex\ContextMenuHandlers\{1}",
fileType, clsid.ToString("B"));
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName1))
{
// Set the default value of the key.
if (key != null && !string.IsNullOrEmpty(friendlyName))
{
key.SetValue(null, friendlyName);
}
}
}
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
string keyName = string.Format(#"{0}\shellex\ContextMenuHandlers\{1}",
fileType, clsid.ToString("B"));
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName))
{
// Set the default value of the key.
if (key != null && !string.IsNullOrEmpty(friendlyName))
{
key.SetValue(null, friendlyName);
}
}
}
public static void UnregisterShellExtContextMenuHandler(Guid clsid,
string fileType)
{
if (clsid == null)
{
throw new ArgumentException("clsid must not be null");
}
if (string.IsNullOrEmpty(fileType))
{
throw new ArgumentException("fileType must not be null or empty");
}
// If fileType starts with '.', try to read the default value of the
// HKCR\<File Type> key which contains the ProgID to which the file type
// is linked.
if (fileType.StartsWith("."))
{
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType))
{
if (key != null)
{
// If the key exists and its default value is not empty, use
// the ProgID as the file type.
string defaultVal = key.GetValue(null) as string;
if (!string.IsNullOrEmpty(defaultVal))
{
fileType = defaultVal;
}
}
}
}
else {
// Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
string keyName1 = string.Format(#"{0}\Background\shellex\ContextMenuHandlers\{1}",
fileType, clsid.ToString("B"));
Registry.ClassesRoot.DeleteSubKeyTree(keyName1, false);
}
// Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}.
string keyName = string.Format(#"{0}\shellex\ContextMenuHandlers\{1}",
fileType, clsid.ToString("B"));
Registry.ClassesRoot.DeleteSubKeyTree(keyName, false);
}