English 中文(简体)
Is there a managed API for kernel32.searchpath?
原标题:

Is there a managed API for kernel32.searchpath? i.e not using a pinvoke.

http://www.pinvoke.net/default.aspx/kernel32.searchpath

最佳回答
    static void Main(string[] args)
    {

        string lpPath = null;
        string lpFileName = "notepad";
        string lpExtension = ".exe";
        int nBufferLength = 255;
        string lpBuffer = "";
        string lpFilePart = "";

        int bufferSize = SearchPath(lpPath, lpFileName, lpExtension, nBufferLength, out lpBuffer, out lpFilePart);

    }

    private static int SearchPath(string lpPath, string lpFileName, string lpExtension, int nBufferLength, out string lpBuffer, out string lpFilePart)
    {
        // lpPath [in, optional] 
        // The path to be searched for the file. 
        // If this parameter is NULL, the function searches for a matching file using a registry-dependent system search path.

        //lpFileName [in] 
        //The name of the file for which to search.

        //lpExtension [in, optional] 
        //The extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. 

        //If a file name extension is not required or if the file name contains an extension, this parameter can be NULL.

        //nBufferLength [in] 
        //The size of the buffer that receives the valid path and file name, in TCHARs.

        //lpBuffer [out] 
        //A pointer to the buffer to receive the path and file name of the file found. The string is a null-terminated string.

        //lpFilePart [out, optional] 
        //A pointer to the variable to receive the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash () in the path.

        //Return Value
        //If the function succeeds, the value returned is the length, in TCHARs, of the string that is copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer that is required to hold the path.

        //If the function fails, the return value is zero. 

        List<string> pathsToSearch = new List<string>();
        string currentWorkingFolder = Environment.CurrentDirectory;
        string path = System.Environment.GetEnvironmentVariable("path");
        lpBuffer = "";
        lpFilePart = "";

        if (lpPath == null)
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager");
            object safeProcessSearchModeObject = key.GetValue("SafeProcessSearchMode");
            if (safeProcessSearchModeObject != null)
            {
                int safeProcessSearchMode = (int)safeProcessSearchModeObject;
                if (safeProcessSearchMode == 1)
                {
                    // When the value of this registry key is set to "1", 
                    // SearchPath first searches the folders that are specified in the system path, 
                    // and then searches the current working folder. 
                    pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[] { Path.PathSeparator }, StringSplitOptions.None));
                    pathsToSearch.Add(currentWorkingFolder);
                }
                else 
                {
                    // When the value of this registry entry is set to "0", 
                    // the computer first searches the current working folder, 
                    // and then searches the folders that are specified in the system path. 
                    // The system default value for this registry key is "0".
                    pathsToSearch.Add(currentWorkingFolder);
                    pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[] { Path.PathSeparator }, StringSplitOptions.None));
                }
            }
            else
            {
                // Default 0 case
                pathsToSearch.Add(currentWorkingFolder);
                pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[] { Path.PathSeparator }, StringSplitOptions.None));
            }
        }
        else
        {
            // Path was provided, use it
            pathsToSearch.Add(lpPath);
        }

        FileInfo foundFile = SearchPath(pathsToSearch, lpExtension, lpFileName);
        if (foundFile!= null)
        {
            lpBuffer = Path.Combine(foundFile.DirectoryName, foundFile.Name);
            lpFilePart = foundFile.Name;

        }

        return lpBuffer.Length;
    }

    private static FileInfo SearchPath(List<string> paths, string extension, string fileNamePart)
    {
        foreach (string path in paths)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            var fileInfo = dir.GetFiles().Where(file => file.Extension == extension && file.Name.Contains(fileNamePart));
            if (fileInfo.Any())
                return fileInfo.First();
        }
        return null;
    }
问题回答

Not really, unless you count re-implementing the entire logic of the function in C# yourself which would be a waste of time, IMO, when a couple of lines of P/Invoke would do it just as well.

You can use DirectoryInfo.GetFiles(String searchPattern, SearchOption searchOption). To get all of the *.exe files in a directory including subdirectories, you could use:

DirectoryInfo di = new DirectoryInfo("c:	emp");
var files = di.GetFiles("*.exe", SearchOption.AllDirectories);

Take a look at the MSDN documentation at http://msdn.microsoft.com/en-us/library/ms143327.aspx





相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签