views:

518

answers:

1

Hmmm. Okay after revisiting PInvoke, I'm sure that I don't quite get it :-/ (just asked this question)

Let me illustrate the code I need to handle. It works when I use "Add Reference --> COM --> Microsoft Shell Controls and Automatation" ... but sadly it places a reference in my project that looks like this: "C:\Users\Tim\Documents\Visual Studio 2008\Projects\Wing\FileWing\obj\Debug\Interop.Shell32.dll"

I'm digging though the recycling bin and seek for a item that I want to recover. Is there any way NOT fighting through the PInvoke to get this done? Or to get a reference to the system32/shell32.dll that lets me use this code at runtime?

private void recoverRecyclerBinEntry(string fileName, int size)
{
    try
    {
        Shell Shl = new Shell();
        Folder Recycler = Shl.NameSpace(10);

        // scans through all the recyclers entries till the one to recover has been found
        for (int i = 0; i < Recycler.Items().Count; i++)
        {
            FolderItem FI = Recycler.Items().Item(i);
            string FileName = Recycler.GetDetailsOf(FI, 0);
            if (Path.GetExtension(FileName) == "")
                FileName += Path.GetExtension(FI.Path);
            //Necessary for systems with hidden file extensions.

            string FilePath = Recycler.GetDetailsOf(FI, 1);
            string combinedPath = Path.Combine(FilePath, FileName);

            if (size == FI.Size && fileName == combinedPath)
            {
                Debug.Write("Match found. Restoring " + combinedPath + "...");
                Undelete(FI);
                Debug.WriteLine("done.");
            }
            else
            {
                Debug.WriteLine("No match");
            }
        }
    } 
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
        Debug.WriteLine(ex.StackTrace);
    }
}

private bool Undelete(FolderItem Item)
{
    try
    {
        foreach (FolderItemVerb FIVerb in Item.Verbs())
        {
            if (
                (FIVerb.Name.ToUpper().Contains("WIEDERHERSTELLEN")) ||
                (FIVerb.Name.ToUpper().Contains("ESTORE")) ||
                (FIVerb.Name.ToUpper().Contains("NDELETE"))
                )
            {
                FIVerb.DoIt();
                return true;
            }
        }
        //execute the first one:
        Item.Verbs().Item(0).DoIt();
        return true;
    }
    catch (Exception)
    {
        Debug.WriteLine("ERROR undeleting");
        return false;
    }
}
+2  A: 

Right now you're mixing 2 different concepts: PInvoke and COM Interop.

PInvoke allows you to access native C functions from within managed code. It works by defining a marshal compatible signature of the native method in managed code and marking it with the DllImport attribute. It requires, and cannot have, a metadata reference to the native DLL. The DLL is discovered at runtime using normal loading rules for a Win32 DLL.

COM Interop allows you to access COM compatible objects from managed code. This is done by getting a marshal compatible managed definition of the COM interface and then gaining a referece to the object in one of several ways. Getting the managed definition is often accomplished by means of adding a metadata reference to the PIA (primary interop assembly) for the COM component. Until C# 4.0, this reference cannot be removed, without a lot of work, and must be deployed with your application.

In this particular example you are using COM interop and not PInvoke.

JaredPar
First off - sorry, just finished university and they don't teach winapis there ;-) Okay, so I use COM interop. You say I need a reference to the interop assembly. I guess this is this stuff here, which is rather small and okay for me: ..\Visual Studio 2008\Projects\Wing\FileWing\obj\Debug\Interop.Shell32.dllNow my question is: how can I influence where this object is created (like setting the path of this object somewhere else) or how can I deploy this object before, so it is installed with my application?
Akku
@Tim, I don't believe you can influence where it's created. It's done automatically by the build system. To deploy it simply copy it into the destination folder of your application.
JaredPar
Thanks! This is exactly what I needed to do :-)
Akku